spine-framework 0.5.0-rc.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -221,6 +221,29 @@ function getSourceCommit(root: string, manifestRel: string): string | null {
|
|
|
221
221
|
}
|
|
222
222
|
// CIL[END stable_id="~/scripts/checksum-manifest.mts:getSourceCommit:function"]
|
|
223
223
|
|
|
224
|
+
// CIL[BEGIN stable_id="~/scripts/checksum-manifest.mts:gitTrackedFiles:function" type="function" identity="gitTrackedFiles" parent="~/scripts/checksum-manifest.mts"]
|
|
225
|
+
// CIL[DOC-MACRO purpose="Resolve the set of git-index file paths for manifest filtering"]
|
|
226
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Run git ls-files -z at root and return its paths as a Set; null when git/index is unavailable or empty"]
|
|
227
|
+
// CIL[DOC-CONTEXT module="spine-integrity" layer="build" related_files="scripts/checksum-manifest.mts,scripts/verify-manifest.mts"]
|
|
228
|
+
// CIL[DOC-CONTRACT inputs="root: project root" outputs="Set of POSIX rel paths or null" errors="returns null when git is missing, root is not a repo, or the index is empty" side_effects="spawns a git subprocess"]
|
|
229
|
+
// CIL[DOC-MICRO logic_summary="The index (not the worktree) defines what a fresh clone will contain — ignored and unstaged-new files are absent" notable_decisions="empty index returns null so a bootstrap repo with no commits still produces a manifest"]
|
|
230
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
231
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
232
|
+
export function gitTrackedFiles(root: string): Set<string> | null {
|
|
233
|
+
try {
|
|
234
|
+
const out = execFileSync('git', ['ls-files', '-z', '--cached'], {
|
|
235
|
+
cwd: root,
|
|
236
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
237
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
238
|
+
})
|
|
239
|
+
const rels = out.toString('utf8').split('\0').filter(Boolean)
|
|
240
|
+
return rels.length > 0 ? new Set(rels) : null
|
|
241
|
+
} catch {
|
|
242
|
+
return null
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// CIL[END stable_id="~/scripts/checksum-manifest.mts:gitTrackedFiles:function"]
|
|
246
|
+
|
|
224
247
|
// CIL[BEGIN stable_id="~/scripts/checksum-manifest.mts:getFrameworkVersion:function" type="function" identity="getFrameworkVersion" parent="~/scripts/checksum-manifest.mts"]
|
|
225
248
|
// CIL[DOC-MACRO purpose="Resolve framework_version from package.json"]
|
|
226
249
|
// CIL[DOC-RESPONSIBILITY responsibility="Read <root>/package.json and return its version field; null when unreadable"]
|
|
@@ -261,7 +284,7 @@ export function computeTreeDigest(files: ReadonlyArray<readonly [string, string]
|
|
|
261
284
|
// CIL[DOC-RESPONSIBILITY responsibility="Validate argv, build the manifest object, serialize with sorted keys and LF endings, print a summary"]
|
|
262
285
|
// CIL[DOC-CONTEXT module="spine-integrity" layer="build" related_files="scripts/build-manifest.sh,package.json"]
|
|
263
286
|
// CIL[DOC-CONTRACT inputs="argv: <root> <output> [--include-dir <d>...]" outputs="exit 0 with manifest written" errors="exit 2 usage error; exit 1 on fs/git failures" side_effects="writes <output>, stdout summary"]
|
|
264
|
-
// CIL[DOC-MICRO logic_summary="frozen is always true on generated manifests; node/npm baselines are stamped from the plan G baseline (node >=22.13.0, npm >=10.0.0)" notable_decisions="no timestamp — determinism is verified by running the generator twice and diffing"]
|
|
287
|
+
// CIL[DOC-MICRO logic_summary="frozen is always true on generated manifests; node/npm baselines are stamped from the plan G baseline (node >=22.13.0, npm >=10.0.0); collected entries are filtered to git-index files so ignored/untracked scratch files can never produce MISSING failures on fresh clones" notable_decisions="no timestamp — determinism is verified by running the generator twice and diffing; filtering happens in main only because export-standalone shares collectProtectedFiles on a pre-commit output tree"]
|
|
265
288
|
// CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
266
289
|
// CIL[DOC-STABILITY stability="stable"]
|
|
267
290
|
function main(): void {
|
|
@@ -312,7 +335,11 @@ function main(): void {
|
|
|
312
335
|
const manifestRel = path.relative(root, output).split(path.sep).join('/')
|
|
313
336
|
const excludeRels = new Set<string>([manifestRel])
|
|
314
337
|
|
|
315
|
-
const
|
|
338
|
+
const tracked = gitTrackedFiles(root)
|
|
339
|
+
const collected = collectProtectedFiles(root, extraDirs, excludeRels)
|
|
340
|
+
const entries = tracked === null
|
|
341
|
+
? collected
|
|
342
|
+
: collected.filter((entry) => tracked.has(entry.rel))
|
|
316
343
|
const pairs: Array<readonly [string, string]> = entries.map(
|
|
317
344
|
(entry) => [entry.rel, hashEntry(entry)] as const,
|
|
318
345
|
)
|
|
@@ -333,6 +360,9 @@ function main(): void {
|
|
|
333
360
|
|
|
334
361
|
fs.writeFileSync(output, JSON.stringify(manifest, null, 2) + '\n', 'utf8')
|
|
335
362
|
|
|
363
|
+
if (tracked !== null && collected.length !== entries.length) {
|
|
364
|
+
console.log(` untracked files skipped: ${collected.length - entries.length}`)
|
|
365
|
+
}
|
|
336
366
|
console.log(` manifest: ${manifestRel}`)
|
|
337
367
|
console.log(` files hashed: ${pairs.length}`)
|
|
338
368
|
console.log(` tree_digest: ${manifest.tree_digest}`)
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
PROTECTED_DIRS,
|
|
19
19
|
collectProtectedFiles,
|
|
20
20
|
computeTreeDigest,
|
|
21
|
+
gitTrackedFiles,
|
|
21
22
|
hashEntry,
|
|
22
23
|
topLevelDir,
|
|
23
24
|
} from './checksum-manifest.mts'
|
|
@@ -192,7 +193,7 @@ function verifyListedFiles(rootAbs: string, files: Record<string, string>): Fail
|
|
|
192
193
|
// CIL[DOC-RESPONSIBILITY responsibility="Enumerate the same trees the generator covered (defaults plus any top-level dirs present in the manifest) and flag anything not in the files map"]
|
|
193
194
|
// CIL[DOC-CONTEXT module="spine-integrity" layer="build" related_files="scripts/checksum-manifest.mts"]
|
|
194
195
|
// CIL[DOC-CONTRACT inputs="rootAbs, manifestRel, files map" outputs="Failure[]" errors="none" side_effects="reads filesystem"]
|
|
195
|
-
// CIL[DOC-MICRO logic_summary="Shared collectProtectedFiles keeps exclusion rules identical between generate and verify; the manifest's own path is excluded" notable_decisions="manifest top-level dirs are unioned in so --include-dir manifests verify without extra flags"]
|
|
196
|
+
// CIL[DOC-MICRO logic_summary="Shared collectProtectedFiles keeps exclusion rules identical between generate and verify; the manifest's own path is excluded; results are filtered to git-index files so ignored/untracked scratch files cannot flag EXTRA" notable_decisions="manifest top-level dirs are unioned in so --include-dir manifests verify without extra flags; tracked-filter mirrors the generator — absent from a fresh clone means absent from the manifest"]
|
|
196
197
|
// CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
197
198
|
// CIL[DOC-STABILITY stability="stable"]
|
|
198
199
|
function findExtraFiles(rootAbs: string, manifestRel: string, files: Record<string, string>): Failure[] {
|
|
@@ -203,7 +204,10 @@ function findExtraFiles(rootAbs: string, manifestRel: string, files: Record<stri
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
const extraDirs = [...trees].filter((d) => !PROTECTED_DIRS.includes(d))
|
|
206
|
-
const
|
|
207
|
+
const tracked = gitTrackedFiles(rootAbs)
|
|
208
|
+
const present = collectProtectedFiles(rootAbs, extraDirs, new Set([manifestRel])).filter(
|
|
209
|
+
(entry) => tracked === null || tracked.has(entry.rel),
|
|
210
|
+
)
|
|
207
211
|
|
|
208
212
|
const failures: Failure[] = []
|
|
209
213
|
for (const entry of present) {
|