From 8d7e0b8d39507a1ac7e94cbe7570362dd6987701 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 02:57:59 +0800 Subject: [PATCH 1/8] Add one-time ignored path identity updater --- ...one-time-preserve-ignored-path-identity.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/scripts/one-time-preserve-ignored-path-identity.py diff --git a/.github/scripts/one-time-preserve-ignored-path-identity.py b/.github/scripts/one-time-preserve-ignored-path-identity.py new file mode 100644 index 0000000..204e0c3 --- /dev/null +++ b/.github/scripts/one-time-preserve-ignored-path-identity.py @@ -0,0 +1,66 @@ +from pathlib import Path + +selection = Path("src/selection-workspace.ts") +text = selection.read_text() +old_import = 'import type { DiffSelection } from "./types.js";\n' +new_import = old_import + 'import { normalizeRepoPath } from "./util.js";\n' +if old_import not in text: + raise SystemExit("selection-workspace import anchor not found") +text = text.replace(old_import, new_import, 1) +old_parse = ' return [...new Set(result.stdout.split("\\0").filter(Boolean).map((file) => file.replaceAll("\\\\", "/")))].sort();\n' +new_parse = ' return [...new Set(result.stdout.split("\\0").filter(Boolean).map(normalizeRepoPath))].sort();\n' +if old_parse not in text: + raise SystemExit("ignoredFiles parser anchor not found") +text = text.replace(old_parse, new_parse, 1) +selection.write_text(text) + +tests = Path("tests/selection-workspace.test.ts") +text = tests.read_text() +anchor = 'test("ignored dependency directories remain allowed as execution environment", async (context) => {\n' +if anchor not in text: + raise SystemExit("selection-workspace test anchor not found") +regression = r'''test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => { + const root = await initializeRepository({ + ".gitignore": "coverage*\n", + "package.json": JSON.stringify({ name: "ignored-path-identity", private: true, type: "module", scripts: { test: "node --test" } }, null, 2), + "src/value.js": "export const value = 1;\n", + "test/value.test.js": "import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { value } from '../src/value.js'; test('value', () => { assert.equal(value, 2); assert.equal(readFileSync('coverage\\\\proof.lcov', 'utf8').trim(), 'allow'); });\n", + }); + context.after(() => rm(root, { recursive: true, force: true })); + const base = git(root, "rev-parse", "HEAD").trim(); + const target = await commitChange(root, "export const value = 2;\n", "selected change"); + await writeFiles(root, { + "coverage/proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", + "coverage\\proof.lcov": "allow\n", + }); + + await assert.rejects( + analyzeRepository({ + repo: root, + base, + runChecks: true, + coverageLcov: "coverage/proof.lcov", + coverageCommit: target, + timeoutMs: 20_000, + }), + (error: unknown) => { + assert.ok(error instanceof Error); + assert.match(error.message, /ignored filesystem input.*visible to repository execution/); + assert.ok(error.message.includes("coverage\\proof.lcov")); + return true; + }, + ); +}); + +''' +text = text.replace(anchor, regression + anchor, 1) +tests.write_text(text) + +changelog = Path("CHANGELOG.md") +text = changelog.read_text() +anchor = "### Fixed\n\n" +if anchor not in text: + raise SystemExit("CHANGELOG fixed section not found") +item = "- Preserved ignored-file path identity across platforms when enforcing immutable workspace alignment. POSIX filenames containing literal backslashes are no longer rewritten as directory separators, so a distinct ignored runtime input such as `coverage\\proof.lcov` cannot alias an explicitly allowed `coverage/proof.lcov` data artifact and bypass the pre-execution fail-closed gate.\n" +text = text.replace(anchor, anchor + item, 1) +changelog.write_text(text) From cbe4e25e249606f464600dcd0c1f26711cfc185a Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 02:58:09 +0800 Subject: [PATCH 2/8] Add one-time ignored path identity workflow --- ...ne-time-preserve-ignored-path-identity.yml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/one-time-preserve-ignored-path-identity.yml diff --git a/.github/workflows/one-time-preserve-ignored-path-identity.yml b/.github/workflows/one-time-preserve-ignored-path-identity.yml new file mode 100644 index 0000000..ced393b --- /dev/null +++ b/.github/workflows/one-time-preserve-ignored-path-identity.yml @@ -0,0 +1,39 @@ +name: One-time preserve ignored path identity + +on: + push: + branches: + - fix/preserve-ignored-path-identity + paths: + - .github/workflows/one-time-preserve-ignored-path-identity.yml + +permissions: + contents: write + +jobs: + update: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + ref: fix/preserve-ignored-path-identity + - uses: actions/setup-node@v7 + with: + node-version: 22 + cache: npm + - run: npm ci + - name: Apply path-identity fix and regression + run: python3 .github/scripts/one-time-preserve-ignored-path-identity.py + - name: Run full tests + run: npm test + - name: Clean rebuild tracked dist + run: npm run clean && npm run build + - name: Validate diff + run: git diff --check + - name: Commit generated update + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add CHANGELOG.md src/selection-workspace.ts tests/selection-workspace.test.ts dist + git commit -m "Preserve ignored path identity" + git push origin HEAD:fix/preserve-ignored-path-identity From 24dfe3cbf608f849db715765e288eb95f079c657 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 18:58:49 +0000 Subject: [PATCH 3/8] Preserve ignored path identity --- CHANGELOG.md | 1 + dist/selection-workspace.d.ts.map | 2 +- dist/selection-workspace.js | 3 ++- dist/selection-workspace.js.map | 2 +- src/selection-workspace.ts | 3 ++- tests/selection-workspace.test.ts | 33 +++++++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f94c79..18caf9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes are documented here. This project follows Semantic Versionin ### Fixed +- Preserved ignored-file path identity across platforms when enforcing immutable workspace alignment. POSIX filenames containing literal backslashes are no longer rewritten as directory separators, so a distinct ignored runtime input such as `coverage\proof.lcov` cannot alias an explicitly allowed `coverage/proof.lcov` data artifact and bypass the pre-execution fail-closed gate. - Failed closed on unattributed targeted-runner process failures even when another qualified batch target is unavailable. An unavailable target can no longer act as a sink that lets unrelated observed passes survive an ambiguous process-level failure; only explicitly failed targets retain localized failure attribution. - Failed closed on deletion-only zero-context hunks when attributing current changed symbols and call references. Git represents a deletion-only hunk with a zero-length new-side range anchored to a neighboring current line; ProofDiff now reconciles reconstructed current-line spans with Git numstat additions before treating those anchors as changed current code. - Preserved precise changed-line hunks across renames by scoping per-file Git diffs to both the previous and current path. This prevents a rename with content edits from being reinterpreted as a whole-file addition and overstating changed-line or call-reference evidence. diff --git a/dist/selection-workspace.d.ts.map b/dist/selection-workspace.d.ts.map index d907578..a86b5f5 100644 --- a/dist/selection-workspace.d.ts.map +++ b/dist/selection-workspace.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"selection-workspace.d.ts","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA2IhD,MAAM,WAAW,yBAAyB;IACxC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCpJ"} \ No newline at end of file +{"version":3,"file":"selection-workspace.d.ts","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4IhD,MAAM,WAAW,yBAAyB;IACxC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAsB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCpJ"} \ No newline at end of file diff --git a/dist/selection-workspace.js b/dist/selection-workspace.js index cfd413a..9a23ca5 100644 --- a/dist/selection-workspace.js +++ b/dist/selection-workspace.js @@ -1,6 +1,7 @@ import path from "node:path"; import { diffTargetCommit, GitError, gitNullDevice, listUntrackedFiles, resolveRevisionCommit } from "./git.js"; import { runProcess, safeExecutablePath } from "./process.js"; +import { normalizeRepoPath } from "./util.js"; const ROOT_DISCOVERY_METADATA = new Set([ "package.json", "tsconfig.json", @@ -108,7 +109,7 @@ async function ignoredFiles(root, pathspecs, exclusions) { const message = result.stderr.trim() || result.error || `git ls-files exited with ${String(result.exitCode)}`; throw new GitError(`Could not inspect ignored immutable-workspace inputs: ${message}`); } - return [...new Set(result.stdout.split("\0").filter(Boolean).map((file) => file.replaceAll("\\", "/")))].sort(); + return [...new Set(result.stdout.split("\0").filter(Boolean).map(normalizeRepoPath))].sort(); } function isPythonDiscoveryPath(repoPath) { const segments = repoPath.split("/"); diff --git a/dist/selection-workspace.js.map b/dist/selection-workspace.js.map index 8650b0a..27dc2cc 100644 --- a/dist/selection-workspace.js.map +++ b/dist/selection-workspace.js.map @@ -1 +1 @@ -{"version":3,"file":"selection-workspace.js","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"selection-workspace.js","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/selection-workspace.ts b/src/selection-workspace.ts index 145b443..5117629 100644 --- a/src/selection-workspace.ts +++ b/src/selection-workspace.ts @@ -2,6 +2,7 @@ import path from "node:path"; import { diffTargetCommit, GitError, gitNullDevice, listUntrackedFiles, resolveRevisionCommit } from "./git.js"; import { runProcess, safeExecutablePath, type ProcessResult } from "./process.js"; import type { DiffSelection } from "./types.js"; +import { normalizeRepoPath } from "./util.js"; const ROOT_DISCOVERY_METADATA = new Set([ "package.json", @@ -112,7 +113,7 @@ async function ignoredFiles(root: string, pathspecs: string[], exclusions: strin const message = result.stderr.trim() || result.error || `git ls-files exited with ${String(result.exitCode)}`; throw new GitError(`Could not inspect ignored immutable-workspace inputs: ${message}`); } - return [...new Set(result.stdout.split("\0").filter(Boolean).map((file) => file.replaceAll("\\", "/")))].sort(); + return [...new Set(result.stdout.split("\0").filter(Boolean).map(normalizeRepoPath))].sort(); } function isPythonDiscoveryPath(repoPath: string): boolean { diff --git a/tests/selection-workspace.test.ts b/tests/selection-workspace.test.ts index eefd04d..f51f711 100644 --- a/tests/selection-workspace.test.ts +++ b/tests/selection-workspace.test.ts @@ -94,6 +94,39 @@ test("ignored runtime-only inputs are allowed statically but rejected before rep ); }); +test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => { + const root = await initializeRepository({ + ".gitignore": "coverage*\n", + "package.json": JSON.stringify({ name: "ignored-path-identity", private: true, type: "module", scripts: { test: "node --test" } }, null, 2), + "src/value.js": "export const value = 1;\n", + "test/value.test.js": "import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { value } from '../src/value.js'; test('value', () => { assert.equal(value, 2); assert.equal(readFileSync('coverage\\\\proof.lcov', 'utf8').trim(), 'allow'); });\n", + }); + context.after(() => rm(root, { recursive: true, force: true })); + const base = git(root, "rev-parse", "HEAD").trim(); + const target = await commitChange(root, "export const value = 2;\n", "selected change"); + await writeFiles(root, { + "coverage/proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", + "coverage\\proof.lcov": "allow\n", + }); + + await assert.rejects( + analyzeRepository({ + repo: root, + base, + runChecks: true, + coverageLcov: "coverage/proof.lcov", + coverageCommit: target, + timeoutMs: 20_000, + }), + (error: unknown) => { + assert.ok(error instanceof Error); + assert.match(error.message, /ignored filesystem input.*visible to repository execution/); + assert.ok(error.message.includes("coverage\\proof.lcov")); + return true; + }, + ); +}); + test("ignored dependency directories remain allowed as execution environment", async (context) => { const root = await initializeRepository({ ".gitignore": "node_modules/\n", From ea5cecd6d7e8d0b63ed02f958d8b5dff472c918c Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 02:59:45 +0800 Subject: [PATCH 4/8] Extend one-time ignored path identity updater --- ...one-time-preserve-ignored-path-identity.py | 64 ++++++------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/.github/scripts/one-time-preserve-ignored-path-identity.py b/.github/scripts/one-time-preserve-ignored-path-identity.py index 204e0c3..4796719 100644 --- a/.github/scripts/one-time-preserve-ignored-path-identity.py +++ b/.github/scripts/one-time-preserve-ignored-path-identity.py @@ -2,65 +2,39 @@ selection = Path("src/selection-workspace.ts") text = selection.read_text() -old_import = 'import type { DiffSelection } from "./types.js";\n' -new_import = old_import + 'import { normalizeRepoPath } from "./util.js";\n' -if old_import not in text: - raise SystemExit("selection-workspace import anchor not found") -text = text.replace(old_import, new_import, 1) -old_parse = ' return [...new Set(result.stdout.split("\\0").filter(Boolean).map((file) => file.replaceAll("\\\\", "/")))].sort();\n' -new_parse = ' return [...new Set(result.stdout.split("\\0").filter(Boolean).map(normalizeRepoPath))].sort();\n' -if old_parse not in text: - raise SystemExit("ignoredFiles parser anchor not found") -text = text.replace(old_parse, new_parse, 1) -selection.write_text(text) +old = ' const normalized = relative.replaceAll("\\\\", "/");\n' +new = ' const normalized = normalizeRepoPath(relative);\n' +if old not in text: + raise SystemExit("repoLocalDataArtifact normalization anchor not found") +selection.write_text(text.replace(old, new, 1)) tests = Path("tests/selection-workspace.test.ts") text = tests.read_text() -anchor = 'test("ignored dependency directories remain allowed as execution environment", async (context) => {\n' +anchor = 'test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => {\n' if anchor not in text: - raise SystemExit("selection-workspace test anchor not found") -regression = r'''test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => { + raise SystemExit("selection-workspace regression anchor not found") +regression = r'''test("explicit POSIX data artifacts preserve literal backslashes in their own identity", { skip: process.platform === "win32" }, async (context) => { const root = await initializeRepository({ ".gitignore": "coverage*\n", - "package.json": JSON.stringify({ name: "ignored-path-identity", private: true, type: "module", scripts: { test: "node --test" } }, null, 2), "src/value.js": "export const value = 1;\n", - "test/value.test.js": "import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { value } from '../src/value.js'; test('value', () => { assert.equal(value, 2); assert.equal(readFileSync('coverage\\\\proof.lcov', 'utf8').trim(), 'allow'); });\n", }); context.after(() => rm(root, { recursive: true, force: true })); const base = git(root, "rev-parse", "HEAD").trim(); const target = await commitChange(root, "export const value = 2;\n", "selected change"); await writeFiles(root, { - "coverage/proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", - "coverage\\proof.lcov": "allow\n", + "coverage\\proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", }); - await assert.rejects( - analyzeRepository({ - repo: root, - base, - runChecks: true, - coverageLcov: "coverage/proof.lcov", - coverageCommit: target, - timeoutMs: 20_000, - }), - (error: unknown) => { - assert.ok(error instanceof Error); - assert.match(error.message, /ignored filesystem input.*visible to repository execution/); - assert.ok(error.message.includes("coverage\\proof.lcov")); - return true; - }, - ); + const report = await analyzeRepository({ + repo: root, + base, + runChecks: true, + coverageLcov: "coverage\\proof.lcov", + coverageCommit: target, + }); + assert.equal(report.coverage?.accepted, true); + assert.equal(report.coverage?.artifact, "coverage\\proof.lcov"); }); ''' -text = text.replace(anchor, regression + anchor, 1) -tests.write_text(text) - -changelog = Path("CHANGELOG.md") -text = changelog.read_text() -anchor = "### Fixed\n\n" -if anchor not in text: - raise SystemExit("CHANGELOG fixed section not found") -item = "- Preserved ignored-file path identity across platforms when enforcing immutable workspace alignment. POSIX filenames containing literal backslashes are no longer rewritten as directory separators, so a distinct ignored runtime input such as `coverage\\proof.lcov` cannot alias an explicitly allowed `coverage/proof.lcov` data artifact and bypass the pre-execution fail-closed gate.\n" -text = text.replace(anchor, anchor + item, 1) -changelog.write_text(text) +tests.write_text(text.replace(anchor, regression + anchor, 1)) From 1e54aebed1cfd3b999a14d124978fbc03df5a554 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 02:59:58 +0800 Subject: [PATCH 5/8] Rerun ignored path identity validation --- .../workflows/one-time-preserve-ignored-path-identity.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/one-time-preserve-ignored-path-identity.yml b/.github/workflows/one-time-preserve-ignored-path-identity.yml index ced393b..171f99d 100644 --- a/.github/workflows/one-time-preserve-ignored-path-identity.yml +++ b/.github/workflows/one-time-preserve-ignored-path-identity.yml @@ -1,4 +1,4 @@ -name: One-time preserve ignored path identity +name: One-time preserve ignored path identity v2 on: push: @@ -22,7 +22,7 @@ jobs: node-version: 22 cache: npm - run: npm ci - - name: Apply path-identity fix and regression + - name: Apply remaining path-identity fix and regression run: python3 .github/scripts/one-time-preserve-ignored-path-identity.py - name: Run full tests run: npm test @@ -35,5 +35,5 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add CHANGELOG.md src/selection-workspace.ts tests/selection-workspace.test.ts dist - git commit -m "Preserve ignored path identity" + git commit -m "Complete ignored path identity preservation" git push origin HEAD:fix/preserve-ignored-path-identity From f12ca077ce334e6f3b17bc2b0b5ffcfe744d9e15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:00:44 +0000 Subject: [PATCH 6/8] Complete ignored path identity preservation --- dist/selection-workspace.js | 2 +- dist/selection-workspace.js.map | 2 +- src/selection-workspace.ts | 2 +- tests/selection-workspace.test.ts | 23 +++++++++++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/dist/selection-workspace.js b/dist/selection-workspace.js index 9a23ca5..0ffd8f1 100644 --- a/dist/selection-workspace.js +++ b/dist/selection-workspace.js @@ -126,7 +126,7 @@ function repoLocalDataArtifact(root, artifact) { const relative = path.relative(root, absolute); if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) return null; - const normalized = relative.replaceAll("\\", "/"); + const normalized = normalizeRepoPath(relative); return isDiscoverySensitivePath(normalized) ? null : normalized; } function boundedDetail(files) { diff --git a/dist/selection-workspace.js.map b/dist/selection-workspace.js.map index 27dc2cc..a4a21bf 100644 --- a/dist/selection-workspace.js.map +++ b/dist/selection-workspace.js.map @@ -1 +1 @@ -{"version":3,"file":"selection-workspace.js","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"selection-workspace.js","sourceRoot":"","sources":["../src/selection-workspace.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAChH,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAsB,MAAM,cAAc,CAAC;AAElF,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IACtC,cAAc;IACd,eAAe;IACf,gBAAgB;IAChB,aAAa;IACb,cAAc;IACd,YAAY;IACZ,aAAa;IACb,SAAS;IACT,WAAW;CACZ,CAAC,CAAC;AACH,MAAM,uBAAuB,GAAG;IAC9B,GAAG,uBAAuB;IAC1B,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;CACvB,CAAC;AACF,MAAM,uCAAuC,GAAG,CAAC,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAClH,MAAM,iCAAiC,GAAG,CAAC,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE3F,SAAS,kBAAkB,CAAC,WAAqB;IAC/C,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;QACxC,kBAAkB,SAAS,KAAK;QAChC,qBAAqB,SAAS,KAAK;KACpC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,4BAA4B,GAAG,kBAAkB,CAAC,uCAAuC,CAAC,CAAC;AACjG,MAAM,4BAA4B,GAAG,kBAAkB,CAAC,iCAAiC,CAAC,CAAC;AAE3F,SAAS,cAAc;IACrB,MAAM,GAAG,GAAsB;QAC7B,IAAI,EAAE,kBAAkB,EAAE;QAC1B,mBAAmB,EAAE,GAAG;QACxB,iBAAiB,EAAE,aAAa,EAAE;QAClC,iBAAiB,EAAE,GAAG;QACtB,sBAAsB,EAAE,GAAG;QAC3B,mBAAmB,EAAE,GAAG;QACxB,SAAS,EAAE,KAAK;QAChB,kBAAkB,EAAE,GAAG;QACvB,MAAM,EAAE,GAAG;KACZ,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;QACpE,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY,EAAE,IAAc,EAAE,cAAc,GAAG,MAAM;IACzE,OAAO,MAAM,UAAU,CAAC,KAAK,EAAE;QAC7B,YAAY;QACZ,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,kBAAkB,aAAa,EAAE,EAAE;QACzC,IAAI,EAAE,gBAAgB;QACtB,IAAI,EAAE,wCAAwC;QAC9C,GAAG,IAAI;KACR,EAAE;QACD,GAAG,EAAE,IAAI;QACT,SAAS,EAAE,MAAM;QACjB,cAAc;QACd,GAAG,EAAE,cAAc,EAAE;KACtB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,wBAAwB,CAAC,IAAY,EAAE,MAAqB;IACzE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE;QAChC,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;QACf,yBAAyB;QACzB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI;KACL,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,QAAQ;QAAE,MAAM,IAAI,QAAQ,CAAC,sGAAsG,CAAC,CAAC;IAChJ,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,KAAK,IAAI,wBAAwB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC1G,MAAM,IAAI,QAAQ,CAAC,+DAA+D,OAAO,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,SAAmB,EAAE,UAAoB;IACjF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE;QAChC,UAAU;QACV,UAAU;QACV,WAAW;QACX,oBAAoB;QACpB,IAAI;QACJ,IAAI;QACJ,GAAG,SAAS;QACZ,GAAG,UAAU;KACd,EAAE,OAAO,CAAC,CAAC;IACZ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,QAAQ,CAAC,8HAA8H,CAAC,CAAC;IACrJ,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,KAAK,IAAI,4BAA4B,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9G,MAAM,IAAI,QAAQ,CAAC,yDAAyD,OAAO,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/F,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,uCAAuC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrH,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAgB;IAChD,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAC/G,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY,EAAE,QAAgB;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACrF,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;AAClE,CAAC;AAED,SAAS,aAAa,CAAC,KAAe;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC9C,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAChF,CAAC;AAOD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CAAC,IAAY,EAAE,SAAwB,EAAE,UAAqC,EAAE;IACnI,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO;IAE9C,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5D,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,IAAI;YAAE,MAAM,IAAI,QAAQ,CAAC,wDAAwD,SAAS,CAAC,IAAI,QAAQ,CAAC,CAAC;QACxH,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAAC,gBAAgB,SAAS,CAAC,IAAI,wBAAwB,MAAM,iCAAiC,IAAI,gPAAgP,CAAC,CAAC;QACxW,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAsB,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC;IAC5L,MAAM,SAAS,GAAG,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACjG,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAAC,gBAAgB,SAAS,CAAC,IAAI,+DAA+D,SAAS,CAAC,MAAM,8BAA8B,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC,SAAS,CAAC,8KAA8K,CAAC,CAAC;IAC9Y,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,yBAAyB;QACrD,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,4BAA4B,CAAC;QAC/D,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,uBAAuB,EAAE,4BAA4B,CAAC,CAAC;IACpF,MAAM,mBAAmB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC7F,MAAM,IAAI,QAAQ,CAAC,gBAAgB,SAAS,CAAC,IAAI,mDAAmD,mBAAmB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,eAAe,KAAK,yCAAyC,aAAa,CAAC,mBAAmB,CAAC,uJAAuJ,CAAC,CAAC;IACzY,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAClG,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,0BAA0B,CAAC;QAC/F,MAAM,IAAI,QAAQ,CAAC,gBAAgB,SAAS,CAAC,IAAI,sEAAsE,QAAQ,gLAAgL,QAAQ,0CAA0C,CAAC,CAAC;IACrW,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/src/selection-workspace.ts b/src/selection-workspace.ts index 5117629..0fe75bb 100644 --- a/src/selection-workspace.ts +++ b/src/selection-workspace.ts @@ -131,7 +131,7 @@ function repoLocalDataArtifact(root: string, artifact: string): string | null { const absolute = path.isAbsolute(artifact) ? path.normalize(artifact) : path.resolve(root, artifact); const relative = path.relative(root, absolute); if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) return null; - const normalized = relative.replaceAll("\\", "/"); + const normalized = normalizeRepoPath(relative); return isDiscoverySensitivePath(normalized) ? null : normalized; } diff --git a/tests/selection-workspace.test.ts b/tests/selection-workspace.test.ts index f51f711..6598b2a 100644 --- a/tests/selection-workspace.test.ts +++ b/tests/selection-workspace.test.ts @@ -94,6 +94,29 @@ test("ignored runtime-only inputs are allowed statically but rejected before rep ); }); +test("explicit POSIX data artifacts preserve literal backslashes in their own identity", { skip: process.platform === "win32" }, async (context) => { + const root = await initializeRepository({ + ".gitignore": "coverage*\n", + "src/value.js": "export const value = 1;\n", + }); + context.after(() => rm(root, { recursive: true, force: true })); + const base = git(root, "rev-parse", "HEAD").trim(); + const target = await commitChange(root, "export const value = 2;\n", "selected change"); + await writeFiles(root, { + "coverage\\proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", + }); + + const report = await analyzeRepository({ + repo: root, + base, + runChecks: true, + coverageLcov: "coverage\\proof.lcov", + coverageCommit: target, + }); + assert.equal(report.coverage?.accepted, true); + assert.equal(report.coverage?.artifact, "coverage\\proof.lcov"); +}); + test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => { const root = await initializeRepository({ ".gitignore": "coverage*\n", From 840d5b7c10c74644fbaeadce21f0e845d1ee52c1 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 03:01:08 +0800 Subject: [PATCH 7/8] Remove one-time ignored path identity updater --- ...one-time-preserve-ignored-path-identity.py | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 .github/scripts/one-time-preserve-ignored-path-identity.py diff --git a/.github/scripts/one-time-preserve-ignored-path-identity.py b/.github/scripts/one-time-preserve-ignored-path-identity.py deleted file mode 100644 index 4796719..0000000 --- a/.github/scripts/one-time-preserve-ignored-path-identity.py +++ /dev/null @@ -1,40 +0,0 @@ -from pathlib import Path - -selection = Path("src/selection-workspace.ts") -text = selection.read_text() -old = ' const normalized = relative.replaceAll("\\\\", "/");\n' -new = ' const normalized = normalizeRepoPath(relative);\n' -if old not in text: - raise SystemExit("repoLocalDataArtifact normalization anchor not found") -selection.write_text(text.replace(old, new, 1)) - -tests = Path("tests/selection-workspace.test.ts") -text = tests.read_text() -anchor = 'test("ignored POSIX paths preserve literal backslashes instead of aliasing allowed artifacts", { skip: process.platform === "win32" }, async (context) => {\n' -if anchor not in text: - raise SystemExit("selection-workspace regression anchor not found") -regression = r'''test("explicit POSIX data artifacts preserve literal backslashes in their own identity", { skip: process.platform === "win32" }, async (context) => { - const root = await initializeRepository({ - ".gitignore": "coverage*\n", - "src/value.js": "export const value = 1;\n", - }); - context.after(() => rm(root, { recursive: true, force: true })); - const base = git(root, "rev-parse", "HEAD").trim(); - const target = await commitChange(root, "export const value = 2;\n", "selected change"); - await writeFiles(root, { - "coverage\\proof.lcov": "TN:\nSF:src/value.js\nDA:1,1\nend_of_record\n", - }); - - const report = await analyzeRepository({ - repo: root, - base, - runChecks: true, - coverageLcov: "coverage\\proof.lcov", - coverageCommit: target, - }); - assert.equal(report.coverage?.accepted, true); - assert.equal(report.coverage?.artifact, "coverage\\proof.lcov"); -}); - -''' -tests.write_text(text.replace(anchor, regression + anchor, 1)) From 5ffed014a580739b523ea69106cc91e9583fc0a9 Mon Sep 17 00:00:00 2001 From: Felix Date: Sun, 16 Aug 2026 03:01:16 +0800 Subject: [PATCH 8/8] Remove one-time ignored path identity workflow --- ...ne-time-preserve-ignored-path-identity.yml | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 .github/workflows/one-time-preserve-ignored-path-identity.yml diff --git a/.github/workflows/one-time-preserve-ignored-path-identity.yml b/.github/workflows/one-time-preserve-ignored-path-identity.yml deleted file mode 100644 index 171f99d..0000000 --- a/.github/workflows/one-time-preserve-ignored-path-identity.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: One-time preserve ignored path identity v2 - -on: - push: - branches: - - fix/preserve-ignored-path-identity - paths: - - .github/workflows/one-time-preserve-ignored-path-identity.yml - -permissions: - contents: write - -jobs: - update: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - with: - ref: fix/preserve-ignored-path-identity - - uses: actions/setup-node@v7 - with: - node-version: 22 - cache: npm - - run: npm ci - - name: Apply remaining path-identity fix and regression - run: python3 .github/scripts/one-time-preserve-ignored-path-identity.py - - name: Run full tests - run: npm test - - name: Clean rebuild tracked dist - run: npm run clean && npm run build - - name: Validate diff - run: git diff --check - - name: Commit generated update - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add CHANGELOG.md src/selection-workspace.ts tests/selection-workspace.test.ts dist - git commit -m "Complete ignored path identity preservation" - git push origin HEAD:fix/preserve-ignored-path-identity