fix(git-sync): branch choreography + strict scoping + delete cap (Phase B hardening)
Fixes found by the live pull/push e2e: - CRITICAL: driveCycle never checked out the 'docmost' branch before applyPullActions, so Docmost content was written straight onto 'main', clobbering local file edits before push could diff them. Now checkout 'docmost' before pull (applyPullActions commits there then checks out main + merges) — mirrors the engine's pull main(). Round-trip now works both ways. - add an unresolved-merge guard (SPEC §9): skip the cycle if the vault is mid-merge instead of failing on checkout. - SAFETY: enabledSpaces() is now STRICT opt-in — only spaces with settings.gitSync.enabled===true; removed the all-spaces fallback that synced every space (incl. a 92-page one) the moment GIT_SYNC_ENABLED flipped. - SAFETY: per-cycle delete cap (GIT_SYNC_MAX_DELETES_PER_CYCLE, default 5): dry-run the push, and if planned deletes exceed the cap, run the apply with deletePage neutralized — phantom absence-deletions from a non-convergent vault can't soft-delete real pages. Fails safe if the dry-run throws. - fix manual trigger: TriggerGitSyncDto.spaceId needs @IsUUID or the global whitelist ValidationPipe strips it (arrived undefined -> vault 'undefined'). Live-verified on an isolated flagged space: push (vault file edit -> Docmost content, stamped lastUpdatedSource='git-sync') and pull (Docmost rename -> vault file + meta) both work; an unrelated 92-page space stayed untouched throughout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -362,6 +362,20 @@ export class EnvironmentService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defense-in-depth absolute cap on how many pages a single push cycle may
|
||||
* soft-delete (default 5). A non-convergent / phantom-absence cycle whose push
|
||||
* plan would delete more than this is forced to skip deletions that cycle (the
|
||||
* orchestrator logs a WARNING). A non-positive or unparseable value falls back
|
||||
* to the default 5 so the cap can never be silently disabled.
|
||||
*/
|
||||
getGitSyncMaxDeletesPerCycle(): number {
|
||||
const parsed = parseInt(
|
||||
this.configService.get<string>('GIT_SYNC_MAX_DELETES_PER_CYCLE', '5'),
|
||||
);
|
||||
return Number.isFinite(parsed) && parsed > 0 ? parsed : 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* The service user id git-sync writes are attributed to. Required when sync is
|
||||
* enabled (validated in environment.validation.ts); optional otherwise.
|
||||
|
||||
Reference in New Issue
Block a user