@davideasden/pi-undo
Persistent workspace undo and redo for Pi
Package details
Install @davideasden/pi-undo from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@davideasden/pi-undo- Package
@davideasden/pi-undo- Version
0.2.26- Published
- Sep 21, 2026
- Downloads
- 762/mo · 255/wk
- Author
- davideasden
- License
- MIT
- Types
- extension
- Size
- 1.4 MB
- Dependencies
- 1 dependency · 2 peers
Pi manifest JSON
{
"extensions": [
"./extensions/pi-undo.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-undo
Persistent workspace undo and redo for Pi.
Each completed agent run creates a checkpoint that captures both the Pi session boundary and a content-addressed workspace snapshot. /undo moves Pi's session tree to a prior run and restores the matching workspace. /redo reverses the undo with a safety snapshot taken before the operation. The system is crash-safe: an interrupted restore is rolled forward or back on next startup using durable journals, write-ahead logging, and quarantine artifacts.
Features
- Persistent undo / redo across Pi restarts. History is stored per-session and survives crashes.
- Diff viewer —
/diffand/diff Nshow before-and-after file changes with colored, scrollable output in TUI mode and a summary in non-TUI modes. - Session + workspace — Pi's session tree and workspace files are restored together as a unit.
- Safety snapshots —
undocaptures the current workspace as a redo safety snapshot;tree navigationrecords a rescue snapshot before switching branches. - Deferred prompts — text, images,
@filereferences, and paste content entered during an undo/redo are queued and processed in FIFO order once the operation completes. Prompts are never lost. - Crash recovery — a write-ahead log (WAL), mutation journal, and quarantine artifacts allow in-progress operations to be rolled forward or back on restart.
- External concurrency detection — file fingerprint and inode checks detect external modification. Conflicting changes are never silently overwritten; the system fails closed or enters
recovery required. - No Git workflow — snapshots use a private object database. No
git commit,git stash,git reset, branches, or forges are required. - Nested repositories and initialized submodules are handled as independent roots. Their
.gitmetadata is never modified. - Performance — batch WAL operations (up to 1,024 files per batch), scoped safety snapshots, prebuilt durable transaction packs, native Rust no-clobber file helper (macOS/Linux, arm64/x64), indexed WAL record and conflict lookups, and parallel manifest blob reads keep restore fast at scale. Unsupported platforms and failed integrity checks automatically use the TypeScript fallback.
Requirements
- Pi
0.86.1或更高版本(已在 0.86.1 上验证)。0.84.4及更早版本不再受支持,也不在 CI 中测试:早期版本的会话树与扩展生命周期行为不同,不保证撤回语义正确。 - Node.js
22.19.0or later. - Git available on
PATH(used internally for content-addressed snapshots).
Native Rust Acceleration
pi-undo includes a cross-platform native Rust helper (pi-undo-fs) to accelerate filesystem operations. The published package contains these six precompiled binaries:
| Platform | Architecture | Binary |
|---|---|---|
| macOS | arm64 | pi-undo-fs-darwin-arm64 |
| macOS | x64 | pi-undo-fs-darwin-x64 |
| Linux | arm64 | pi-undo-fs-linux-arm64 |
| Linux | x64 | pi-undo-fs-linux-x64 |
| Windows | arm64 | pi-undo-fs-win32-arm64.exe |
| Windows | x64 | pi-undo-fs-win32-x64.exe |
The extension automatically selects the correct binary for the current runtime, so users do not need to install Rust or choose a platform manually. Windows binaries use the .exe suffix. On platforms without a precompiled binary, the extension automatically falls back to the TypeScript implementation with the same functionality.
Installation
Install from npm (Recommended)
All supported platforms use the same installation command. The npm package includes precompiled arm64 and x64 Rust helpers for macOS, Linux, and Windows, and the extension selects the correct version at startup:
pi install npm:@davideasden/pi-undo
Restart Pi to load the extension. Users do not need to install Rust or select and install a platform-specific package.
Install from Local Source
pi install /path/to/pi-undo
Load Directly for Development
pi -e /absolute/path/to/pi-undo/extensions/pi-undo.ts
Note:
pi installcopies the entire package, including the precompiled binaries undernative/bin/, into Pi's extension directory. To include a newly compiled native binary in a source installation, runnpm run build:nativebeforepi install.
Usage
Work with Pi normally. pi-undo automatically records a boundary after each completed agent run.
Recovery
If an operation fails mid-flight (for example, the process is killed while files are being restored), pi-undo locks undo history and reports recovery_required. Run:
/undo-recover
to re-run recovery in place: it re-verifies pending journals, settles provably-safe transactions, rebuilds the undo/redo stacks, and refreshes the status line — the in-process equivalent of restarting the session window. If the workspace is still locked afterwards, the blocking transaction belongs to another session in the same workspace; open (or restart) that session and run /undo-recover there.
Diff
/diff
Shows files changed by the most recent completed run. In TUI mode, select a file to open a colored, scrollable before-and-after comparison. Binary files are listed without line-by-line diff.
Use a one-based position to inspect an earlier run (1 is the most recent):
/diff 3
Print, JSON, and RPC modes report a one-line file and line-count summary.
Undo
/undo
Returns to the previous completed run on the current branch. Before restoring, it captures the current workspace as a redo safety snapshot.
After a successful undo, text entered during the operation is replayed into the editor. RPC mode reports the refill request; print and JSON modes do not replay prompts.
撤回会等待当前轮次的输入快照和检查点完成,再选择撤回目标;Pi 已空闲但检查点仍在生成时,不会提前撤回上一轮。检查点生成失败会明确暂停历史。
取消与超时
执行较慢时,状态栏会显示当前阶段、经过的秒数和操作 ID。可以输入:
/undo-cancel
此命令请求安全停止正在执行的撤回或重做。已开始的文件写入会先结束,未提交的事务随后按日志恢复。已经持久提交的操作会继续完成清理。取消或超时分别报告 operation_cancelled、operation_timeout;无法确认子进程停止或恢复一致性时,保留隔离并报告 recovery_required。
默认单次 Git 调用预算为 120 秒,每次撤回、捕获及恢复预算为 300 秒。可在启动 Pi 前用正整数毫秒调整:
export PI_UNDO_GIT_TIMEOUT_MS=180000
export PI_UNDO_OPERATION_TIMEOUT_MS=600000
补偿使用独立预算,避免继承前向操作的取消信号。磁盘 I/O 若无法中断,状态会保留到在途任务结束;超时不表示可以立即释放仍在写入的工作区锁。
长操作或失败会在 <sessionDir>/.pi-undo/diagnostics/<sessionId>-latest.json 保存最近一次诊断,包含操作 ID、阶段、耗时、Git 子命令名和退出结果,不包含提示词、文件内容、完整参数或子进程输出。重新运行 /undo-recover、切换会话或退出时,会先等待旧 runtime 的任务和后台持久化结束。
Redo
/redo
Restores the session and workspace captured immediately before the corresponding undo. The redo safety snapshot preserves edits made between the undo and the redo.
Tree Navigation
Continue to use Pi's native command:
/tree
Before Pi moves to another session-tree boundary, pi-undo validates the target and records a rescue snapshot. After navigation it restores the matching workspace.
While the agent is streaming, /undo and /redo request an abort and wait for idle. If the wait times out, no files are restored. Native /tree is cancelled while streaming and can be retried when idle.
The footer shows available history, for example:
undo:2 redo:1
When crash recovery is pending, the footer shows:
recovery_required
Performance Notes
普通文件原生恢复路径保留 5 次完整拓扑扫描。macOS/Linux 的新版 helper 使用不跟随符号链接的目录句柄扫描,仍会发现 Git 忽略目录中的嵌套仓库。小工作区根据上次扫描规模选择 TypeScript 完整重扫,避免进程启动开销;没有使用 TTL 缓存或默认跳过 node_modules。
原生恢复现支持已有父目录中的普通文件删除,以及覆盖、创建、删除混合计划。扩展能力通过 restore-files-v2 探测;旧 helper、缺少二进制、目录操作及超出句柄预算的计划继续走 TypeScript 路径。pack 持久化、内容校验、no-clobber 与恢复依据均保留。
本机 macOS arm64 的三次 undo 中位数:3,000 包/1 文件从 1,976 ms 降至 924 ms,10,000 包/1 文件从 5,857 ms 降至 2,755 ms;100 文件的子目录撤销从 517 ms 降至 180 ms,混合撤销从 711 ms 降至 186 ms。测量方法和限制见 原生性能验证记录。
可通过真实 Pi 0.86.1 SDK 和离线 faux provider 运行大型工作区基准;它覆盖 3,000/10,000 个依赖包、修改 1/100 个文件,每组撤回三次并验证重做:
PI_UNDO_LARGE_WORKSPACE=1 npx vitest run test/large-workspace.test.ts
输出包含扫描次数、每次耗时、进程峰值 RSS 和事件循环延迟;常规测试以扫描次数作为性能门槛,避免使用易受机器负载影响的墙钟阈值。
Real-world measurements from a 104-file undo operation before optimizations:
ok files:104 total:8797ms apply:8591ms capture:89ms journal:64ms commit:27ms plan:11ms
After batch WAL, scoped safety snapshots, parallel restore I/O, batch file deletes, and prebuilt durable transaction packs:
ok files:104 total:~1050ms apply:~850ms capture:~90ms journal:~65ms
After native Rust helper, durable pack caching, parallel durable finalization, batch validated blob reads, and indexed mutation/path lookups:
ok files:104 total:~850ms apply:~650ms capture:~90ms journal:~65ms plan:~10ms
Performance gains come from:
- Batch WAL durability — write-once, fsync-once per batch of up to 1,024 entries instead of per-file.
- Durable transaction packs — source and target variants, fingerprints, modes, artifact names, and checksums are published and fsynced before native workspace mutation.
- Prebuilt reverse/forward packs — completed agent runs prepare both directions and pin their manifests outside the undo/redo command hot path.
- Optional native helper — verified regular-file batches use platform no-clobber primitives while retaining same-inode ownership artifacts; missing binaries or failed validation fall back before mutation.
- Scoped safety snapshots — only paths recorded in a checkpoint's
changedPathsare snapshotted for undo/redo, not the entire workspace. - Parallel target I/O — up to 32 target artifact files are written and synced concurrently.
- Concurrent request preparation — blob reads, live-state checks, and fingerprint computation run at 32-wide concurrency.
- Batch file deletes — delete operations share the same WAL batch and directory fsync merging.
- Directory fsync merging — barriers are applied once per unique directory per phase, not once per file.
- Native Rust no-clobber helper — packaged macOS arm64 binary uses platform renameat2 with EEXIST guard for regular-file batches; missing binaries or platform mismatch fall back to the TypeScript path before mutation.
- Durable pack caching — completed agent runs build and cache reverse/forward durable packs; the undo/redo hot path reuses the cached pack with manifest pin, avoiding redundant snapshot reads.
- Indexed WAL record lookups — mutation records are indexed by ordinal for O(1) direct access instead of linear scan.
- Indexed path conflict resolution —
exactExclusionsare stored as a Set for O(1) membership checks instead of O(n)Array.includes. - Batch validated manifest blob reads — durable pack reads coalesce blob fetches into a single batch per manifest with combined Git validation.
How It Works
Private state is stored alongside the Pi session:
<sessionDir>/.pi-undo/
For every completed agent run, pi-undo captures:
- A session boundary — the logical point in Pi's session tree.
- A workspace manifest — a content-addressed snapshot of the workspace root(s).
Snapshots use a private Git object database and a temporary Git index. They never touch the repository's normal history, HEAD, reflog, or stash.
The restore flow is:
- Validate current session, workspace topology, and target manifest.
- Establish mutation authority before changing files: either durable JSON
INTENTrecords on the TypeScript path or a complete fsynced transaction pack on the native path. - Capture a safety snapshot when content differs from the preverified checkpoint source; otherwise reuse the pinned checkpoint manifest.
- Move the Pi session cursor to the target boundary.
- Restore workspace paths with fingerprint and inode checks and no-clobber installation.
- Verify the resulting session and workspace before committing the journal (
TARGET_VERIFIED→CLEANED).
Mutation Journal (WAL)
Each file change is tracked through a six-state hash chain:
INTENT → SOURCE_QUARANTINED → SOURCE_VERIFIED → TARGET_INSTALLED → TARGET_VERIFIED → CLEANED
- INTENT — durable intent recorded before any mutation.
- SOURCE_QUARANTINED — original file hard-linked to a random artifact name.
- SOURCE_VERIFIED — original removed, artifact content verified.
- TARGET_INSTALLED — new file hard-linked into place (no-clobber).
- TARGET_VERIFIED — workspace confirmed matching target state.
- CLEANED — source and target artifacts removed.
Batch operations (beginMany, advanceBatch) maintain the same per-file six-state contract while reducing physical fsync calls by grouping entries. On the native path, the transaction pack is the pre-mutation INTENT authority; finalization or startup recovery materializes the same six per-file states into the append-only WAL before cleanup.
Every WAL record is checksum-linked to its predecessor. The journal is append-only and never mutated in place. Native finalization advances through TARGET_VERIFIED, fsyncs the installed inode while its ownership marker is still present, then removes exact artifacts and appends CLEANED.
Quarantine and External Concurrency
Ordinary files and symlinks are restored through same-directory, same-filesystem artifacts:
- Source capture:
link(original, sourceArtifact)— fails withEEXISTif artifact already exists. - Target installation:
link(targetArtifact, original)— fails withEEXISTif original was externally recreated. - Fingerprint + inode: before each state transition, both content fingerprint and
(dev, ino)identity are verified. A matching fingerprint with a different inode is treated as external replacement and triggers a safe fail-closed state. - Artifact cleanup: only artifacts registered in the journal with matching paths, names, fingerprints, and ownership are removed. Unclaimed files are never deleted.
- Rollback: from any state,
restoreMutationconverges to the pre-operation state. If a previous target was externally replaced with identical content but a different inode, the external file is preserved and the journal remains active.
Safety and Recovery
- Pi
HEAD, index, refs, reflog, stash, config, and other repository metadata are never modified. - Nested repositories and submodules are restored as independent roots. Their
.gitdirectories are not created or deleted. - If the process stops during a restore, startup recovery reads the transaction journal:
- Without a trusted cursor marker: restores the rollback manifest and marks the transaction aborted.
- With a trusted cursor marker: completes cursor durability and commits the transaction.
- On conflict (identity, leaf, manifest, cursor, or workspace mismatch): enters
recovery requiredand blocks further history mutation.
When recovery_required appears, first back up the workspace and Pi session JSONL. Transaction diagnostics are stored in:
<sessionDir>/.pi-undo/transactions/
A transaction directory may contain descriptor.json, restore-plan.json, state.json, mutations.jsonl, durable-pack-v1.bin, and a native helper request. Do not delete .pi-undo without a backup: unresolved packs or quarantine artifacts may be the only surviving copy of a file version.
Troubleshooting recovery_required
First stop other Pi instances, editors, formatters, and watchers that may write to the same workspace. Then completely quit and restart Pi once. Startup recovery is idempotent and normally finishes an interrupted transaction automatically. Deleting .pi-undo while Pi is still running does not clear the in-memory recovery lock, and the active process may recreate the directory.
If the footer includes an opId, locate that exact transaction first. Recovery data is stored under the session directory for each workspace. Inspecting .pi-undo for a different workspace can therefore produce a misleading result that no pending journal exists:
OP_ID="op-..."; TX="$(find "${PI_AGENT_DIR:-$HOME/.pi/agent}/sessions" -type d -path "*/.pi-undo/transactions/$OP_ID" -print -quit)"; test -n "$TX" && printf 'transaction=%s\n' "$TX"
Back up the workspace before continuing. Inspect the transaction phase and descriptor without editing them:
jq '{opId,phase,revision,observedLogicalLeaf}' "$TX/state.json"
jq '{action,fromLogicalLeaf,toLogicalLeaf,workspaceIdentity,sessionIdentity,scopeCount:(.scopePaths | length)}' "$TX/descriptor.json"
List every non-terminal transaction under the same .pi-undo root. This command is intentionally kept on one line because trailing whitespace after a continuation backslash can break find -exec when a multiline command is pasted:
ROOT="$(dirname "$(dirname "$TX")")"; find "$ROOT/transactions" -name state.json -type f -exec jq -r 'select(.phase != "COMMITTED" and .phase != "ABORTED") | "\(.opId) \(.phase)"' {} +
If mutations.jsonl exists, summarize the final state of each mutation ordinal and list mutations that have not been cleaned:
jq -s 'group_by(.ordinal) | map(.[-1]) | group_by(.state) | map({state: .[0].state, count: length})' "$TX/mutations.jsonl"
jq -s 'group_by(.ordinal) | map(.[-1]) | map(select(.state != "CLEANED")) | .[] | {ordinal,path,kind,state}' "$TX/mutations.jsonl"
- If the second command prints any records, artifacts or file mutations are still active. Do not delete or move the transaction. Preserve the workspace, session JSONL, transaction directory, and same-directory
.pi-undo-*artifacts for manual recovery. - If the second command prints nothing, every WAL mutation is already
CLEANED. A footer such asrecovery_required files:1 op:...may still appear because the conflict path count has a minimum fallback of one.files:1alone does not prove that one active file remains. - Only when every mutation is
CLEANED, the transaction phase is stillRECOVERY_REQUIRED, and you have independently verified that the current workspace and Pi session are the result you want to keep, back up and isolate that transaction:
SESSION="$(jq -r '.sessionIdentity.path' "$TX/descriptor.json")"; STAMP="$(date '+%Y%m%d-%H%M%S')"; BACKUP="$ROOT/recovery-backup/$STAMP"; mkdir -p "$BACKUP"; cp -p "$SESSION" "$BACKUP/$(basename "$SESSION").backup"; mv "$TX" "$BACKUP/"
After isolating a fully cleaned transaction, completely quit every Pi process for that workspace and start Pi again. Reloading the session alone may retain the in-memory recovery lock. Do not edit state.json by hand because journal states and descriptors are checksum-bound. Do not remove the entire .pi-undo directory because it may still contain committed history, snapshots, packs, or the only recoverable copy of a file.
Limitations
- Git-ignored files are not included in snapshots and are not created or deleted during restore.
- Empty directories are not represented in snapshots.
- Real
.gitmetadata is never created, modified, or deleted. - The workspace lock prevents concurrent
pi-undoinstances, but cannot prevent editors, watchers, or other processes from writing files concurrently. - Fingerprint and inode checks reduce the external-concurrency race window, but cannot make the final check-and-unlink atomic in pure Node.js.
--no-sessionmode has no durable session cursor. Undo and redo can work in-process, but crash persistence is not guaranteed.- Uninitialized gitlinks are not initialized automatically. A broken nested repository causes capture to fail instead of being silently skipped.
- Workspace files and Pi session JSONL are not an operating-system-level ACID transaction. Snapshots, WAL, cursor markers, verification, and idempotent recovery are used to converge to the old or new state.
Development
Dependencies
Clone the repository and install dependencies:
git clone https://github.com/DavidEasden/pi-undo.git
cd pi-undo
npm install
Build the Native Rust Helper
Install the Rust toolchain before building or updating a native binary:
npm run build:native
npm run build:native creates pi-undo-fs for the current build platform under native/pi-undo-fs/target/release/. The Native binaries workflow builds arm64 and x64 versions on macOS, Linux, and Windows runners, verifies the full six-binary matrix, and uploads them as workflow artifacts. The Publish to npm workflow publishes the package when a v* tag is pushed, using the binaries committed under native/bin/.
For local development on the current platform, copy the generated file into native/bin/ and rename it for the platform. For example, a Windows build must use the corresponding .exe filename.
cp native/pi-undo-fs/target/release/pi-undo-fs native/bin/pi-undo-fs-darwin-arm64
chmod +x native/bin/pi-undo-fs-darwin-arm64
Every precompiled binary listed under Requirements must be committed under native/bin/ to be part of a release. The Native binaries workflow verifies the complete six-binary matrix before uploading artifacts, and the Publish to npm workflow publishes the package on a v* tag push. The npm package must configure Trusted Publishing (OIDC) for the Publish to npm workflow. If no binary is available for the current platform, the extension automatically uses the TypeScript fallback.
Project Layout
extensions/pi-undo.ts Pi extension entry point
src/
atomic-fs.ts Atomic file writes, fsync helpers
controller.ts Undo/redo/diff controller orchestrator
diff-ui.ts TUI diff view (Ink/React components)
diff-view.ts Diff computation and rendering
encoding.ts checksum, canonical JSON
git-runner.ts Git subprocess runner with counting
journal.ts Transaction journal (session/descriptor/phase)
model.ts Core types: manifest, root, session, plan
mutation-journal.ts WAL mutation journal (hash chain, batch ops)
durable-pack.ts Pre-mutation source/target authority and finalization
native-restore.ts Optional platform helper adapter with TypeScript fallback
packed-recovery.ts Pack-to-WAL rollback/roll-forward recovery
path-safety.ts Symlink escape, relative path safety
pi-runtime.ts Pi integration layer (session/extension bridge)
quarantine.ts File isolation, no-clobber install, external concurrency
recovery.ts Startup crash recovery
restore-engine.ts Workspace restore engine (plan → apply → verify)
root-discovery.ts Workspace root topology detection (nested repos, submodules)
session-state.ts Pi session cursor management
snapshot-store.ts Git-backed content-addressed snapshot store
status-reporter.ts Phase timing and footer status
workspace-lock.ts Cross-instance workspace lock
native/pi-undo-fs/ Rust no-clobber regular-file helper
native/bin/ Precompiled platform binaries included in release packages
test/ Unit, integration, recovery, and fault-injection tests
Testing
npm test # Full test suite (425+ tests)
npm run test:native # Rust helper and durable-pack recovery tests
npm run test:watch # Watch mode
npm run test:integration # Pi runtime and extension integration tests
npm run typecheck # TypeScript type checking
npm run pack:dry-run # Inspect npm package contents
The typecheck filters known pre-existing issues in Pi's own dependencies (undici-types, @modelcontextprotocol, @google/genai, ReadonlySessionManager). Only new project-level errors are enforced.
Performance Benchmarks
Benchmark tests assert Git call counts and WAL record counts, not wall-clock thresholds, to avoid environmental flakiness. Selected synthetic results (104-file restore, includes fixture setup, capture, plan, and apply):
| Scenario | Git calls | WAL records | Duration |
|---|---|---|---|
| 104-file restore (write) — batch + parallel I/O | ≤12 | 624 | ~1.1s |
| 100-file restore (delete) — batch deletes | ≤12 | 600 | ~0.6s |
| 4,000-file rollback snapshot — batch Git | ≤24 (4 x mktree, 4 x commit-tree) |
— | ~7s |
The 104-file standalone apply probe (10 warmup iterations + 10 measured) completes in approximately 3.9s post-optimization on the TypeScript path, and approximately 2.8s on the native Rust path.
Performance Optimizations
Several hot paths were profiled and corrected from quadratic (n doubled ≈ 4× cost) to near-linear scaling. Each change was verified against the existing test suite (425+ tests) plus fault-injection and adversarial-diff tests. Optimization order was guided by real profile data rather than static code review alone. After this phase, attention shifted to the native Rust helper path, which dominates production workloads.
Wall-clock comparison (n changed files + n ignored files)
Plan phase — undo diff derivation and workspace topology check:
| n | Before | After | Improvement |
|---|---|---|---|
| 1,000 | ~178ms | ~131ms | 1.4× |
| 2,000 | ~399ms | ~259ms | 1.5× |
| 5,000 | ~2.5s | ~699ms | ~3.6× |
Bidirectional durable pack prepare — agent-settled caching for undo/redo:
| n | Before (no batch) | After (batched) | Improvement |
|---|---|---|---|
| 500 | ~949ms | ~249ms | 3.8× |
| 1,000 | ~2,940ms | ~386ms | 7.6× |
| 2,000 | ~10,512ms | ~677ms | 15.5× |
Native apply — the production hot path:
| n | TypeScript fallback | Native Rust helper | Improvement |
|---|---|---|---|
| 500 | ~2,572ms | ~253ms | 10.2× |
| 1,000 | ~5,726ms | ~374ms | 15.3× |
| 2,000 | ~10,521ms | ~646ms | 16.3× |
Algorithm microbenchmarks
| Scenario | Before | After | Improvement |
|---|---|---|---|
| 8,000×8,000 path overlap check | ~1,352ms | ~7ms | 193× |
| 4,000-directory ignored prefix scan (plan) | ~544ms | ~161ms | 3.4× |
| 5,000×5,000 manifest integrity verify | ~610ms | ~7ms | 87× |
Key enablers
- Manifest context batching (
SnapshotStore.readBlobs): one manifest read and full revalidation serves all blob fetches per operation instead of one manifest load per blob. 2,000-file pack creation dropped from 10.5s to 796ms. - Blob read batch sizing (
BLOB_BATCH_MAX_ENTRIES: 256 → 2,048): 40cat-file --batchprocesses collapsed to 6 for 5,000 files by letting the 16MiB byte budget drive batch boundaries. - Path overlap indexing (
pathSetsOverlapinpath-safety.ts): sorted binary search plus ancestor enumeration replaces a nestedsome()pattern. 8,000×8,000 path pairs from 1.35s to 7ms. - Ignored-proof prefix index (
IgnoredProofIndexinrestore-engine.ts): lazily sorted binary lower-bound search for directory prefix lookups replaces a full-set spread per candidate. 4,000 directories from 544ms to 161ms. - WAL ordinal indexing (
loadOrdinalinmutation-journal.ts): direct array access by contiguous ordinal replaces linear.find()throughout quarantine and legacy recovery. - Native Rust no-clobber helper (
native/pi-undo-fs): platform native hardlink operations with EEXIST guard. Processes in ~0.3ms per file vs ~5.3ms for the TypeScript fallback, with WAL materialized from the durable pack.