mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 16:02:03 +00:00
* fix(codex): safely re-land WSL direct homes * fix(codex): finish WSL direct-home cutover * fix(codex): coalesce WSL launch hook installs * perf(codex): avoid duplicate retired WSL session scan * fix(codex): retain canonical WSL retired-home path * fix(codex): fail closed before retiring WSL auth * fix(codex): reopen WSL drain after rollback * fix(codex): preserve WSL source on unknown panes * fix(codex): harden repeated WSL runtime drains * perf(codex): bound pending WSL session scans * fix(codex): recover invalid WSL session watermarks * fix(codex): validate retained WSL scan state * fix(codex): accept durable WSL scan state * test(codex): cover the drain's inode-identity guard against destination replacement Removing the four `target_auth -ef temporary_destination_auth` assertions left all 33 apply-script tests passing, so a regression deleting them would have shipped silently. Reproduced before writing this. A hash check cannot catch the case. The pinned hard link keeps the original inode, so it still hashes correctly after another writer atomically renames a different file over the destination path; only inode identity sees it. Without the guard the script exits 0 and retires the source, leaving the user holding bytes nothing validated. The new case asserts the source survives. The harness is split by responsibility so no file exceeds its max-lines budget: fixtures, the coreutils interference shims, the run types, the apply runner, and the recovery/absent runners. The atomic-rename hook is deliberately separate from the in-place rewrite shim because different guards catch them. * fix(codex): keep the split drain harness inside the child-process boundaries Extracting the harness into non-test modules moved it out of the exemptions the single test file had: three new files import child_process, and two spawned without windowsHide. Adds the three to the import allowlist, and sets windowsHide on the spawns rather than exempting them - the flag is correct for these calls regardless of the ratchet, and they are skipped on win32 anyway. --------- Co-authored-by: Merge Sim <sim@local>
123 lines
4.6 KiB
TypeScript
123 lines
4.6 KiB
TypeScript
import { quotePosixShell } from '../../shared/wsl-login-shell-command'
|
|
|
|
export const WSL_SESSION_BRIDGE_TIMEOUT_MS = 30_000
|
|
|
|
const WSL_CODEX_SESSION_BRIDGE_BODY = [
|
|
'set -u',
|
|
'rollback_manifest=${3-}',
|
|
'rollback_stage_root=${4-}',
|
|
'scan_scope=${5-full}',
|
|
'scan_start=${6-}',
|
|
'scan_end=${7-}',
|
|
'if [ -n "$rollback_manifest" ]; then',
|
|
' [ -n "$rollback_stage_root" ] || exit 1',
|
|
' mkdir -p -- "$rollback_stage_root" || exit 1',
|
|
' : > "$rollback_manifest" || exit 1',
|
|
'fi',
|
|
'scanned_files=0',
|
|
'linked_files=0',
|
|
'bridge_failed=0',
|
|
'if [ ! -d "$source_sessions_root" ]; then',
|
|
` printf '{"scannedFiles":0,"linkedFiles":0}\\n'`,
|
|
' exit 0',
|
|
'fi',
|
|
'file_list=$(mktemp) || exit 1',
|
|
'day_list="$file_list.days"',
|
|
'trap \'rm -f -- "$file_list" "$day_list"\' EXIT HUP INT TERM',
|
|
'case "$scan_scope" in',
|
|
` full) find "$source_sessions_root" -type f -name '*.jsonl' -print0 > "$file_list" || exit 1 ;;`,
|
|
' recent)',
|
|
' case "$scan_start" in ????/??/??) ;; *) exit 1 ;; esac',
|
|
' case "$scan_end" in ????/??/??) ;; *) exit 1 ;; esac',
|
|
' if [[ "$scan_start" > "$scan_end" ]]; then',
|
|
` find "$source_sessions_root" -type f -name '*.jsonl' -print0 > "$file_list" || exit 1`,
|
|
' else',
|
|
' : > "$file_list" || exit 1',
|
|
' find "$source_sessions_root" -mindepth 3 -maxdepth 3 -type d -print0 > "$day_list" || exit 1',
|
|
" while IFS= read -r -d '' session_day_root; do",
|
|
' session_day=${session_day_root#"$source_sessions_root"/}',
|
|
' case "$session_day" in ????/??/??) ;; *) continue ;; esac',
|
|
' [[ "$session_day" < "$scan_start" ]] && continue',
|
|
' find "$session_day_root" -maxdepth 1 -type f -name \'*.jsonl\' -print0 >> "$file_list" || exit 1',
|
|
' done < "$day_list"',
|
|
' fi',
|
|
' ;;',
|
|
' *) exit 1 ;;',
|
|
'esac',
|
|
"while IFS= read -r -d '' source_file; do",
|
|
' scanned_files=$((scanned_files + 1))',
|
|
' relative_path=${source_file#"$source_sessions_root"/}',
|
|
' target_file="$managed_sessions_root/$relative_path"',
|
|
' if [ -e "$target_file" ] || [ -L "$target_file" ]; then',
|
|
' continue',
|
|
' fi',
|
|
' target_dir=${target_file%/*}',
|
|
' if ! mkdir -p -- "$target_dir"; then',
|
|
' bridge_failed=1',
|
|
' continue',
|
|
' fi',
|
|
' link_source="$source_file"',
|
|
' if [ -n "$rollback_manifest" ]; then',
|
|
' staged_file="$rollback_stage_root/$relative_path"',
|
|
' staged_dir=${staged_file%/*}',
|
|
' if ! mkdir -p -- "$staged_dir" || ! ln -- "$source_file" "$staged_file"; then',
|
|
' bridge_failed=1',
|
|
' continue',
|
|
' fi',
|
|
' target_stage="$target_file.orca-bridge-$$"',
|
|
' if [ -e "$target_stage" ] || [ -L "$target_stage" ]; then',
|
|
' bridge_failed=1',
|
|
' continue',
|
|
' fi',
|
|
' if ! ln -- "$staged_file" "$target_stage"; then',
|
|
' if ! cp -- "$staged_file" "$target_stage" || ! cmp -s -- "$staged_file" "$target_stage"; then',
|
|
' rm -f -- "$target_stage"',
|
|
' bridge_failed=1',
|
|
' continue',
|
|
' fi',
|
|
' fi',
|
|
' if ! printf \'%s\\0%s\\0\' "$target_stage" "$target_file" >> "$rollback_manifest"; then',
|
|
' rm -f -- "$target_stage"',
|
|
' bridge_failed=1',
|
|
' continue',
|
|
' fi',
|
|
' link_source="$target_stage"',
|
|
' fi',
|
|
// Codex resume ignores symlinked JSONL, so create links inside the distro.
|
|
' if ln -- "$link_source" "$target_file"; then',
|
|
' linked_files=$((linked_files + 1))',
|
|
' elif [ ! -e "$target_file" ] && [ ! -L "$target_file" ]; then',
|
|
' if [ -n "$rollback_manifest" ]; then',
|
|
' bridge_failed=1',
|
|
' else',
|
|
' target_stage="$target_file.orca-bridge-$$"',
|
|
' if [ ! -e "$target_stage" ] && [ ! -L "$target_stage" ] && cp -- "$source_file" "$target_stage" && cmp -s -- "$source_file" "$target_stage" && ln -- "$target_stage" "$target_file"; then',
|
|
' linked_files=$((linked_files + 1))',
|
|
' else',
|
|
' bridge_failed=1',
|
|
' fi',
|
|
' rm -f -- "$target_stage"',
|
|
' fi',
|
|
' fi',
|
|
'done < "$file_list"',
|
|
'[ "$bridge_failed" = 0 ] || exit 1',
|
|
`printf '{"scannedFiles":%s,"linkedFiles":%s}\\n' "$scanned_files" "$linked_files"`
|
|
].join('\n')
|
|
|
|
export const WSL_CODEX_SESSION_BRIDGE_SCRIPT = [
|
|
'source_sessions_root="$1"',
|
|
'managed_sessions_root="$2"',
|
|
WSL_CODEX_SESSION_BRIDGE_BODY
|
|
].join('\n')
|
|
|
|
export function buildWslCodexSessionBridgeShellCommand(paths: {
|
|
managedSessionsRoot: string
|
|
systemSessionsRoot: string
|
|
}): string {
|
|
return [
|
|
`source_sessions_root=${quotePosixShell(paths.systemSessionsRoot)}`,
|
|
`managed_sessions_root=${quotePosixShell(paths.managedSessionsRoot)}`,
|
|
WSL_CODEX_SESSION_BRIDGE_BODY
|
|
].join('\n')
|
|
}
|