forked from abhigyanpatwari/GitNexus
-
Notifications
You must be signed in to change notification settings - Fork 0
test(reconciliation): validate final internal release head #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
100yenadmin
wants to merge
16
commits into
reconcile/r19c-community-order
Choose a base branch
from
reconcile/r21-final-validation
base: reconcile/r19c-community-order
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
9e1d4e3
test(reconciliation): add disposable scale canary
889d344
test(reconciliation): isolate canary environment
df99e1e
fix(scope): stabilize graph lookup collisions
69a1ef5
fix(scan): canonicalize repository path order
e554197
fix(imports): stabilize suffix lookup without reordering phases
7f081ff
test(imports): preserve caller file order
6737075
test(reconciliation): harden canary recovery evidence
f996ac2
test(reconciliation): close canary safety gaps
fed1f3c
test(incremental): compare every recovery boundary
2317a78
test(incremental): make recovery proof hermetic
c1c030e
test(incremental): harden recovery oracle
c231cbf
test(incremental): validate staged extensions
ca65489
fix(scan): canonicalize traversal without order-sensitive Rust binding
26d740e
fix(php): resolve function imports by declaring file
90c8383
test(bench): rebaseline PHP import capture shape
59ad8d9
fix(php): resolve symbol-named PSR-4 imports
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| const PORTABLE_KEYS = [ | ||
| 'PATH', | ||
| 'SHELL', | ||
| 'TMPDIR', | ||
| 'TMP', | ||
| 'TEMP', | ||
| 'LANG', | ||
| 'LC_ALL', | ||
| 'LC_CTYPE', | ||
| 'TZ', | ||
| ]; | ||
|
|
||
| const WINDOWS_KEYS = ['SystemRoot', 'WINDIR', 'COMSPEC', 'PATHEXT']; | ||
|
|
||
| export const createSanitizedEnvironment = (source, { home, platform = process.platform } = {}) => { | ||
| if (!home) throw new Error('sanitized environment requires an isolated home'); | ||
|
|
||
| const result = {}; | ||
| const allowedKeys = platform === 'win32' ? [...PORTABLE_KEYS, ...WINDOWS_KEYS] : PORTABLE_KEYS; | ||
| for (const key of allowedKeys) { | ||
| if (typeof source[key] === 'string') result[key] = source[key]; | ||
| } | ||
|
|
||
| return { | ||
| ...result, | ||
| HOME: home, | ||
| USERPROFILE: home, | ||
| CI: '1', | ||
| GIT_TERMINAL_PROMPT: '0', | ||
| GIT_CONFIG_NOSYSTEM: '1', | ||
| GIT_CONFIG_GLOBAL: platform === 'win32' ? 'NUL' : '/dev/null', | ||
| }; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,297 @@ | ||
| import { spawn, spawnSync } from 'node:child_process'; | ||
| import crypto from 'node:crypto'; | ||
| import fs from 'node:fs'; | ||
| import path from 'node:path'; | ||
|
|
||
| const SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 }; | ||
|
|
||
| const codePointCompare = (left, right) => (left < right ? -1 : left > right ? 1 : 0); | ||
|
|
||
| const assertDirectory = (directory) => { | ||
| const stat = fs.lstatSync(directory); | ||
| if (stat.isSymbolicLink()) { | ||
| throw new Error(`refusing symbolic link in canary evidence path: ${directory}`); | ||
| } | ||
| if (!stat.isDirectory()) { | ||
| throw new Error(`expected canary evidence directory: ${directory}`); | ||
| } | ||
| }; | ||
|
|
||
| const assertTreeHasNoSymlinks = (directory) => { | ||
| assertDirectory(directory); | ||
| for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { | ||
| const entryPath = path.join(directory, entry.name); | ||
| if (entry.isSymbolicLink()) { | ||
| throw new Error(`refusing symbolic link in canary evidence path: ${entryPath}`); | ||
| } | ||
| if (entry.isDirectory()) assertTreeHasNoSymlinks(entryPath); | ||
| } | ||
| }; | ||
|
|
||
| export const prepareEvidenceLayout = ({ evidence, commandDir, snapshotDir, home }) => { | ||
| fs.mkdirSync(evidence, { recursive: true }); | ||
| assertDirectory(evidence); | ||
| for (const directory of [commandDir, snapshotDir, home]) { | ||
| fs.mkdirSync(directory, { recursive: true }); | ||
| assertDirectory(directory); | ||
| } | ||
| assertTreeHasNoSymlinks(evidence); | ||
| }; | ||
|
|
||
| export const writeJsonAtomic = (filePath, value) => { | ||
| assertDirectory(path.dirname(filePath)); | ||
| const temporaryPath = path.join( | ||
| path.dirname(filePath), | ||
| `.${path.basename(filePath)}.${process.pid}.${crypto.randomUUID()}.tmp`, | ||
| ); | ||
| try { | ||
| fs.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, { | ||
| encoding: 'utf8', | ||
| flag: 'wx', | ||
| mode: 0o600, | ||
| }); | ||
| fs.renameSync(temporaryPath, filePath); | ||
| } finally { | ||
| fs.rmSync(temporaryPath, { force: true }); | ||
| } | ||
| }; | ||
|
|
||
| const artifactStem = (name, attempt) => (attempt === 1 ? name : `${name}-attempt-${attempt}`); | ||
|
|
||
| export const openArtifactLogs = (directory, name) => { | ||
| assertDirectory(directory); | ||
| for (let attempt = 1; attempt < 10_000; attempt += 1) { | ||
| const stem = artifactStem(name, attempt); | ||
| const stdoutPath = path.join(directory, `${stem}.stdout.log`); | ||
| const stderrPath = path.join(directory, `${stem}.stderr.log`); | ||
| let stdout; | ||
| try { | ||
| stdout = fs.openSync(stdoutPath, 'wx', 0o600); | ||
| const stderr = fs.openSync(stderrPath, 'wx', 0o600); | ||
| return { stdoutPath, stderrPath, stdout, stderr }; | ||
| } catch (error) { | ||
| if (stdout !== undefined) { | ||
| fs.closeSync(stdout); | ||
| fs.rmSync(stdoutPath, { force: true }); | ||
| } | ||
| if (error?.code !== 'EEXIST') throw error; | ||
| } | ||
| } | ||
| throw new Error(`could not allocate unique command artifacts for ${name}`); | ||
| }; | ||
|
|
||
| export const writeJsonArtifact = (directory, name, value) => { | ||
| assertDirectory(directory); | ||
| for (let attempt = 1; attempt < 10_000; attempt += 1) { | ||
| const filePath = path.join(directory, `${artifactStem(name, attempt)}.json`); | ||
| try { | ||
| fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, { | ||
| encoding: 'utf8', | ||
| flag: 'wx', | ||
| mode: 0o600, | ||
| }); | ||
| return filePath; | ||
| } catch (error) { | ||
| if (error?.code !== 'EEXIST') throw error; | ||
| } | ||
| } | ||
| throw new Error(`could not allocate unique JSON artifact for ${name}`); | ||
| }; | ||
|
|
||
| const isContained = (root, candidate) => { | ||
| const relative = path.relative(root, candidate); | ||
| return ( | ||
| relative === '' || | ||
| (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative)) | ||
| ); | ||
| }; | ||
|
|
||
| const assertNoSymlinkComponents = (root, candidate) => { | ||
| const relative = path.relative(root, candidate); | ||
| let cursor = root; | ||
| for (const component of relative.split(path.sep).filter(Boolean)) { | ||
| cursor = path.join(cursor, component); | ||
| if (fs.lstatSync(cursor).isSymbolicLink()) { | ||
| throw new Error(`refusing symbolic link in canary worktree path: ${cursor}`); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| export const createSafeContainedDirectory = (root, relativePath) => { | ||
| const resolvedRoot = path.resolve(root); | ||
| const candidate = path.resolve(resolvedRoot, relativePath); | ||
| if (!isContained(resolvedRoot, candidate) || candidate === resolvedRoot) { | ||
| throw new Error(`refusing directory outside canary worktree: ${relativePath}`); | ||
| } | ||
| if (fs.existsSync(candidate)) { | ||
| throw new Error(`refusing existing canary fixture directory: ${candidate}`); | ||
| } | ||
| let cursor = resolvedRoot; | ||
| for (const component of path.relative(resolvedRoot, candidate).split(path.sep)) { | ||
| cursor = path.join(cursor, component); | ||
| if (fs.existsSync(cursor)) { | ||
| const stat = fs.lstatSync(cursor); | ||
| if (stat.isSymbolicLink()) { | ||
| throw new Error(`refusing symbolic link in canary worktree path: ${cursor}`); | ||
| } | ||
| if (!stat.isDirectory()) { | ||
| throw new Error(`refusing non-directory in canary worktree path: ${cursor}`); | ||
| } | ||
| } else { | ||
| fs.mkdirSync(cursor, { mode: 0o700 }); | ||
| } | ||
| } | ||
| const realRoot = fs.realpathSync(resolvedRoot); | ||
| const realCandidate = fs.realpathSync(candidate); | ||
| if (!isContained(realRoot, realCandidate)) { | ||
| throw new Error(`refusing directory outside real canary worktree: ${relativePath}`); | ||
| } | ||
| return candidate; | ||
| }; | ||
|
|
||
| export const selectSafeTrackedFiles = (worktree, files, count) => { | ||
| const realWorktree = fs.realpathSync(worktree); | ||
| const candidates = files.map((file) => { | ||
| if (!file || path.isAbsolute(file)) { | ||
| throw new Error(`refusing unsafe tracked path: ${JSON.stringify(file)}`); | ||
| } | ||
| const candidate = path.resolve(worktree, file); | ||
| if (!isContained(path.resolve(worktree), candidate)) { | ||
| throw new Error(`refusing tracked path outside canary worktree: ${file}`); | ||
| } | ||
| assertNoSymlinkComponents(path.resolve(worktree), candidate); | ||
| const stat = fs.lstatSync(candidate); | ||
| if (stat.isSymbolicLink()) { | ||
| throw new Error(`refusing tracked symbolic link in canary mutation set: ${file}`); | ||
| } | ||
| if (!stat.isFile()) { | ||
| throw new Error(`refusing non-file in canary mutation set: ${file}`); | ||
| } | ||
| const realCandidate = fs.realpathSync(candidate); | ||
| if (!isContained(realWorktree, realCandidate)) { | ||
| throw new Error(`refusing tracked path outside real canary worktree: ${file}`); | ||
| } | ||
| return { file, bytes: stat.size }; | ||
| }); | ||
| return candidates | ||
| .sort((left, right) => left.bytes - right.bytes || codePointCompare(left.file, right.file)) | ||
| .slice(0, count); | ||
| }; | ||
|
|
||
| export class ChildSupervisor { | ||
| constructor({ | ||
| platform = process.platform, | ||
| killTimeoutMs = 5_000, | ||
| terminationEnv, | ||
| spawnSyncImpl = spawnSync, | ||
| } = {}) { | ||
| this.platform = platform; | ||
| this.killTimeoutMs = killTimeoutMs; | ||
| this.terminationEnv = terminationEnv ?? { | ||
| SystemRoot: process.env.SystemRoot, | ||
| WINDIR: process.env.WINDIR, | ||
| COMSPEC: process.env.COMSPEC, | ||
| PATHEXT: process.env.PATHEXT, | ||
| TEMP: process.env.TEMP, | ||
| TMP: process.env.TMP, | ||
| }; | ||
| this.spawnSyncImpl = spawnSyncImpl; | ||
| this.children = new Set(); | ||
| this.receivedSignal = undefined; | ||
| this.signalHandlers = new Map(); | ||
| } | ||
|
|
||
| spawn(command, args, options = {}) { | ||
| if (this.receivedSignal) { | ||
| throw new Error(`refusing child spawn after ${this.receivedSignal}`); | ||
| } | ||
| const child = spawn(command, args, { | ||
| ...options, | ||
| detached: this.platform !== 'win32', | ||
| }); | ||
| this.children.add(child); | ||
| child.once('close', () => this.children.delete(child)); | ||
| return child; | ||
| } | ||
|
|
||
| terminate(child, signal = 'SIGTERM') { | ||
| if (!child?.pid || child.exitCode !== null || child.signalCode !== null) return; | ||
| this.terminateProcessGroup(child.pid, signal, child); | ||
| } | ||
|
|
||
| terminateProcessGroup(pid, signal, directChild) { | ||
| if (this.platform === 'win32') { | ||
| const systemRoot = this.terminationEnv.SystemRoot ?? this.terminationEnv.WINDIR; | ||
| let result; | ||
| if (systemRoot) { | ||
| try { | ||
| result = this.spawnSyncImpl( | ||
| path.win32.join(systemRoot, 'System32', 'taskkill.exe'), | ||
| ['/pid', String(pid), '/t', '/f'], | ||
| { | ||
| env: this.terminationEnv, | ||
| stdio: 'ignore', | ||
| windowsHide: true, | ||
| }, | ||
| ); | ||
| } catch (error) { | ||
| result = { error }; | ||
| } | ||
| } | ||
| if ( | ||
| (!result || result.error || result.status !== 0) && | ||
| directChild && | ||
| directChild.exitCode === null && | ||
| directChild.signalCode === null | ||
| ) { | ||
| directChild.kill(signal); | ||
| } | ||
| return; | ||
| } | ||
| try { | ||
| process.kill(-pid, signal); | ||
| } catch (error) { | ||
| if ( | ||
| error?.code !== 'ESRCH' && | ||
| directChild && | ||
| directChild.exitCode === null && | ||
| directChild.signalCode === null | ||
| ) { | ||
| directChild.kill(signal); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| terminateAll(signal = 'SIGTERM') { | ||
| const children = [...this.children]; | ||
| for (const child of children) this.terminate(child, signal); | ||
| if (children.length > 0) { | ||
| setTimeout(() => { | ||
| for (const child of children) { | ||
| if (child.pid) this.terminateProcessGroup(child.pid, 'SIGKILL'); | ||
| } | ||
| }, this.killTimeoutMs); | ||
| } | ||
| } | ||
|
|
||
| installSignalHandlers(targetProcess = process, onSignal = () => {}) { | ||
| for (const signal of ['SIGINT', 'SIGTERM']) { | ||
| const handler = () => { | ||
| if (this.receivedSignal) return; | ||
| this.receivedSignal = signal; | ||
| targetProcess.exitCode = SIGNAL_EXIT_CODES[signal]; | ||
| this.terminateAll(signal); | ||
| onSignal(signal); | ||
| }; | ||
| this.signalHandlers.set(signal, handler); | ||
| targetProcess.on(signal, handler); | ||
| } | ||
| } | ||
|
|
||
| disposeSignalHandlers(targetProcess = process) { | ||
| for (const [signal, handler] of this.signalHandlers) { | ||
| targetProcess.off(signal, handler); | ||
| } | ||
| this.signalHandlers.clear(); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.