Skip baseline walk on git workspaces
`prepareRun` used to call `captureWorkspaceBaseline` on every workspace with a path, even when `.git` was present. The baseline was silently discarded by `collectChangedPaths` (the git branch wins) but the walk still paid for itself — an O(tree) scan on every run start, capped at 20k files, with the only effect being that the first 20k entries got captured before the capper truncated the tail. Collapse the decision into `captureBaselineIfRequired`: the function short-circuits to null for git workspaces so `git status` stays the sole source of truth, and only scans the tree when the baseline is the only source available. The call site in `runtime-bridge` now passes through without the per-call conditional.
This commit is contained in:
1 parent
925b0fae77
commit
aaa31ea5ae
2 files changed
+23
-16
No files matched your search
@@ -110,17 +110,24 @@ const BASELINE_SKIP_DIR_NAMES: ReadonlySet<string> = new Set([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk `workspacePath` and record the mtime of every non-directory
|
* Capture a run-start mtime baseline only for workspaces that need
|
||||||
* entry. Directories matching `BASELINE_SKIP_DIR_NAMES` are pruned at
|
* one. Git workspaces return null here because `git status` already
|
||||||
* walk time — the same categories the registrability filter rejects —
|
* provides the authoritative diff — paying for an O(tree) walk on
|
||||||
* so the baseline stays bounded on real project trees. Stops early at
|
* every run just to throw the result away is a hot-path tax the
|
||||||
|
* scheduler should not be paying.
|
||||||
|
*
|
||||||
|
* For non-git workspaces, walk the workspace and record the mtime of
|
||||||
|
* every non-directory entry. Directories matching
|
||||||
|
* `BASELINE_SKIP_DIR_NAMES` are pruned at walk time — the same
|
||||||
|
* categories the registrability filter rejects — so the baseline
|
||||||
|
* stays bounded on real project trees. The walker stops early at
|
||||||
* `MAX_BASELINE_ENTRIES` and flags `truncated`; the partial baseline
|
* `MAX_BASELINE_ENTRIES` and flags `truncated`; the partial baseline
|
||||||
* still lets the diff detect every file it saw, while the operator is
|
* still covers every path that was captured while the operator sees
|
||||||
* told via the skip reason that an oversize workspace fell off the
|
* the cap signal.
|
||||||
* tail.
|
|
||||||
*/
|
*/
|
||||||
export function captureWorkspaceBaseline(workspacePath: string): WorkspaceBaseline | null {
|
export function captureBaselineIfRequired(workspacePath: string | null): WorkspaceBaseline | null {
|
||||||
if (!workspacePath) return null;
|
if (!workspacePath) return null;
|
||||||
|
if (isGitRepo(workspacePath)) return null;
|
||||||
try {
|
try {
|
||||||
if (!statSync(workspacePath).isDirectory()) return null;
|
if (!statSync(workspacePath).isDirectory()) return null;
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import type { CredentialResolver } from "@main/credentials";
|
|||||||
import { getConnectorDefinition } from "@main/connectors";
|
import { getConnectorDefinition } from "@main/connectors";
|
||||||
import { projectInboxMessageToPi } from "./inbox-projection";
|
import { projectInboxMessageToPi } from "./inbox-projection";
|
||||||
import { projectAgentEventToLogChunk, extractTextBody } from "./agent-event-projection";
|
import { projectAgentEventToLogChunk, extractTextBody } from "./agent-event-projection";
|
||||||
import { captureWorkspaceBaseline, reconcileWorkspaceArtifacts } from "./artifact-projector";
|
import { captureBaselineIfRequired, reconcileWorkspaceArtifacts } from "./artifact-projector";
|
||||||
import {
|
import {
|
||||||
handleBeforeToolCall,
|
handleBeforeToolCall,
|
||||||
handleAfterToolCall,
|
handleAfterToolCall,
|
||||||
@@ -501,13 +501,13 @@ export class RuntimeBridge {
|
|||||||
workspaceId: string | null;
|
workspaceId: string | null;
|
||||||
workspacePath: string | null;
|
workspacePath: string | null;
|
||||||
};
|
};
|
||||||
// Capture an mtime baseline for non-git workspaces so `bash` and
|
// Capture an mtime baseline only for non-git workspaces so `bash`
|
||||||
// the end-of-run reconciliation can still diff changed files
|
// and the end-of-run reconciliation can still diff changed files
|
||||||
// against a known-start reference. Git workspaces leave the
|
// against a known-start reference. Git workspaces skip the walk —
|
||||||
// baseline as null — `git status` is the source of truth there.
|
// `git status` is the source of truth there, and paying for an
|
||||||
const baseline = payload.workspacePath
|
// O(tree) scan on every run just to throw the result away is a
|
||||||
? captureWorkspaceBaseline(payload.workspacePath)
|
// hot-path tax the scheduler should not be paying.
|
||||||
: null;
|
const baseline = captureBaselineIfRequired(payload.workspacePath);
|
||||||
this.registerActiveRun({
|
this.registerActiveRun({
|
||||||
runId,
|
runId,
|
||||||
agentId: payload.agentId,
|
agentId: payload.agentId,
|
||||||
|
|||||||
Reference in new issue
Block a user