docs/adr/0010-file-operation-engine-module.md
#3467–#3468)Supersession note. Rather than build a separate File Operation Engine, the file-mutation safety policy this ADR proposed was absorbed into the Shell Command Projection Module (ADR-0009). Phase 3 (
#3467) addedplatformWriteSync/platformReadSync/platformEnsureDir/normalizeContentto that seam, owning atomic write (tmp+rename),.mdnormalization, and directory creation as a single platform-conditional surface. Phase 4 (#3468) removed the duplicatedatomicWriteFileSync/safeReadFile/normalizeMdwrappers fromcore.cjs. TheapplyFileMutationPlan/ typed plan IR design proposed below was not built — the simpler per-call seam proved sufficient for the actual drift sites. Lock-file lifecycle (Track B item 3) remains owned bywithPlanningLockinplanning-workspace.cjsbecause its{ flag: 'wx' }exclusive-create semantics differ from atomic-write rename semantics.
We propose introducing a File Operation Engine Module that owns policy for managed file reads, writes, deletes, locks, backups, and rollbacks across installer, migration, and planning surfaces. Today, file mutation behavior is duplicated across bin/install.js, get-shit-done/bin/lib/installer-migrations.cjs, and multiple planning modules, with drift in atomic-write guarantees, path safety checks, and ownership classification.
This ADR also captures where Shell Command Projection Module policy should be consumed or expanded for hook-command-specific file mutations, so shell command drift and file mutation drift do not evolve as separate bug classes.
get-shit-done/bin/lib/ as the single seam for file mutation safety policy.rewrite-json, rewrite-text with format (toml/markdown/plain), delete-file, backup-file, restore-file, ensure-dir).bin/install.js
isGsdHookCommand)STALE_HOOK_BASENAMES)get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs
isManagedCodexHookCommand regex/path detection duplicated from installer-owned hook policyget-shit-done/bin/lib/shell-command-projection.cjs
isManagedHookBasename already owns part of this policy and should become the canonical ownerbin/install.js
atomicWriteFileSync and temp cleanup registryget-shit-done/bin/lib/core.cjs
atomicWriteFileSync helper diverges in fallback behavior from installer/migration variantsget-shit-done/bin/lib/installer-migrations.cjs
writeFileAtomicSync, rollback journaling, lock handling, and containment checksget-shit-done/bin/lib/planning-workspace.cjs and get-shit-done/bin/lib/state.cjs
get-shit-done/bin/lib/roadmap.cjs, phase.cjs, milestone.cjs, frontmatter.cjs, drift.cjs
The File Operation Engine Module should expose typed mutation planning and execution helpers:
planFileMutations({
rootDir,
operations: [
{ type: 'rewrite-json', relPath, mutate },
{ type: 'rewrite-text', relPath, mutate, format: 'toml' | 'markdown' | 'plain' },
{ type: 'delete-file', relPath },
{ type: 'ensure-dir', relPath },
],
ownership: { mode: 'managed-only' | 'allow-user', classifier },
})
applyFileMutationPlan({
plan,
atomic: true,
rollback: true,
lock: { scope: 'config' | 'planning', id: '...' },
})
For projection-adjacent paths, adapters should consume projection policy:
isManagedHookCommand(commandText, { surface, configDir })
0008-installer-migration-module.md0009-shell-command-projection-module.md#1755, #2866, #2979, #3002, #3017, #3439