Record a history rewrite on the repository [IFC-3284]
Merged
GM
14d ago+1954+1954+0123456789012345678901234567890123456789-149-149-012345678901234567890123456789
Why
When content at an earlier commit can no longer be re-derived, today only the worker logs and the orchestrator tell why. This PR stores the answer on the repository itself. IFC-3284, phase 6 of the IFC-3210 spec.
What changed
- Four
LOCAL, optional attributes onCoreGenericRepository:last_rewrite_previous_commit,last_rewrite_commit,last_rewrite_atandrewrite_count.CoreRepositoryandCoreReadOnlyRepositoryinherit them and override nothing. HistoryRewriteRecorderwrites them only when the graph comparison classifies a branch asREWRITE. Its store is a port. The SDK adapter reads the repository node through the generic and saves it, so the SDK builds the mutation of the node's own kind with only the changed fields.collect_pending_importsrecords each rewrite right after the branch commit is written, inside the collection lock. A failed record fails that branch alone, and its import stays queued.
What to look at
InfrahubRepository._queue_import: one place for the new-branch, updated-branch and staging paths.- A failed record has a step of its own,
record. On the default branch it is logged at error level and fails the run, but it does not writeerror-import: the import still runs and writesin-sync(FR-013). - A failed record is logged once where it is caught, the way a failed import is: the store chains the SDK error, so the reason is the API's own message for a known failure, and the traceback is kept only for an error that is not recognised.
- The
RewriteEventEmitterport is not here. It comes with the trunk signal (IFC-3285), because there is no event yet. The spec now says so. - The SDK protocols gain the four attributes in https://github.com/opsmill/infrahub-sdk-python/pull/1401, now merged. The
python_sdkpointer names its merge commit oninfrahub-develop.
How to test
uv run pytest backend/tests/unit/git/divergence/ backend/tests/unit/git/test_branch_reconciliation.py
uv run pytest backend/tests/component/git/test_repository_rewrite_branch_safety.py --neo4j
uv run pytest "backend/tests/integration/git/test_git_live_remote.py::TestRewrittenBranchSynchronisation" --neo4j
I broke each guard and watched its test fail, for example: classify against the worktree head instead of the graph commit, make the four attributes AWARE, or drop the catch around the record.
Checklist
- Tests added/updated
- Changelog entry added. This PR also carries
+failed-branch-blocks-other-branches.fixed.md, which IFC-3282 moved to the top of the stack. - External docs updated: IFC-3287 documents the reconciliation
- Internal .md docs updated
- I have reviewed AI generated content