Keep Git status and diffs current across platforms (#2775)

* fix(server): make Git observation cross-platform

Platform-specific watchers and forced full refreshes amplified Git processes and could miss nested changes. Share checkout and repository observation internally, scope final-state refreshes, and bound degraded polling so streamed summaries and diffs stay correct under bursts.

* fix(server): refresh Git worktree state on metadata changes

* fix(server): keep Git watcher runtime inputs current

* fix(server): normalize watcher runtime boundaries

* fix(server): reconcile Git observer topology

* test(server): report Git watcher event batches

* fix(server): close Git observation gaps

* chore(ci): remove temporary Git observation jobs
This commit is contained in:
Mohamed Boudra
2026-08-02 12:20:20 +02:00
committed by GitHub
parent f888bae04d
commit 0a106dd35f
16 changed files with 3558 additions and 631 deletions
@@ -0,0 +1,119 @@
import { appendFile } from "node:fs/promises";
interface GitCommandTraceContext {
id: string;
args: string[];
cwd: string;
submittedAtMs: number;
startedAtMs: number | null;
spawnedAtMs: number | null;
pid: number | null;
submittedQueue: GitCommandTraceQueueState;
startedQueue: GitCommandTraceQueueState | null;
settled: boolean;
}
interface GitCommandTraceQueueState {
active: number;
pending: number;
}
interface GitCommandTraceSettlement {
outcome: "closed" | "spawn_error" | "timed_out";
exitCode?: number | null;
signal?: NodeJS.Signals | null;
truncated?: boolean;
}
let nextTraceId = 1;
let pendingTraceWrite = Promise.resolve();
function appendTrace(event: Record<string, unknown>): void {
const tracePath = process.env.PASEO_GIT_TRACE_FILE?.trim();
if (!tracePath) return;
pendingTraceWrite = pendingTraceWrite
.then(() => appendFile(tracePath, `${JSON.stringify(event)}\n`, "utf8"))
.catch(() => {
// Diagnostic tracing must never change command execution.
});
}
export async function flushGitCommandTrace(): Promise<void> {
await pendingTraceWrite;
}
export function submitGitCommandTrace(
args: string[],
cwd: string,
queue: GitCommandTraceQueueState,
): GitCommandTraceContext | null {
if (!process.env.PASEO_GIT_TRACE_FILE?.trim()) return null;
const submittedAtMs = Date.now();
const context: GitCommandTraceContext = {
id: `${process.pid}:${nextTraceId++}`,
args: [...args],
cwd,
submittedAtMs,
startedAtMs: null,
spawnedAtMs: null,
pid: null,
submittedQueue: { ...queue },
startedQueue: null,
settled: false,
};
return context;
}
export function startGitCommandTrace(
context: GitCommandTraceContext | null,
queue: GitCommandTraceQueueState,
): void {
if (!context) return;
context.startedAtMs = Date.now();
context.startedQueue = { ...queue };
}
export function spawnGitCommandTrace(
context: GitCommandTraceContext | null,
pid: number | undefined,
): void {
if (!context) return;
context.spawnedAtMs = Date.now();
context.pid = pid ?? null;
}
export function settleGitCommandTrace(
context: GitCommandTraceContext | null,
settlement: GitCommandTraceSettlement,
): void {
if (!context || context.settled) return;
context.settled = true;
const atMs = Date.now();
appendTrace({
kind: "git_command",
event: "settled",
id: context.id,
atMs,
submittedAtMs: context.submittedAtMs,
startedAtMs: context.startedAtMs,
args: context.args,
cwd: context.cwd,
queueWaitMs: context.startedAtMs === null ? null : context.startedAtMs - context.submittedAtMs,
spawnCallMs:
context.startedAtMs === null || context.spawnedAtMs === null
? null
: context.spawnedAtMs - context.startedAtMs,
pid: context.pid,
queue: {
submitted: context.submittedQueue,
started: context.startedQueue,
},
durationMs: atMs - context.submittedAtMs,
...settlement,
});
}