Prevent overlapping multi-node workspace operations and duplicate repository landings. - Add durable coordination leases, fence tokens, and land-intent persistence. - Fence workspace merge dispatches and repository publication across engine nodes. - Reconcile expired coordination state safely and cover lease lifecycle behavior. Files changed: .../fn-9059-workspace-durable-coordination.md | 7 + AGENTS.md | 1 + docs/architecture.md | 2 + docs/multi-project.md | 48 ++++ .../workspace-coordination-leases.pg.test.ts | 56 ++++ .../__tests__/postgres/workspace-leases.pg.test.ts | 112 ++++++++ packages/core/src/engine-node-identity.ts | 22 ++ packages/core/src/index.ts | 3 + .../0060_fn_9059_workspace_coordination_leases.sql | 10 + packages/core/src/postgres/schema-applier.ts | 13 +- packages/core/src/postgres/schema/project.ts | 31 ++ packages/core/src/store.ts | 18 ++ packages/core/src/task-store/workspace-leases.ts | 261 +++++++++++++++++ packages/core/src/tasks/workspace-lease-types.ts | 24 ++ .../engine/src/__tests__/project-engine.test.ts | 69 ++++- .../src/__tests__/self-healing-workspace.test.ts | 63 ++++- .../workspace-durable-coordination.test.ts | 49 ++++ .../src/__tests__/workspace-merger-lease.test.ts | 312 ++++++++++++++++++++- packages/engine/src/merge/merger-ai.ts | 277 ++++++++++++++++-- packages/engine/src/merge/workspace-fence-ref.ts | 171 +++++++++++ packages/engine/src/project-engine.ts | 175 ++++++++++-- packages/engine/src/runtimes/in-process-runtime.ts | 4 +- packages/engine/src/self-healing.ts | 191 ++++++++++++- packages/engine/src/util/run-audit.ts | 2 + .../engine/src/worktree/worktree-acquisition.ts | 43 ++- 25 files changed, 1901 insertions(+), 63 deletions(-) Fusion-Task-Id: FN-9059 Fusion-Task-Lineage: e51e3f54-69ee-4337-a218-4895d87474aa Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
23 lines
815 B
TypeScript
23 lines
815 B
TypeScript
import { hostname } from "node:os";
|
|
import { randomUUID } from "node:crypto";
|
|
|
|
let defaultNodeId: string | undefined;
|
|
let incarnationId: string | undefined;
|
|
|
|
/**
|
|
* FNXC:Workspace 2026-08-15-08:23:
|
|
* FUSION_NODE_ID names a deployment slot, not an authority to clear an
|
|
* unexpired lease. Without it, hostname-pid changes after restart, so recovery
|
|
* intentionally waits for TTL; the incarnation prevents restart inheritance.
|
|
*/
|
|
export function resolveEngineNodeId(): string {
|
|
const configured = process.env.FUSION_NODE_ID?.trim();
|
|
if (configured) return configured;
|
|
return defaultNodeId ??= `${hostname()}-${process.pid}`;
|
|
}
|
|
|
|
/** Per-process identity distinguishes a restarted slot from its predecessor. */
|
|
export function resolveEngineIncarnationId(): string {
|
|
return incarnationId ??= randomUUID();
|
|
}
|