From 55fc8b91e4563ea562128e13b1d681f5ce262f3a Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:44:24 +0800 Subject: [PATCH] fix(ci): preserve recorded npm resolution during vendor rescoping --- scripts/rescope-vendor.spec.ts | 24 ++++++++++++++++++------ scripts/rescope-vendor.ts | 12 +++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/scripts/rescope-vendor.spec.ts b/scripts/rescope-vendor.spec.ts index 563be68dfa..f05658ce64 100644 --- a/scripts/rescope-vendor.spec.ts +++ b/scripts/rescope-vendor.spec.ts @@ -1,15 +1,27 @@ -/** - * Acceptance-path coverage for the rescope codemod's exact-edit classifier: a - * duplicated insertion — what a non-idempotent apply produces — must be - * rejected rather than applied again. - */ +/** Recorded npm evidence stays intact while authored files and exact edits remain checked. */ import { describe, expect, it } from 'vitest' -import { exactEditState } from './rescope-vendor.ts' +import { exactEditState, isRescopeExcluded } from './rescope-vendor.ts' const ANCHOR = '\n## Sync procedure' const INSERTED = `\n15. **rescope**: one log entry.\n${ANCHOR}` +describe('rescope file selection', () => { + it('preserves the recorded npm resolution', () => { + expect(isRescopeExcluded('scripts/dependency-catalog/package-lock.json')).toBe(true) + }) + + it.each([ + 'scripts/dependency-catalog/package.json', + 'scripts/dependency-catalog/source.ts', + 'scripts/other/package-lock.json', + 'packages/example/src/index.ts', + 'packages/example/package.json', + ])('keeps %s subject to upstream package-name checks', (file) => { + expect(isRescopeExcluded(file)).toBe(false) + }) +}) + describe('exactEditState', () => { it('classifies an insertion by its target form, so a duplicate is invalid', () => { expect(exactEditState(`log\n${ANCHOR}\n`, ANCHOR, INSERTED, 1)).toBe('pending') diff --git a/scripts/rescope-vendor.ts b/scripts/rescope-vendor.ts index 1e03a9fa9d..dd845381cb 100644 --- a/scripts/rescope-vendor.ts +++ b/scripts/rescope-vendor.ts @@ -419,8 +419,12 @@ const VENDORED_LIBRARY = /^@deepseek-ai\\/(cosmokit|schemastery)(\\/|$)/ })), ] -/** Files the rescope must never rewrite. */ -function excluded(file: string): boolean { +/** + * Identify files whose recorded content must remain outside the rescope pass. + * @param file - Repository-relative path with forward slash separators. + * @returns Whether the codemod must preserve the file without scanning its tokens. + */ +export function isRescopeExcluded(file: string): boolean { if (file === 'scripts/rescope-vendor.ts') return true // the mapping itself if (file.startsWith('.agents/notes/')) return true // notes record what was true when written // Recorded model payloads quote documentation verbatim, so they must mirror the @@ -430,6 +434,8 @@ function excluded(file: string): boolean { if (file === 'docs/rescope.md' || file === 'docs/rescope.zh.md') return true if (file.endsWith('.i18n.yaml')) return true // blob-hash records, re-recorded by the pairing gate if (file === 'pnpm-lock.yaml') return true // regenerated by pnpm install + // Raw npm registry resolution; only gen-dependency-catalog --refresh replaces this evidence. + if (file === 'scripts/dependency-catalog/package-lock.json') return true if (/^vendor\/[^/]+\/(README\.md|LICENSE)$/.test(file)) return true // upstream files kept verbatim return !EXTENSIONS.some(extension => file.endsWith(extension)) } @@ -558,7 +564,7 @@ function main(): void { const all = patterns(reverse) const files = execFileSync('git', ['ls-files', '-z'], { cwd: root, encoding: 'utf8' }) .split('\0') - .filter(file => file !== '' && !excluded(file)) + .filter(file => file !== '' && !isRescopeExcluded(file)) const counts = new Map() const failures: string[] = []