openclaw/scripts/check-changed.d.mts
Peter Steinberger c5d6dcfc84
fix(scripts): run changed checks locally when Blacksmith never ran them (#114225)
* fix(scripts): run changed checks locally when Blacksmith never ran them

AGENTS.md already says trusted-source work falls back to local execution when
the remote backend is unavailable, but the tooling did not implement it: a lease,
broker, DNS, or network failure surfaced as a plain exit 1, so the lanes were
reported red without ever having been evaluated. That is worse than slow — a run
that never happened looked the same as a run that failed.

Tee the wrapper output and use its run summary as the discriminator. The summary
only appears once the command reached the box, so a failure carrying
`command-exit` is a real verdict and propagates unchanged; anything else never
produced one and re-runs locally, with a loud note so the proof summary records
which machine produced it.

Deliberately a positive test for `command-exit` rather than a blocklist of
infrastructure errors. Guessing wrong toward "infrastructure" only re-runs the
checks locally; guessing wrong toward "real failure" would block on an outage.
It must never widen to "fall back on any non-zero exit" — prompt snapshots are
Linux-only truth and would pass locally on macOS, turning a red gate green.

The sparse-checkout path keeps no fallback: it exists precisely because the
checkout cannot resolve the diff refs, so there is nothing local to run.

* fix(scripts): require positive pre-dispatch evidence before falling back

A missing run summary does not prove the remote never started: a wrapper that
crashes or loses its output transport after dispatch looks identical. Reading
that absence as "never ran" would rerun locally and could turn an unknown or
failing Linux-only lane green, which is the exact masking this guard exists to
prevent.

Require a positive pre-dispatch signature instead, and keep the command-exit
veto. Also reapply backpressure on the tee: inherited stdio got it from the OS,
piping does not, so a verbose delegated run could buffer its whole output here.
2026-07-26 22:02:36 -04:00

78 lines
3 KiB
TypeScript

import type { ChangedLaneResult } from "./changed-lanes.mjs";
export type ChangedCheckCommand = {
name: string;
args: string[];
bin?: string;
env?: NodeJS.ProcessEnv;
};
export type ChangedCheckPlan = {
commands: ChangedCheckCommand[];
summary: string;
};
export type ChangedCheckPlanOptions = {
env?: NodeJS.ProcessEnv;
staged?: boolean;
base?: string;
head?: string;
platform?: NodeJS.Platform;
swiftlintAvailable?: boolean;
};
export type TargetedLintOptions = {
fileExists?: (path: string) => boolean;
};
export type TargetedLintCommand = Required<
Pick<ChangedCheckCommand, "name" | "bin" | "args" | "env">
>;
export function createChangedCheckChildEnv(baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
export function changedCheckLocalDependenciesReady(cwd?: string): boolean;
export function changedCheckRequiresRemote(result?: ChangedLaneResult): boolean;
export function shouldDelegateChangedCheckToCrabbox(
argv?: string[],
env?: NodeJS.ProcessEnv,
options?: { cwd?: string; result?: ChangedLaneResult; diffRefsReady?: boolean },
): boolean;
export function buildChangedCheckCrabboxArgs(argv?: string[], options?: { cwd?: string }): string[];
export function delegationFailedBeforeRunning(output: string): boolean;
export function shouldRunNpmLockGuard(paths: string[]): boolean;
export function shouldRunPromptSnapshotCheck(paths: string[]): boolean;
export function shouldRunPromptSnapshotOwnerTest(paths: string[]): boolean;
export function shouldRunControlUiI18nVerify(paths: string[]): boolean;
export function shouldRunRuntimeSidecarBaselineCheck(paths: string[]): boolean;
export function shouldRunSqliteSessionSchemaBaselineCheck(paths: string[]): boolean;
export function shouldRunPluginSdkApiBaselineCheck(paths: string[]): boolean;
export function shouldRunPluginSdkSurfaceChecks(paths: string[]): boolean;
export function shouldRunDeprecationHygieneChecks(paths: string[]): boolean;
export function shouldRunCanvasA2uiNativeResourceCheck(paths: string[]): boolean;
export function shouldRunAppcastOwnerTest(paths: string[]): boolean;
export function shouldRunTestTempCreationReport(paths: string[]): boolean;
export function createNpmLockGuardCommand(paths: string[]): ChangedCheckCommand | null;
export function createChangedCheckPlan(
result: ChangedLaneResult,
options?: ChangedCheckPlanOptions,
): ChangedCheckPlan;
export function createTargetedCoreLintCommand(
paths: string[],
env?: NodeJS.ProcessEnv,
options?: TargetedLintOptions,
): TargetedLintCommand | null;
export function createTargetedExtensionLintCommand(
paths: string[],
env?: NodeJS.ProcessEnv,
options?: TargetedLintOptions,
): TargetedLintCommand | null;
export function createTargetedScriptLintCommand(
paths: string[],
env?: NodeJS.ProcessEnv,
options?: TargetedLintOptions,
): TargetedLintCommand | null;
export function createPnpmManagedCommand<T extends ChangedCheckCommand>(
command: T,
env?: NodeJS.ProcessEnv,
): T & { bin: string; env: NodeJS.ProcessEnv };
export function cleanupCorepackPnpmShimDir(): void;