Files
gitmost/packages/git-sync/build/engine/cycle.d.ts
claude code agent 227 ed3b65c36b Merge remote-tracking branch 'gitea/develop' into batch/issues-2026-06-25
# Conflicts:
#	apps/server/src/core/ai-chat/ai-chat.service.spec.ts
#	apps/server/src/core/ai-chat/ai-chat.service.ts
2026-06-25 12:48:47 +03:00

71 lines
3.0 KiB
TypeScript

import { VaultGit } from "./git.js";
import { GitSyncClient } from "./client.types.js";
import { Settings } from "./settings.js";
/**
* Absolute-path filesystem primitives the cycle needs. Injected (not imported)
* so the engine stays IO-free and unit-testable. `mkdir` is recursive; `rm` is
* force (a missing file is a no-op).
*/
export interface CycleFs {
readFile: (absPath: string) => Promise<string>;
writeFile: (absPath: string, text: string) => Promise<void>;
mkdir: (absDir: string) => Promise<void>;
rm: (absPath: string) => Promise<void>;
}
export interface RunCycleDeps {
spaceId: string;
/** The Docmost seam (reads for pull, writes for push). */
client: GitSyncClient;
/** The per-space git vault (a real working repo). */
vault: VaultGit;
/** Engine settings; `vaultPath` roots the relPath -> absolute-path mapping. */
settings: Settings;
fs: CycleFs;
log: (line: string) => void;
/**
* Delete-cap hook (the ONLY caller-specific policy). Called with the push
* dry-run's planned delete count (`Number.POSITIVE_INFINITY` when the dry-run
* itself failed, so the hook can fail safe) and the live client; returns the
* client to use for the REAL apply. The default (omitted) applies every op
* unmodified. gitmost uses it to neutralize deletes when over its cap.
*
* When omitted, NO dry-run is performed (one fewer push planning pass).
*/
resolveApplyClient?: (plannedDeletes: number, client: GitSyncClient) => GitSyncClient;
}
export interface RunCycleResult {
ran: boolean;
/** Set when the cycle short-circuited without running pull/push. */
skipped?: "merge-in-progress";
pull?: {
written: number;
deleted: number;
conflict: boolean;
};
push?: {
mode: string;
failures: number;
};
}
/**
* Run ONE full reconcile cycle for a space: PULL (Docmost -> vault) then PUSH
* (vault -> Docmost), under the engine's required branch choreography. This is
* the single entry point the app drives — it owns the staging order so it can
* never drift from the engine it ships with.
*
* Staging (the ⭐ data-loss-critical order, SPEC §6/§9):
* 1. assertGitAvailable + ensureRepo (the git state store must exist).
* 2. refuse on an unresolved merge (a prior conflicting pull); next checkout
* would fail otherwise.
* 3. ensureBranch('docmost','main') + checkout('docmost'). Pull writes MUST
* land on `docmost`, not `main`: applyPullActions commits on `docmost`,
* then checks out `main` and merges docmost -> main. Writing Docmost
* content straight onto `main` would clobber local file edits before push
* can diff them.
* 4. PULL: readExisting -> listSpaceTree -> computePullActions -> apply.
* 5. PUSH: optional dry-run to feed the delete-cap hook, then the real apply.
*
* Lock + cap POLICY live in the caller; this owns only the mechanics.
*/
export declare function runCycle(deps: RunCycleDeps): Promise<RunCycleResult>;