Slice 15: Ingest Mutation Safety
Scope#
Harden internal ingest before making codealmanac ingest public.
The workflow now audits filesystem mutation around a harness run:
preflight = mutation_policy.preflight(workspace)
harness = harnesses.run(...)
safety = mutation_policy.validate(preflight, workspace, harness.changed_files)The policy is local and Git-backed:
- require Git change tracking before AI lifecycle writes
- require
.almanac/to be clean before the run starts - allow pre-existing dirty application files as source material
- fail if any non-
.almanac/path changes during the run - fail if the harness reports a changed file outside
.almanac/
Architecture#
services/workspaces owns the typed workspace change-state port because it is
repo/worktree state. The concrete Git implementation lives in
integrations/workspaces/git.
workflows/ingest
-> IngestMutationPolicy
-> services/workspaces/WorkspaceChangeProbe protocol
-> integrations/workspaces/git/GitWorkspaceChangeProbeapp.py wires the Git probe into IngestMutationPolicy. CLI, workflows, and
services still do not import concrete integrations.
Cosmic Python Translation#
Chapter 6 describes Unit of Work as an abstraction over atomic operations with a stable snapshot and commit/rollback boundary. CodeAlmanac filesystem writes cannot honestly roll back like a database transaction. This slice borrows the snapshot boundary but does not fake rollback: Git status before/after the harness run is the audit surface, and unsafe mutation fails the run.
Behavior#
Dirty app code remains usable:
src/app.py modified before ingest -> allowed if unchanged by the run
src/app.py modified by the harness -> run failsDirty wiki state is not allowed:
.almanac/pages/foo.md modified before ingest -> preflight failsThis protects user-authored wiki edits from being silently merged with an agent run and gives the run ledger a clear failure reason.
Tests#
- Git porcelain status parser handles renames and untracked paths.
- Ingest succeeds with pre-existing dirty app code when the harness leaves it unchanged.
- Ingest fails when the harness mutates a dirty app file without reporting it.
- Ingest fails when
.almanac/is dirty before the run. - Ingest fails outside a Git worktree.
- Architecture test still prevents CLI/workflows/services from importing integrations.