2.9 KiB
Isolate proto freshness generation from the scanned repository
Decided 2026-08-25. Check 2f ran make proto in the scanned CMS working tree
and compared git status before and after. That made a read-oriented safety
check destructive: concurrent checker processes generated into the same files,
an interrupted run could leave a partially rewritten tree, and a generated
file that was already dirty could change bytes without changing its porcelain
status.
Decision
- Copy the proto generation inputs and existing generated outputs into a unique temporary sandbox for every freshness invocation.
- Run
make protoonly in that sandbox. Link only the installed package-local generator executables and their package entrypoints needed by Buf and the export script; generated output paths never point back into the scanned repository. - Snapshot generated regular files and symlinks by type, mode, link target, and SHA-256 content digest before and after generation. Sort paths before reporting added, modified, and removed outputs in the existing porcelain-like CLI format.
- Remove the owned sandbox on success, generator failure, and all ordinary return paths. Abrupt process interruption can affect only disposable system temporary state, never the scanned working tree.
- Exercise the boundary with real
makerecipes, including independent concurrent checker processes and a generator that writes partial output before failing.
A repository-wide lock was rejected because it serializes independent safety runs and still leaves the live working tree vulnerable to interrupted generation. Comparing only Git status in a temporary checkout was rejected because status is not a content comparison and can conceal a second rewrite of an already-modified file. Copying the entire repository, including dependency trees and build artifacts, was rejected because proto generation needs only a small, explicit input and output surface.
Consequences
- Parallel check-safety processes can run proto freshness checks without contending on generated files or corrupting the CMS checkout.
- Check 2f retains its
make protosuccess, failure, and before/after finding messages while its freshness verdict now follows deterministic file content. - Generator stderr is still returned through
protoFreshnessResult.output, and sandbox preparation, snapshot, generation, and cleanup failures retain their causal error chains. proto_freshness.goowns isolation and comparison; focused regression coverage lives inproto_freshness_test.go.
Keywords: check-safety, check 2f, proto freshness, make proto, concurrency, interruption safety, sandbox, checkProtoGeneratedFreshness, checkProtoGeneratedFreshnessInSandbox, protoFreshnessResult, proto_freshness.go, proto_freshness_test.go, backend/internal/api, backend/internal/mcpserver/generated, packages/api/src, buf generate, pnpm generate-exports