chore(tooling): typecheck root test/** with a dedicated tsgo lane (#104475)

* chore(types): add declaration files for scripts/lib and scripts/e2e modules

* chore(types): add declaration files for top-level script modules (a-m)

* chore(types): add declaration files for top-level script modules (n-z)

* test: use a non-secret-shaped gateway token fixture

* test: type ci workflow guard helpers for the root test lane

* chore(tooling): typecheck root test/** with a dedicated tsgo lane

- test/tsconfig/tsconfig.test.root.json: root-test program (strict unused checks,
  fixtures excluded; two Docker E2E clients that import built dist/** stay out,
  same rationale as the scripts/e2e exclusion in tsconfig.scripts.json)
- tsgo:test:root wired into tsgo:test, check:test-types, scripts/check.mjs, and
  the ci.yml test-types shard, mirroring the tsgo:scripts lane (#104348)
- changed-lane routing: test/**/*.ts (excluding fixtures) and the lane tsconfig
  now trigger 'typecheck test root' in check:changed; previously test/ paths ran
  lint only, so harness type errors surfaced first in CI (#104287 envDir case)
- burn down all 1071 latent type errors in the program: precise param/local
  types across test/scripts, test/vitest, test/e2e, and transitive scripts/e2e
  program members; 205 sibling .d.mts declaration files for imported .mjs
  modules (committed separately); zero any, zero ts-expect-error
- resolve the pre-existing testing star-export ambiguity in
  scripts/e2e/parallels/common.ts with an explicit re-export

Closes #104388

* chore(types): correct declaration fidelity per structured review

- re-derive 51 .d.mts files from implementation data flow instead of
  initializers: fix a wrong never return (runTestProjectsDelegation returns
  the child), add encoding-sensitive exec/spawn overloads (plain-gh), restore
  the full release profile union, make parsed paths string | null, add missing
  parseArgs fields via help/non-help unions, add a missing sibling declaration
  (budget-number-args), drop 15 unused lint directives
- precise install-record/tuple typing removes the type-aware oxlint
  regressions the first declarations caused in scripts/e2e implementations
- route .mts declaration edits under test/ to the testRoot lane and reference
  the test-root project from tsconfig.projects.json so tsgo:all covers it
  (closes both review findings against the lane wiring)

* chore(scripts): keep telegram runner dist typing structural for the boundary guard

* chore(types): declare runtime pack and gateway readiness exports added on main

* test: pin the importTargetPlan form of the plugin-contract plan import

The guard expectation still referenced the raw await import( form that
7ae5996bb3 (#103975) replaced with the importTargetPlan fallback helper;
the assertion fails on current main.
This commit is contained in:
Peter Steinberger
2026-07-11 06:15:41 -07:00
committed by GitHub
parent e681646834
commit fe261b0f59
307 changed files with 8531 additions and 401 deletions
+6
View File
@@ -1472,6 +1472,12 @@ jobs:
echo "Current CI targets must provide the tsgo:scripts package script." >&2
exit 1
fi
if pnpm run --silent 2>/dev/null | grep -q '^ tsgo:test:root$'; then
pnpm tsgo:test:root
elif [[ "$HISTORICAL_TARGET" != "true" ]]; then
echo "Current CI targets must provide the tsgo:test:root package script." >&2
exit 1
fi
;;
*)
echo "Unsupported check task: $TASK" >&2
+2 -1
View File
@@ -1963,9 +1963,10 @@
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:extensions",
"tsgo:profile": "node scripts/profile-tsgo.mjs",
"tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo",
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test",
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test && pnpm tsgo:test:root",
"tsgo:test:extensions": "pnpm tsgo:extensions:test",
"tsgo:test:packages": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages.tsbuildinfo",
"tsgo:test:root": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.root.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-root.tsbuildinfo",
"tsgo:test:src": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo",
"tsgo:test:ui": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-ui.tsbuildinfo",
"tui": "node scripts/run-node.mjs tui",
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env node
export function describeSeamKinds(relativePath: unknown, source: unknown): string[];
export function determineSeamTestStatus(
seamKinds: unknown,
relatedTestMatches: unknown,
): {
status: string;
reason: string;
};
export function main(argv?: string[]): Promise<void>;
export const HELP_TEXT: "Usage: node scripts/audit-seams.mjs [--help]\n\nAudit repo seam inventory and emit JSON to stdout.\n\nSections:\n duplicatedSeamFamilies Plugin SDK seam families imported from multiple production files\n overlapFiles Production files that touch multiple seam families\n optionalClusterStaticLeaks Optional extension/plugin clusters referenced from the static graph\n missingPackages Workspace packages whose deps are not mirrored at the root\n seamTestInventory High-signal seam candidates with nearby-test gap signals,\n including cron orchestration seams for agent handoff,\n outbound/media delivery, heartbeat/followup handoff,\n and scheduler state crossings, plus subagent seams\n for spawn/session handoff, announce delivery,\n lifecycle registry, cleanup, and parent streaming\n\nNotes:\n - Output is JSON only.\n - For clean redirected JSON through package scripts, prefer:\n pnpm --silent audit:seams > seam-inventory.json\n";
+24
View File
@@ -0,0 +1,24 @@
export function parseArgs(argv: unknown): {
maxWorkers?: unknown;
cwd: string;
mode: unknown;
ref: unknown;
rss: unknown;
};
export function parseMaxRssBytes(output: unknown): number | null;
export function formatRss(valueBytes: unknown): string;
export function resolveBenchRssResult({
label,
output,
rss,
status,
}: {
label: unknown;
output: unknown;
rss: unknown;
status: unknown;
}): {
maxRssBytes: number | null;
output: unknown;
status: unknown;
};
+92
View File
@@ -0,0 +1,92 @@
import type fs from "node:fs";
export type BuildCacheEntry =
| string
| {
path: string;
extensions?: string[];
recursive?: boolean;
};
export type BuildAllStep = {
label: string;
kind?: "node" | "pnpm";
args?: string[];
pnpmArgs?: string[];
env?: NodeJS.ProcessEnv;
windowsNodeOptions?: string;
cache?: {
env?: string[];
inputs: BuildCacheEntry[];
outputs: BuildCacheEntry[];
restore?: "always";
};
};
export type BuildAllCacheState = {
cacheable: boolean;
fresh: boolean;
restorable?: boolean;
reason: string;
signature?: string;
outputRoot?: string;
stampPath?: string;
inputFiles?: number;
outputFiles?: number;
relativeOutputFiles?: string[];
stampedOutputs?: string[];
};
export const BUILD_ALL_STEPS: BuildAllStep[];
export const BUILD_ALL_PROFILES: Record<string, string[]>;
export const BUILD_ALL_PROFILE_STEP_ENV: Record<string, Record<string, NodeJS.ProcessEnv>>;
export function buildAllUsage(): string;
export function parseBuildAllArgs(argv: string[]): { help: boolean; profile: string };
export function resolveBuildAllSteps(profile?: string): BuildAllStep[];
export function resolveBuildAllEnvironment(
env?: NodeJS.ProcessEnv,
now?: () => Date,
readGitCommit?: () => string | null,
): { [key: string]: string | undefined; OPENCLAW_BUILD_TIMESTAMP: string };
export function resolveBuildAllStep(
step: BuildAllStep,
params?: {
platform?: NodeJS.Platform;
env?: NodeJS.ProcessEnv;
nodeExecPath?: string;
npmExecPath?: string;
comSpec?: string;
},
): {
command: string;
args: string[];
options: {
stdio: "inherit";
env: NodeJS.ProcessEnv;
shell?: boolean;
windowsVerbatimArguments?: boolean;
};
};
export function resolveBuildAllStepCacheState(
step: BuildAllStep,
params?: { rootDir?: string; fs?: typeof fs; env?: NodeJS.ProcessEnv },
): BuildAllCacheState;
export function writeBuildAllStepCacheStamp(
step: BuildAllStep,
cacheState: BuildAllCacheState,
params?: { rootDir?: string; fs?: typeof fs },
): void;
export function resolveBuildAllStepCacheStampState(
step: BuildAllStep,
cacheState: BuildAllCacheState,
params?: { rootDir?: string; fs?: typeof fs },
): BuildAllCacheState;
export function restoreBuildAllStepCacheOutputs(
cacheState: BuildAllCacheState,
params?: { rootDir?: string; fs?: typeof fs },
): boolean;
export function formatBuildAllDuration(durationMs: number): string;
export function formatBuildAllTimingSummary(
timings: Array<{ label: string; durationMs: number; status: string }>,
): string;
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env node
/**
* Creates the esbuild plugin that neutralizes Pierre diffs' browser side-effect import.
*/
export function createPierreDiffsSideEffectImportPlugin(): {
name: string;
setup(buildContext: unknown): void;
};
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env node
/**
* Reads bundled plugin asset hook commands for a build or copy phase.
*/
export function readBundledPluginAssetHooks(options?: Record<string, unknown>): Promise<
{
aliases: string[];
command: string;
packageName: unknown;
phase: unknown;
pluginDir: string;
pluginId: string;
}[]
>;
/**
* Runs bundled plugin asset hook commands for the selected phase/plugins.
*/
export function runBundledPluginAssetHooks(options?: Record<string, unknown>): Promise<void>;
/**
* Parses `--phase` and repeated `--plugin` flags for asset hook scripts.
*/
export function parseBundledPluginAssetArgs(argv: unknown): {
phase: unknown;
plugins: unknown[];
};
+55
View File
@@ -0,0 +1,55 @@
export type ChangedLane =
| "core"
| "coreTests"
| "extensions"
| "extensionTests"
| "scripts"
| "testRoot"
| "apps"
| "docs"
| "tooling"
| "liveDockerTooling"
| "releaseMetadata"
| "all";
export type ChangedLanes = Record<ChangedLane, boolean>;
export type ChangedLaneResult = {
paths: string[];
lanes: ChangedLanes;
extensionImpactFromCore: boolean;
docsOnly: boolean;
reasons: string[];
};
export type DetectChangedLanesOptions = {
packageJsonChangeKind?: "liveDockerTooling" | "tooling" | null;
};
export function normalizeChangedPath(inputPath: unknown): string;
export function createEmptyChangedLanes(): ChangedLanes;
export function isChangedLaneTestPath(changedPath: string): boolean;
export function detectChangedLanes(
changedPaths: string[],
options?: DetectChangedLanesOptions,
): ChangedLaneResult;
export function detectChangedLanesForPaths(params: {
paths: string[];
base: string;
head?: string;
staged?: boolean;
mergeHeadFirstParent?: boolean;
}): ChangedLaneResult;
export function listChangedPathsFromGit(params: {
base: string;
head?: string;
includeWorktree?: boolean;
cwd?: string;
mergeHeadFirstParent?: boolean;
}): string[];
export function listStagedChangedPaths(cwd?: string): string[];
export function isLiveDockerPackageScriptOnlyChange(before: string, after: string): boolean;
export function isPackageScriptOnlyChange(before: string, after: string): boolean;
export const LIVE_DOCKER_AUTH_SHELL_TARGETS: string[];
export const RELEASE_METADATA_PATHS: Set<string>;
+9 -1
View File
@@ -15,6 +15,8 @@ const EXTENSION_PATH_RE = /^extensions\/[^/]+(?:\/|$)/u;
const CORE_PATH_RE = /^(?:src\/|ui\/|packages\/)/u;
const SCRIPTS_TYPECHECK_PATH_RE =
/^(?:scripts\/.*\.(?:[cm]?ts|[cm]?tsx)|tsconfig\.scripts\.json)$/u;
const TEST_ROOT_TYPECHECK_PATH_RE =
/^(?:test\/(?!fixtures\/).*\.(?:[cm]?ts|[cm]?tsx)|test\/tsconfig\/tsconfig\.test\.root\.json)$/u;
const TOOLING_PATH_RE =
/^(?:scripts\/|test\/vitest\/|\.github\/|\.vscode\/|config\/|deploy\/|git-hooks\/|Dockerfile\.sandbox(?:-(?:browser|common))?$|Makefile$|docker-setup\.sh$|setup-podman\.sh$|openclaw\.podman\.env$|skills\/pyproject\.toml$|vitest(?:\..+)?\.config\.ts$|tsconfig.*\.json$|\.dockerignore$|\.gitignore$|\.jscpd\.json$|\.npmignore$|\.pre-commit-config\.yaml$|\.swiftformat$|\.swiftlint\.yml$|\.oxlint.*|\.oxfmt.*)/u;
const ROOT_GLOBAL_PATH_RE =
@@ -56,7 +58,7 @@ export const RELEASE_METADATA_PATHS = new Set([
"package.json",
]);
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "testRoot" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
/**
* @typedef {{
@@ -88,6 +90,7 @@ export function createEmptyChangedLanes() {
extensions: false,
extensionTests: false,
scripts: false,
testRoot: false,
apps: false,
docs: false,
tooling: false,
@@ -145,6 +148,9 @@ export function detectChangedLanes(changedPaths, options = {}) {
if (SCRIPTS_TYPECHECK_PATH_RE.test(changedPath)) {
lanes.scripts = true;
}
if (TEST_ROOT_TYPECHECK_PATH_RE.test(changedPath)) {
lanes.testRoot = true;
}
if (DOCS_PATH_RE.test(changedPath)) {
lanes.docs = true;
@@ -299,12 +305,14 @@ export function listChangedPathsFromGit(params) {
let rangePaths;
let noMergeBase = false;
try {
// oxlint-disable-next-line typescript/no-base-to-string, typescript/restrict-template-expressions -- resolveMergeHeadDiffBase returns a git ref string when present.
rangePaths = runGitNameOnlyDiff([`${base}...${head}`], cwd);
} catch (error) {
if (!isGitNoMergeBaseError(error)) {
throw error;
}
noMergeBase = true;
// oxlint-disable-next-line typescript/no-base-to-string, typescript/restrict-template-expressions -- resolveMergeHeadDiffBase returns a git ref string when present.
rangePaths = runGitNameOnlyDiff([`${base}..${head}`], cwd);
}
if (params.includeWorktree === false) {
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env node
/**
* Collects architecture smell findings from the configured source roots.
*/
export function collectArchitectureSmells(): Promise<
Array<{
category: string;
file: string;
line: number;
kind: string;
specifier: string;
reason: string;
}>
>;
/**
* Runs the architecture smell check and writes human/JSON output.
*/
export function main(argv: unknown, io: unknown): Promise<number>;
+69
View File
@@ -0,0 +1,69 @@
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 shouldDelegateChangedCheckToCrabbox(
argv?: string[],
env?: NodeJS.ProcessEnv,
): boolean;
export function buildChangedCheckCrabboxArgs(argv?: string[], options?: { cwd?: string }): string[];
export function shouldRunShrinkwrapGuard(paths: string[]): boolean;
export function shouldRunPromptSnapshotCheck(paths: string[]): boolean;
export function shouldRunPromptSnapshotOwnerTest(paths: string[]): boolean;
export function shouldRunRuntimeSidecarBaselineCheck(paths: string[]): boolean;
export function shouldRunCanvasA2uiNativeResourceCheck(paths: string[]): boolean;
export function shouldRunAppcastOwnerTest(paths: string[]): boolean;
export function shouldRunTestTempCreationReport(paths: string[]): boolean;
export function createShrinkwrapGuardCommand(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;
+3
View File
@@ -394,6 +394,9 @@ export function createChangedCheckPlan(result, options = {}) {
if (lanes.scripts) {
addTypecheck("typecheck scripts", ["tsgo:scripts"]);
}
if (lanes.testRoot) {
addTypecheck("typecheck test root", ["tsgo:test:root"]);
}
if (lanes.core || lanes.coreTests) {
const coreLintCommand = createTargetedCoreLintCommand(result.paths, baseEnv);
@@ -0,0 +1,20 @@
#!/usr/bin/env node
/**
* Reports whether a handle is forbidden in changelog thanks text.
*/
export function isForbiddenChangelogThanksHandle(
handle: unknown,
options?: Record<string, unknown>,
): boolean;
/**
* Reports whether a handle needs a separate human credit.
*/
export function requiresExplicitHumanChangelogThanks(handle: unknown): boolean;
/**
* Finds changelog lines that thank forbidden handles.
*/
export function findForbiddenChangelogThanks(content: unknown): unknown;
/**
* Runs the changelog attribution check.
*/
export function main(argv?: string[]): Promise<void>;
@@ -0,0 +1,31 @@
#!/usr/bin/env node
/**
* Finds channel-specific references inside channel-agnostic protected sources.
*/
export function findChannelAgnosticBoundaryViolations(
content: unknown,
fileName?: string,
options?: Record<string, unknown>,
): unknown[];
/**
* Finds reverse dependencies from channel core into plugin/runtime surfaces.
*/
export function findChannelCoreReverseDependencyViolations(
content: unknown,
fileName?: string,
): unknown[];
/**
* Finds user-facing channel names in ACP-owned text sources.
*/
export function findAcpUserFacingChannelNameViolations(
content: unknown,
fileName?: string,
): unknown[];
/**
* Finds raw system mark literals where shared constants should be used.
*/
export function findSystemMarkLiteralViolations(content: unknown, fileName?: string): unknown[];
/**
* Runs all channel-agnostic boundary checks.
*/
export function main(): Promise<void>;
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env node
export namespace testing {
export { cases };
export { nodeImportSpecifierForPath };
export { parseArgs };
export { readPositiveIntEnv };
export { readPositiveNumberEnv };
export { repoRoot };
export { resolveDefaultLimitsMb };
export { runCase };
export { runStartupMemoryCheck };
}
declare const cases: {
id: string;
label: string;
args: string[];
limitMb: unknown;
}[];
declare function nodeImportSpecifierForPath(filePath: unknown): string;
declare function parseArgs(argv: unknown): {
jsonPath: string;
summaryPath: string;
};
declare function readPositiveIntEnv(
name: unknown,
fallback: unknown,
env?: NodeJS.ProcessEnv,
): unknown;
declare function readPositiveNumberEnv(
name: unknown,
fallback: unknown,
env?: NodeJS.ProcessEnv,
): unknown;
declare const repoRoot: string;
declare function resolveDefaultLimitsMb(platform?: NodeJS.Platform): {
help: number;
pluginsList: number;
statusJson: number;
gatewayStatus: number;
};
declare function runCase(
testCase: unknown,
params?: Record<string, unknown>,
): {
id: unknown;
label: unknown;
command: string;
limitMb: unknown;
maxRssMb: number | null;
status: string;
exitCode: unknown;
signal: unknown;
error: string | null;
};
declare function runStartupMemoryCheck(
argv?: string[],
params?: Record<string, unknown>,
): {
skipped: boolean;
results: {
id: unknown;
label: unknown;
command: string;
limitMb: unknown;
maxRssMb: number | null;
status: string;
exitCode: unknown;
signal: unknown;
error: string | null;
}[];
};
@@ -0,0 +1,19 @@
#!/usr/bin/env node
export function collectDatabaseFirstLegacyStoreSourceFiles(
sourceRoots: string[],
): Promise<string[]>;
/**
* Finds database-first legacy-store violations in one TypeScript/JavaScript source file.
*/
export function collectDatabaseFirstLegacyStoreViolations(
content: string,
relativePath?: string,
scanOptions?: Record<string, unknown>,
): {
kind: string;
line: number;
}[];
/**
* Runs the database-first legacy-store guard.
*/
export function main(): Promise<void>;
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* Parses compact knip output into unused file paths.
*/
export function parseKnipCompactUnusedFiles(output: unknown): unknown[];
/**
* Compares detected unused files against the checked-in allowlist.
*/
export function compareUnusedFilesToAllowlist(
actualFiles: unknown,
allowlistFiles: unknown,
optionalAllowlistFiles?: unknown[],
): {
actual: unknown[];
allowed: unknown[];
unexpected: unknown[];
stale: unknown[];
duplicateAllowedCount: number;
allowlistIsSorted: boolean;
};
/**
* Runs knip and returns parsed unused-file results.
*/
export function runKnipUnusedFiles(params?: Record<string, unknown>): Promise<unknown>;
/**
* Checks detected unused files against the current allowlist.
*/
export function checkUnusedFiles(
output: unknown,
allowlistFiles?: string[],
optionalAllowlistFiles?: string[],
): {
ok: boolean;
comparison: {
actual: unknown[];
allowed: unknown[];
unexpected: unknown[];
stale: unknown[];
duplicateAllowedCount: number;
allowlistIsSorted: boolean;
};
message: string;
};
/**
* Maximum buffered knip output retained for diagnostics.
*/
export const KNIP_MAX_BUFFER_BYTES: number;
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Collects dependency pin violations for the current workspace.
*/
export function collectDependencyPinViolations(cwd?: string): unknown[];
/**
* Runs the dependency pin check.
*/
export function main(): Promise<void>;
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env node
export function parseArgs(argv: unknown): {
base: string;
head: string;
};
export type TermMatch = {
file: string;
line: number;
kind: "title" | "link label";
term: string;
};
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Parses docs MDX check arguments.
*/
export function parseArgs(argv: unknown): {
roots: unknown[];
jsonOut: string;
maxErrors: number;
};
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Finds dynamic import advisories in a single source file.
*/
export function findDynamicImportAdvisories(content: unknown, fileName?: string): unknown[];
/**
* Runs the dynamic import advisory check.
*/
export function main(argv?: string[]): Promise<void>;
@@ -0,0 +1,89 @@
#!/usr/bin/env node
/**
* Resolves the compile worker count from CLI/env/default settings.
*/
export function resolveCompileConcurrency(
env?: NodeJS.ProcessEnv,
availableParallelism?: number,
): number;
/**
* Appends child-process output while preserving only the diagnostic tail.
*/
export function appendBoundedStepOutput(
buffer: unknown,
chunk: unknown,
maxChars?: number,
): {
text: string;
truncatedChars: unknown;
};
/**
* Formats the successful boundary compile summary.
*/
export function formatBoundaryCheckSuccessSummary(params?: Record<string, unknown>): string;
/**
* Formats skipped compile progress for fresh extension canaries.
*/
export function formatSkippedCompileProgress(params?: Record<string, unknown>): string;
/**
* Formats slow extension compile diagnostics.
*/
export function formatSlowCompileSummary(params?: Record<string, unknown>): string;
/**
* Formats a failed boundary-check child process step.
*/
export function formatStepFailure(label: unknown, params?: Record<string, unknown>): string;
/**
* Checks whether an extension boundary compile canary is still fresh.
*/
export function isBoundaryCompileFresh(
extensionId: unknown,
params?: Record<string, unknown>,
): boolean;
/**
* Runs one node-based boundary check step with timeout and output capture.
*/
export function runNodeStepAsync(
label: unknown,
args: unknown,
timeoutMs: unknown,
params?: Record<string, unknown>,
): Promise<unknown>;
/**
* Runs boundary check steps with bounded concurrency.
*/
export function runNodeStepsWithConcurrency(steps: unknown, concurrency: unknown): Promise<void>;
/**
* Resolves canary artifact paths for an extension boundary compile.
*/
export function resolveCanaryArtifactPaths(
extensionId: unknown,
rootDir?: string,
): {
extensionRoot: string;
canaryPath: string;
tsconfigPath: string;
};
/**
* Removes canary artifacts for multiple extensions.
*/
export function cleanupCanaryArtifactsForExtensions(extensionIds: unknown, rootDir?: string): void;
/**
* Installs signal/exit cleanup for extension canary artifacts.
*/
export function installCanaryArtifactCleanup(
extensionIds: unknown,
params?: Record<string, unknown>,
): () => void;
/**
* Resolves the local lock path for extension boundary checks.
*/
export function resolveBoundaryCheckLockPath(rootDir?: string): string;
/**
* Acquires the single-process lock for extension boundary checks.
*/
export function acquireBoundaryCheckLock(params?: Record<string, unknown>): () => void;
/**
* Runs the extension package TypeScript boundary check.
*/
export function main(argv?: string[]): Promise<void>;
@@ -0,0 +1,19 @@
#!/usr/bin/env node
/**
* Reads the checked-in expected boundary inventory.
*/
export function readExpectedInventory(mode: unknown): Promise<unknown>;
/**
* Diffs expected and actual boundary inventory entries.
*/
export function diffInventory(
expected: unknown,
actual: unknown,
): {
missing: unknown;
unexpected: unknown;
};
/**
* Entrypoint wrapper for the extension plugin SDK boundary check.
*/
export function main(argv: unknown, io: unknown): Promise<1 | 0>;
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Finds local wildcard re-export lines in a barrel source string.
*/
export function findLocalWildcardReexports(source: unknown): unknown;
/**
* Runs the extension wildcard re-export guard.
*/
export function main(argv?: string[], io?: NodeJS.Process): Promise<0 | 1>;
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env node
export namespace testing {
export { hasPrivateQaDist };
export { parseArgs };
export { readStartupReport };
export { runGatewayCpuScenarios };
export { validateStartupReport };
}
declare function hasPrivateQaDist(repoRoot: unknown, fsImpl?: typeof fs): boolean;
declare function parseArgs(argv: string[]): {
outputDir: string;
startupCases: string[];
qaScenarios: string[];
runs: number;
warmup: number;
skipStartup: boolean;
skipQa: boolean;
cpuCoreWarn: number;
hotWallWarnMs: number;
};
declare function readStartupReport(startupOutput: unknown):
| {
diagnosticFailure: string;
diagnosticDetail: string;
report: null;
}
| {
diagnosticFailure: null;
diagnosticDetail: null;
report: unknown;
};
declare function runGatewayCpuScenarios(
options: unknown,
params?: Record<string, unknown>,
): Promise<{
exitCode: number;
summary: {
options: {
startupCases: unknown;
qaScenarios: unknown;
runs: unknown;
warmup: unknown;
cpuCoreWarn: unknown;
hotWallWarnMs: unknown;
qaStateDir: string | null;
};
steps: {
error?: unknown;
name: unknown;
status: unknown;
signal: unknown;
}[];
observations: (
| {
kind: string;
id: unknown;
cpuCoreRatioMax: number;
wallMsMax: number;
cpuCoreRatio?: undefined;
wallMs?: undefined;
}
| {
kind: string;
id: string;
cpuCoreRatio: number;
wallMs: number;
cpuCoreRatioMax?: undefined;
wallMsMax?: undefined;
}
)[];
qaSummaryFailure?: string | undefined;
qaSummaryFailureDetail?: string | null | undefined;
startupReportFailure?: string | undefined;
startupReportFailureDetail?: string | null | undefined;
generatedAt: string;
outputDir: unknown;
startupOutput: string | null;
qaSummary: string | null;
};
}>;
declare function validateStartupReport(
report: unknown,
):
| "startup report must be a JSON Record<string, unknown>"
| "startup report missing results array"
| "startup report has no measured results"
| null;
import fs from "node:fs";
@@ -0,0 +1,156 @@
#!/usr/bin/env node
/**
* Appends watch output while preserving only the diagnostic tail.
*/
export function appendBoundedWatchLog(
current: unknown,
chunk: unknown,
maxChars?: number,
): {
text: string;
truncated: boolean;
};
/**
* Updates bounded watch-build detection state from new output.
*/
export function updateWatchBuildDetection(
state: unknown,
chunk: unknown,
): {
buffer: string;
triggered: unknown;
reason: unknown;
};
/**
* Parses a safe non-negative integer CLI value.
*/
export function readNonNegativeInteger(value: unknown, label: unknown): number;
/**
* Parses gateway watch regression CLI arguments.
*/
export function parseArgs(argv: unknown): {
outputDir: string;
windowMs: number;
readyTimeoutMs: number;
readySettleMs: number;
sigkillGraceMs: number;
sigkillExitGraceMs: number;
cpuWarnMs: number;
cpuFailMs: number;
distRuntimeFileGrowthMax: number;
distRuntimeByteGrowthMax: number;
keepLogs: boolean;
skipBuild: boolean;
};
/**
* Reports whether gateway watch output contains a ready marker.
*/
export function hasGatewayReadyLog(text: unknown): boolean;
export function resolveTimedWatchShell(deps?: Record<string, unknown>): string;
export function buildTimedWatchCommand(
pidFilePath: unknown,
timeFilePath: unknown,
isolatedHomeDir: unknown,
port: unknown,
deps?: Record<string, unknown>,
):
| {
command: string;
args: unknown[];
env: {
OPENCLAW_DISABLE_BONJOUR: string;
OPENCLAW_SKIP_ACPX_RUNTIME: string;
OPENCLAW_SKIP_ACPX_RUNTIME_PROBE: string;
OPENCLAW_SKIP_BROWSER_CONTROL_SERVER: string;
OPENCLAW_SKIP_CANVAS_HOST: string;
OPENCLAW_SKIP_CHANNELS: string;
OPENCLAW_SKIP_CRON: string;
OPENCLAW_SKIP_GMAIL_WATCHER: string;
OPENCLAW_RUNTIME_POSTBUILD_STATIC_ASSETS: string;
OPENCLAW_TEST_MINIMAL_GATEWAY: string;
NODE_ENV: string;
OPENCLAW_WATCH_PID_FILE: unknown;
HOME: unknown;
OPENCLAW_HOME: unknown;
OPENCLAW_CONFIG_PATH: string;
OPENCLAW_STATE_DIR: string;
PATH: string;
XDG_CONFIG_HOME: string;
};
}
| {
command: unknown;
args: string[];
env: {
OPENCLAW_DISABLE_BONJOUR: string;
OPENCLAW_SKIP_ACPX_RUNTIME: string;
OPENCLAW_SKIP_ACPX_RUNTIME_PROBE: string;
OPENCLAW_SKIP_BROWSER_CONTROL_SERVER: string;
OPENCLAW_SKIP_CANVAS_HOST: string;
OPENCLAW_SKIP_CHANNELS: string;
OPENCLAW_SKIP_CRON: string;
OPENCLAW_SKIP_GMAIL_WATCHER: string;
OPENCLAW_RUNTIME_POSTBUILD_STATIC_ASSETS: string;
OPENCLAW_TEST_MINIMAL_GATEWAY: string;
NODE_ENV: string;
OPENCLAW_WATCH_PID_FILE: unknown;
HOME: unknown;
OPENCLAW_HOME: unknown;
OPENCLAW_CONFIG_PATH: string;
OPENCLAW_STATE_DIR: string;
PATH: string;
XDG_CONFIG_HOME: string;
};
};
/**
* Runs a bounded gateway watch process and captures timing/log artifacts.
*/
export function runTimedWatch(
options: unknown,
outputDir: unknown,
deps?: Record<string, unknown>,
): Promise<{
exit: unknown;
spawnError: unknown;
timingFileMissing: boolean;
timing: unknown;
readyBeforeWindow: boolean;
exitedBeforeReady: boolean;
exitedBeforeStop: boolean;
idleCpuMs: number | null;
stdoutPath: string;
stderrPath: string;
timeFilePath: string;
watchTriggeredBuild: boolean;
watchBuildReason: string | null;
}>;
/**
* Stops the timed watch child process with TERM/KILL fallback.
*/
export function stopTimedWatchChild(
child: unknown,
watchPid: unknown,
options: unknown,
deps?: Record<string, unknown>,
): Promise<unknown>;
/**
* Reports whether restored CI artifacts need fresh build stamps.
*/
export function shouldRefreshBuildStampForRestoredArtifacts(params: unknown): boolean;
/**
* Writes build and runtime-postbuild stamps for the current artifact set.
*/
export function writeBuildAndRuntimePostBuildStamps(params?: Record<string, unknown>): void;
/**
* Collects pass/fail findings for the bounded gateway watch regression run.
*/
export function collectGatewayWatchFindings(params: unknown): {
failures: string[];
warnings: string[];
};
export function shouldReportDuplicateDistRuntimeRegression(failures: unknown): unknown;
/**
* Maximum retained stdout/stderr text for gateway watch diagnostics.
*/
export const WATCH_LOG_CAPTURE_MAX_CHARS: number;
export const WATCH_LOG_FAILURE_TAIL_CHARS: 12000;
+192
View File
@@ -0,0 +1,192 @@
#!/usr/bin/env node
/**
* Parses a safe non-negative integer option.
*/
export function readNumber(value: unknown, label: unknown): number;
/**
* Parses a safe positive integer option.
*/
export function readPositiveNumber(value: unknown, label: unknown): number;
/**
* Parses memory FD repro CLI arguments and environment fallbacks.
*/
export function parseArgs(argv: string[]): {
fileCount: number;
mode: "fixed" | "leak" | "report";
maxWorkspaceRegFds: number;
minLeakedFds: number;
invokeTimeoutMs: number;
sampleDelayMs: number;
settleDelayMs: number;
outputDir: string;
keep: boolean;
allowNonDarwin: boolean;
};
/**
* Writes isolated OpenClaw config for the synthetic memory workspace.
*/
export function writeConfig({
homeDir,
workspaceDir,
port,
token,
}: {
homeDir: unknown;
workspaceDir: unknown;
port: unknown;
token: unknown;
}): string;
/**
* Updates bounded gateway-ready output state from a stdout/stderr chunk.
*/
export function updateGatewayReadyOutputState(
state: unknown,
chunk: unknown,
maxChars?: number,
): {
tail: string;
readySeen: boolean;
};
/**
* Reports whether a spawned child has already exited.
*/
export function hasChildExited(child: unknown): boolean;
/**
* Waits until gateway output and listener state both indicate readiness.
*/
export function waitForGatewayReady({
child,
port,
logPath,
timeoutMs,
}: {
child: unknown;
port: unknown;
logPath: unknown;
timeoutMs: unknown;
}): Promise<void>;
/**
* Stops the gateway child using the default process/runtime hooks.
*/
export function stopGateway({ child, port }: { child: unknown; port: unknown }): Promise<void>;
/**
* Stops the gateway child and unknown remaining listener process.
*/
export function stopGatewayWithRuntime({
child,
childExitPollIntervalMs,
childExitPolls,
port,
findGatewayPidFn,
killProcess,
listenerSettleDelayMs,
}: {
child: unknown;
childExitPollIntervalMs?: number | undefined;
childExitPolls?: number | undefined;
port: unknown;
findGatewayPidFn: unknown;
killProcess: unknown;
listenerSettleDelayMs?: number | undefined;
}): Promise<void>;
/**
* Classifies the memory_search HTTP response into success/error details.
*/
export function classifyMemorySearchInvokeResponse({
httpOk,
status,
bodyText,
}: {
httpOk: unknown;
status: unknown;
bodyText: unknown;
}):
| {
ok: boolean;
httpOk: unknown;
status: unknown;
gatewayOk: boolean | undefined;
error: string;
}
| {
ok: boolean;
httpOk: unknown;
status: unknown;
error: string;
gatewayOk?: undefined;
}
| {
error?: string | undefined;
toolError?: string | undefined;
ok: boolean;
httpOk: unknown;
status: unknown;
gatewayOk: boolean | undefined;
resultCount: unknown;
toolDisabled: boolean;
toolUnavailable: boolean;
};
export function invokeMemorySearch({
port,
token,
timeoutMs,
}: {
port: unknown;
token: unknown;
timeoutMs: unknown;
}): Promise<
| {
durationMs: number;
bodyPreview: string;
ok: boolean;
httpOk: unknown;
status: unknown;
gatewayOk: boolean | undefined;
error: string;
aborted?: undefined;
}
| {
durationMs: number;
bodyPreview: string;
ok: boolean;
httpOk: unknown;
status: unknown;
error: string;
gatewayOk?: undefined;
aborted?: undefined;
}
| {
durationMs: number;
bodyPreview: string;
error?: string | undefined;
toolError?: string | undefined;
ok: boolean;
httpOk: unknown;
status: unknown;
gatewayOk: boolean | undefined;
resultCount: unknown;
toolDisabled: boolean;
toolUnavailable: boolean;
aborted?: undefined;
}
| {
ok: boolean;
aborted: boolean;
durationMs: number;
error: string;
}
>;
/**
* Maximum gateway-ready output tail retained while waiting for startup.
*/
export const GATEWAY_READY_OUTPUT_MAX_CHARS: number;
/**
* Maximum bytes read from the memory_search HTTP response.
*/
export const MEMORY_SEARCH_RESPONSE_MAX_BYTES: number;
/**
* Probe query expected to hit the synthetic top-level memory file.
*/
export const MEMORY_SEARCH_PROBE_QUERY: "Top-level memory file";
export { readBoundedResponseText };
import { readBoundedResponseText } from "./lib/bounded-response.mjs";
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env node
/**
* Returns one-based line numbers containing merge conflict markers.
*/
export function findConflictMarkerLines(content: unknown): unknown[];
/**
* Lists tracked files in the repository.
*/
export function listTrackedFiles(cwd?: string): string[];
/**
* Scans files for merge conflict markers, skipping binary content.
*/
export function findConflictMarkersInFiles(
filePaths: unknown,
readFile?: typeof fs.readFileSync,
): {
filePath: unknown;
lines: unknown[];
}[];
/**
* Finds merge conflict markers in tracked repository files.
*/
export function findConflictMarkersInTrackedFiles(cwd?: string): {
filePath: unknown;
lines: unknown[];
}[];
/**
* Runs the merge conflict marker check.
*/
export function main(): Promise<void>;
import fs from "node:fs";
@@ -0,0 +1,13 @@
#!/usr/bin/env node
/**
* Finds `os.tmpdir()` or imported `tmpdir()` call lines in source.
*/
export function findMessagingTmpdirCallLines(content: unknown, fileName?: string): unknown[];
/**
* Runs the messaging tmpdir guard.
*/
export function main(): Promise<void>;
/**
* Source roots scanned for unsafe messaging tmpdir usage.
*/
export const messagingTmpdirGuardSourceRoots: string[];
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Finds raw `window.open(...)` or `globalThis.open(...)` call lines.
*/
export function findRawWindowOpenLines(content: unknown, fileName?: string): unknown[];
/**
* Runs the raw window.open guard.
*/
export function main(): Promise<void>;
+9
View File
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Collects disallowed package patch declarations and patch files.
*/
export function collectPackagePatchViolations(cwd?: string): unknown[];
/**
* Runs the package patch guard.
*/
export function main(): Promise<void>;
@@ -0,0 +1,39 @@
#!/usr/bin/env node
/**
* Diffs expected and actual plugin-extension boundary inventory entries.
*/
export function diffInventory(
expected: unknown,
actual: unknown,
): {
missing: unknown;
unexpected: unknown;
};
/**
* Entrypoint wrapper for the plugin-extension import boundary check.
*/
export function main(argv: unknown, io: unknown): Promise<1 | 0>;
/**
* Cached inventory of src/plugins imports that cross into bundled extensions.
*/
export const collectPluginExtensionImportBoundaryInventory: () => Promise<
Array<{
file: string;
line: number;
kind: string;
specifier: string;
reason: string;
}>
>;
/**
* Cached expected plugin-extension import inventory baseline.
*/
export const readExpectedInventory: () => Promise<
Array<{
file: string;
line: number;
kind: string;
specifier: string;
reason: string;
}>
>;
@@ -0,0 +1,97 @@
#!/usr/bin/env node
/**
* Parses plugin gateway gauntlet CLI arguments and env defaults.
*/
export function parseArgs(argv: string[]): {
repoRoot: string;
outputDir: string;
pluginIds: string[];
shardTotal: number;
shardIndex: number;
limit: number | undefined;
skipPrebuild: boolean;
skipLifecycle: boolean;
skipQa: boolean;
qaBaseline: boolean;
skipSlashHelp: boolean;
qaScenarios: string[];
qaPluginChunkSize: number;
cpuCoreWarn: number;
hotWallWarnMs: number;
maxRssWarnMb: number;
wallAnomalyMultiplier: number;
rssAnomalyMultiplier: number;
qaCpuRegressionMultiplier: number;
qaWallRegressionMultiplier: number;
commandTimeoutMs: number;
buildTimeoutMs: number;
qaTimeoutMs: number;
allowEmpty: boolean;
failOnObservation: boolean;
keepRunRoot: boolean;
};
export function buildObservationGuardFailures(observations: unknown, enabled?: boolean): unknown;
/**
* Builds the command that prepares QA runtime artifacts before gauntlet probes.
*/
export function createGauntletPrebuildCommand(repoRoot: unknown): {
command: string;
args: string[];
};
/**
* Converts an output path to a repo-relative path, rejecting paths outside the repo.
*/
export function toRepoRelativePath(repoRoot: unknown, absolutePath: unknown): string;
/**
* Parses `/usr/bin/time` output into wall, CPU, and RSS metrics.
*/
export function parseTimedMetrics(
stderr: unknown,
wallMs: unknown,
mode: unknown,
): {
wallMs: unknown;
cpuMs: number | null;
cpuCoreRatio: number | null;
maxRssMb: number | null;
};
/**
* Runs a measured command through the live process implementation.
*/
export type GauntletMeasuredRow = {
diagnosticFailure?: string;
logPath: string | null;
logWriteError?: string;
spawnError?: { code?: string };
status: number;
timedOut: boolean;
wallMs: number;
};
export type GauntletMeasuredCommandParams = {
[key: string]: unknown;
args: string[];
command: string;
consoleOutputMaxBytes?: number;
cwd: string;
env: NodeJS.ProcessEnv;
label: string;
logDir: string;
maxBufferBytes?: number;
phase: string;
timeoutKillGraceMs?: number;
timeoutMs: number;
timeMode?: string;
};
export function runMeasuredCommand(
params: GauntletMeasuredCommandParams,
): Promise<GauntletMeasuredRow>;
/**
* Runs one command with optional timing wrapper, bounded output, and log capture.
*/
export function runMeasuredCommandLive(
params: GauntletMeasuredCommandParams,
): Promise<GauntletMeasuredRow>;
/**
* Reports whether gauntlet result rows contain work beyond the prebuild step.
*/
export function hasGauntletWorkRows(rows: unknown): unknown;
@@ -0,0 +1,21 @@
#!/usr/bin/env node
export function parseArgs(argv: unknown):
| {
help: true;
packageDirs: string[];
}
| {
packageDirs: string[];
help?: undefined;
};
/**
* Builds publishable plugin npm runtimes and verifies declared outputs exist.
*/
export function checkPluginNpmRuntimeBuilds(params?: Record<string, unknown>): Promise<
{
pluginDir: string;
status: string;
entryCount: number;
copiedStaticAssets: string[];
}[]
>;
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Finds wildcard plugin SDK re-export lines in an extension API barrel.
*/
export function findPluginSdkWildcardReexports(source: unknown): unknown;
/**
* Runs the plugin SDK wildcard re-export guard.
*/
export function main(argv?: string[], io?: NodeJS.Process): Promise<0 | 1>;
@@ -0,0 +1,36 @@
#!/usr/bin/env node
/**
* Extracts the gateway event name list from server-methods-list.ts source.
* Bare identifiers in the array (e.g. GATEWAY_EVENT_UPDATE_AVAILABLE) are
* resolved against constantsSource (src/gateway/events.ts).
*/
export function extractGatewayEventNames(listSource: unknown, constantsSource: unknown): string[];
/**
* Extracts qualified static string constants declared at Swift type scope.
* Type qualification avoids resolving unrelated constants that share a short
* member name elsewhere in the app.
*/
export function extractSwiftStaticStringConstants(source: unknown): Map<unknown, unknown>;
/** Extracts Swift gateway-event case labels, including qualified constants. */
export function extractSwiftHandledEvents(
source: unknown,
constants?: Map<unknown, unknown>,
): Set<unknown>;
/**
* Extracts event names a Kotlin source handles: string-literal case labels of
* `when (event)` blocks plus `event == "..."` comparisons, both scoped to
* `fun handle*Event(...)` bodies. Scoping matters: bare `event == "..."`
* literals also appear in predicate helpers that are not called from the
* dispatch path (e.g. gatewayEventInvalidatesNodesDevices in NodeRuntime.kt),
* and counting those would silently mark events as covered. Swift extraction
* stays tree-wide because Swift consumption always reads `.event` off a
* received EventFrame, which does not have that false-positive shape.
*/
export function extractKotlinHandledEvents(source: unknown): Set<unknown>;
/**
* Compares a client's handled events against the gateway catalog and its
* allowlist. Returns human-readable error strings. Client-only names (e.g. the
* client-synthesized "seqGap" pseudo-event) are intentionally ignored; this
* check only guards the server->client direction.
*/
export function compareEventCoverage(params: unknown): string[];
@@ -0,0 +1,8 @@
#!/usr/bin/env node
export function parseArgs(argv: string[]): {
staged: boolean;
base: string;
head: string;
paths: string[];
};
export function main(argv?: string[]): void;
@@ -0,0 +1,14 @@
export type RuntimeSidecarLoaderViolation = {
line: number;
specifier: string;
sourcePath: string;
reason: string;
};
export function collectTsdownEntrySources(
config: Array<{ entry?: Record<string, string> }>,
): Set<string>;
export function findRuntimeSidecarLoaderViolations(
content: string,
importerPath: string,
explicitEntrySources: Set<string>,
): RuntimeSidecarLoaderViolation[];
@@ -0,0 +1,5 @@
#!/usr/bin/env node
/**
* Entrypoint for the SDK-package extension import boundary checker.
*/
export const main: (argv: unknown, io: unknown) => Promise<1 | 0>;
@@ -0,0 +1,73 @@
#!/usr/bin/env node
export function collectSessionStoreRuntimeFileBackedCompatExports(
content: unknown,
fileName?: string,
): Map<unknown, unknown>;
export function findSessionStoreRuntimeFileBackedCompatExportViolations(
content: unknown,
fileName?: string,
): {
line: unknown;
reason: string;
}[];
export function findSessionAccessorBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findEmbeddedAgentSessionTargetViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findSessionAccessorWriteBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findTranscriptWriterBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findGatewaySessionCreateLifecycleViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findSessionCompactManualTrimBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findSessionLifecycleCleanupBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function findMemoryHostSessionCorpusBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
/** Ratchet compare: counts above baseline are regressions, below are improvements. */
export function compareSessionAccessorDebt(
currentCounts: unknown,
baselineCounts: unknown,
): {
regressions: {
concern: string;
path: string;
currentCount: unknown;
baselineCount: unknown;
}[];
improvements: {
concern: string;
path: string;
currentCount: unknown;
baselineCount: unknown;
}[];
};
export function formatSessionAccessorDebtImprovements(improvements: unknown): unknown[];
export function main(): Promise<void>;
export const allowedSessionStoreRuntimeFileBackedCompatExports: Set<string>;
export const migratedSessionAccessorFiles: Set<string>;
export const migratedBundledPluginSessionAccessorFiles: Set<string>;
export const migratedEmbeddedAgentSessionTargetFiles: Set<string>;
export const migratedSessionAccessorWriteFiles: Set<string>;
export const migratedTranscriptWriterFiles: Set<string>;
export const migratedSessionCompactManualTrimFiles: Set<string>;
export const migratedSessionLifecycleCleanupFiles: Set<string>;
export const migratedMemoryHostSessionCorpusFiles: Set<string>;
@@ -0,0 +1,7 @@
#!/usr/bin/env node
export function findSessionTranscriptReaderBoundaryViolations(
content: unknown,
fileName?: string,
): unknown[];
export function main(): Promise<void>;
export const migratedSessionTranscriptReaderFiles: Set<string>;
@@ -0,0 +1,5 @@
#!/usr/bin/env node
/**
* Entrypoint for the src extension import boundary checker.
*/
export const main: (argv: unknown, io: unknown) => Promise<1 | 0>;
@@ -0,0 +1,9 @@
#!/usr/bin/env node
/**
* Collects test-helper extension import boundary inventory.
*/
export const collectTestHelperExtensionImportBoundaryInventory: () => Promise<unknown>;
/**
* Entrypoint for the test-helper extension import boundary checker.
*/
export const main: (argv: unknown, io: unknown) => Promise<1 | 0>;
@@ -0,0 +1,16 @@
#!/usr/bin/env node
/**
* Collects web-fetch provider boundary violations in core source files.
*/
export function collectWebFetchProviderBoundaryViolations(): Promise<
Array<{
file: string;
line: number;
provider: string;
reason: string;
}>
>;
/**
* Runs the web-fetch provider boundary check.
*/
export function main(argv: unknown, io: unknown): Promise<1 | 0>;
@@ -0,0 +1,37 @@
#!/usr/bin/env node
/**
* Collects web-search provider boundary inventory from core source files.
*/
export function collectWebSearchProviderBoundaryInventory(): Promise<
Array<{
file: string;
line: number;
provider: string;
reason: string;
}>
>;
/**
* Reads the expected web-search provider boundary inventory baseline.
*/
export function readExpectedInventory(): Promise<
Array<{
file: string;
line: number;
provider: string;
reason: string;
}>
>;
/**
* Diffs expected and actual web-search provider boundary inventory entries.
*/
export function diffInventory(
expected: unknown,
actual: unknown,
): {
missing: unknown;
unexpected: unknown;
};
/**
* Entrypoint wrapper for the web-search provider boundary check.
*/
export function main(argv: unknown, io: unknown): Promise<1 | 0>;
+19
View File
@@ -0,0 +1,19 @@
/**
* Returns command usage text for the aggregate check runner.
*/
export function usage(): string;
/**
* Runs selected repository check lanes.
*/
export function main(argv?: string[]): Promise<void>;
/**
* Runs one managed check command and returns timing/status details.
*/
export function runCommand(
command: unknown,
runManagedCommandImpl?: (options: { args: string[]; bin: string }) => Promise<number>,
): Promise<{
name: unknown;
durationMs: number;
status: number;
}>;
+1
View File
@@ -119,6 +119,7 @@ export async function main(argv = process.argv.slice(2)) {
: [
{ name: "typecheck prod", args: ["tsgo:prod"] },
{ name: "typecheck scripts", args: ["tsgo:scripts"] },
{ name: "typecheck test root", args: ["tsgo:test:root"] },
],
},
{
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env node
export function isRetryableGhJsonErrorMessage(message: unknown): boolean;
/**
* Flattens paginated GitHub run job responses.
*/
export function collectRunJobsFromPages(
pages: Array<{ jobs?: Array<Record<string, unknown>> }>,
): Array<Record<string, unknown>>;
/**
* Summarizes longest jobs and total timing for a workflow run.
*/
export function summarizeRunTimings(
run: unknown,
limit?: number,
): {
byDuration: Array<{ name: string; durationSeconds: number }>;
byQueue: Array<{ name: string; queueSeconds: number }>;
conclusion: unknown;
status: unknown;
wallSeconds: number | null;
badJobs: unknown;
};
/**
* Summarizes pnpm store warmup overlap near run start.
*/
export function summarizePnpmStoreWarmupBarrier(
run: unknown,
windowSeconds?: number,
): {
activePostWarmupJobCount: unknown;
firstPostWarmupStartDelaySeconds: number | null;
postWarmupP95StartDelaySeconds: unknown;
postWarmupStartedWithinWindow: unknown;
preflightToWarmupCompleteSeconds: number | null;
preflightToWarmupStartSeconds: number | null;
warmupDurationSeconds: number | null;
warmupResult: string;
windowSeconds: number;
} | null;
/**
* Selects the latest main push CI run, optionally matching a head SHA.
*/
export function selectLatestMainPushCiRun(
runs: Array<Record<string, unknown>>,
headSha?: string | null,
): Record<string, unknown> | null;
/**
* Parses CI run timing CLI arguments.
*/
export function parseRunTimingArgs(args: unknown): {
explicitRunId: unknown;
limit: number;
recentLimit: number | null;
useLatestMain: boolean;
};
@@ -0,0 +1,66 @@
/**
* Parses comma-separated PR numbers from CLI/env input.
*/
export function parsePrNumberList(value: unknown): number[];
/**
* Parses duplicate PR close workflow arguments.
*/
export function parseArgs(
argv: string[],
env?: NodeJS.ProcessEnv,
):
| {
apply: boolean;
duplicates: number[];
help: true;
labels: string[];
landedPr?: number;
repo: string;
}
| {
apply: boolean;
duplicates: number[];
help?: undefined;
labels: string[];
landedPr: number;
repo: string;
};
/**
* Parses changed hunk ranges from unified diff text.
*/
export function parseUnifiedDiffRanges(diffText: unknown): Map<unknown, unknown>;
/**
* Builds the close/skip plan for duplicate PR candidates.
*/
export function buildDuplicateClosePlan({
candidates,
diffs,
landed,
repo,
}: {
candidates: unknown;
diffs: unknown;
landed: unknown;
repo: unknown;
}): Array<Record<string, unknown>>;
/**
* Applies labels/comments/closes for planned duplicate PR actions.
*/
export function applyClosePlan({
labels,
plan,
repo,
runGh,
}: {
labels?: string[] | undefined;
plan: unknown;
repo: unknown;
runGh: unknown;
}): void;
/**
* Runs the duplicate PR close workflow.
*/
export function runDuplicateCloseWorkflow(
args: unknown,
runGh?: (args: string[], options?: Record<string, unknown>) => string,
): Array<Record<string, unknown>>;
+3
View File
@@ -0,0 +1,3 @@
export function canonicalProviderName(provider: unknown): unknown;
export function parseProvidersFromHelp(text: unknown): unknown[];
export function isProviderAdvertised(provider: unknown, advertisedProviders: unknown): unknown;
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env node
/**
* Creates a structured dependency diff report from base/head payloads.
*/
export function createDependencyChangesReport({
basePayload,
headPayload,
dependencyFileChanges,
baseLabel,
headLabel,
generatedAt,
}: {
basePayload: unknown;
headPayload: unknown;
dependencyFileChanges?:
| Array<{ status: string; path: string; oldPath: string | null }>
| undefined;
baseLabel?: string | undefined;
headLabel?: string | undefined;
generatedAt?: string | undefined;
}): {
generatedAt: string;
baseLabel: string;
headLabel: string;
summary: {
basePackages: number;
headPackages: number;
addedPackages: number;
removedPackages: number;
changedPackages: number;
dependencyFileChanges: number;
};
dependencyFileChanges: unknown[];
addedPackages: {
packageName: string;
versions: unknown[];
}[];
removedPackages: {
packageName: string;
versions: unknown[];
}[];
changedPackages: {
packageName: string;
addedVersions: unknown[];
removedVersions: unknown[];
}[];
};
/**
* Reports whether a path is a dependency-related file.
*/
export function isDependencyFile(filePath: unknown): boolean;
/**
* Returns git pathspecs used for dependency diff collection.
*/
export function dependencyDiffPathspecs(): string[];
export function parseArgs(argv: string[]):
| {
rootDir: string;
baseRef: string;
baseLockfile: null;
headLockfile: string;
jsonPath: string | null;
markdownPath: string | null;
}
| {
rootDir: string;
baseRef: null;
baseLockfile: string;
headLockfile: string;
jsonPath: string | null;
markdownPath: string | null;
};
/**
* Runs the dependency changes report CLI.
*/
export function main(argv?: string[]): Promise<number>;
@@ -0,0 +1,90 @@
#!/usr/bin/env node
/**
* Extracts the package name from a pnpm lockfile package key.
*/
export function packageNameFromLockKey(lockKey: unknown): unknown;
/**
* Collects dependency ownership and transitive surface metadata.
*/
export function collectDependencyOwnershipSurfaceReport(params?: Record<string, unknown>): {
schemaVersion: number;
generatedAt: string;
target: {
packageName: unknown;
packageVersion: unknown;
gitBranch: string | null;
gitCommit: string | null;
lockfile: string;
ownershipMetadata: string;
};
summary: {
importerCount: number;
lockfilePackageCount: number;
rootDirectDependencyCount: number;
rootClosurePackageCount: number;
rootOwnershipRecordCount: number;
buildRiskPackageCount: number;
};
ownershipGaps: string[];
staleOwnershipRecords: string[];
ownershipWarnings: {
name: string;
owner: unknown;
sourceSections: unknown[];
message: string;
}[];
buildRiskPackages: {
name: unknown;
lockKey: string;
requiresBuild: boolean;
hasBin: boolean;
platformRestricted: boolean;
}[];
topRootDependencyCones: {
name: string;
specifier: unknown;
section: string;
resolved: string;
owner: unknown;
class: unknown;
risk: unknown;
sourceCategory: string | null;
sourceSections: unknown[];
sourceFileCount: number;
closureSize: number;
missingSnapshotKeys: unknown[];
}[];
rootDependencies: {
name: string;
specifier: unknown;
section: string;
resolved: string;
owner: unknown;
class: unknown;
risk: unknown;
sourceCategory: string | null;
sourceSections: unknown[];
sourceFileCount: number;
closureSize: number;
missingSnapshotKeys: unknown[];
}[];
importerClosures: {
importer: string;
directDependencyCount: number;
closureSize: number;
}[];
};
/**
* Collects policy errors from a dependency ownership surface report.
*/
export function collectDependencyOwnershipSurfaceCheckErrors(report: unknown): unknown;
/**
* Renders a dependency ownership surface report as Markdown.
*/
export function renderDependencyOwnershipSurfaceMarkdownReport(report: unknown): string;
export function parseArgs(argv: string[]): {
asJson: boolean;
check: boolean;
jsonPath: string | null;
markdownPath: string | null;
};
@@ -0,0 +1,60 @@
#!/usr/bin/env node
/**
* Classifies npm advisory findings into report-only findings and hard blockers.
*/
export type VulnerabilityAdvisory = {
id: string;
severity: string;
title: string;
url: string;
vulnerable_versions: string;
};
export type VulnerabilityFinding = VulnerabilityAdvisory & {
malware: boolean;
packageName: string;
production: boolean;
};
export function classifyVulnerabilityFindings({
allAdvisories,
productionAdvisories,
}: {
allAdvisories: Record<string, VulnerabilityAdvisory[]>;
productionAdvisories: Record<string, VulnerabilityAdvisory[]>;
}): {
blockers: VulnerabilityFinding[];
findings: VulnerabilityFinding[];
};
/**
* Runs the dependency vulnerability gate against pnpm-lock.yaml.
*/
export function runDependencyVulnerabilityGate({
rootDir,
fetchImpl,
}?: {
rootDir?: string | undefined;
fetchImpl?: typeof fetch | undefined;
}): Promise<{
blockers: VulnerabilityFinding[];
findings: VulnerabilityFinding[];
generatedAt: string;
policy: {
blocks: string[];
reports: string[];
vulnerabilityExceptions: boolean;
};
graphs: {
all: {
packages: number;
packageVersions: unknown;
};
production: {
packages: number;
packageVersions: unknown;
};
};
}>;
/**
* Renders the dependency vulnerability gate report as Markdown.
*/
export function renderDependencyVulnerabilityGateMarkdownReport(report: unknown): string;
export function main(argv?: string[]): Promise<1 | 0>;
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env node
export function parseArgs(argv: unknown): {
target: string;
sourceRepo: string;
sourceSha: string;
clawhubRepo: string;
clawhubSourceRepo: string;
clawhubSourceSha: string;
};
/**
* Resolves the local ClawHub repository path used for docs mirroring.
*/
export function resolveClawHubRepoPath(value?: string, options?: Record<string, unknown>): string;
/**
* Mirrors ClawHub docs into the target docs tree.
*/
export function syncClawHubDocsTree(
targetDocsDir: unknown,
options?: Record<string, unknown>,
): {
repository: unknown;
sha: unknown;
path: string;
files: number;
};
@@ -162,7 +162,9 @@ async function runCronCleanupScenario(params: {
gateway: GatewayRpcClient;
pidPath: string;
}): Promise<{ jobId: string; runId?: string; pid: number; status?: unknown }> {
const { assert, waitFor } = await loadMcpChannelsHarness();
const harness = await loadMcpChannelsHarness();
const assert: McpChannelsHarness["assert"] = harness.assert;
const { waitFor } = harness;
const { gateway, pidPath } = params;
const job = await gateway.request<CronJob>("cron.add", {
name: "cron mcp cleanup docker e2e",
@@ -245,7 +247,8 @@ async function runSubagentCleanupScenario(params: {
pidsPath: string;
exitPath: string;
}): Promise<{ runId: string; exitedPids: number[]; pids: number[] }> {
const { assert } = await loadMcpChannelsHarness();
const harness = await loadMcpChannelsHarness();
const assert: McpChannelsHarness["assert"] = harness.assert;
const { gateway, pidPath, pidsPath, exitPath } = params;
await resetProbeFiles({ pidPath, pidsPath, exitPath });
@@ -295,7 +298,9 @@ async function runSubagentCleanupScenario(params: {
}
async function main() {
const { assert, connectGateway } = await loadMcpChannelsHarness();
const harness = await loadMcpChannelsHarness();
const assert: McpChannelsHarness["assert"] = harness.assert;
const { connectGateway } = harness;
const gatewayUrl = process.env.GW_URL?.trim();
const gatewayToken = process.env.GW_TOKEN?.trim();
const stateDir = process.env.OPENCLAW_STATE_DIR?.trim() || path.join(os.homedir(), ".openclaw");
+195
View File
@@ -0,0 +1,195 @@
export function shouldPrintHelp(argv: string[]): boolean;
export function validateCliArgs(argv: string[]): void;
export function readPositiveInt(raw: string | undefined, fallback: number, label?: string): number;
export function readPositiveTimerMs(
raw: string | undefined,
fallback: number,
label?: string,
): number;
export function resolveKitchenSinkRpcConfig(env?: NodeJS.ProcessEnv): {
commandMaxRssMiB: number;
commandTimeoutMs: number;
fetchBodyMaxBytes: number;
fetchTimeoutMs: number;
installTimeoutMs: number;
maxRssMiB: number;
outputCaptureChars: number;
readyTimeoutMs: number;
rpcTimeoutMs: number;
};
export function resolveKitchenSinkRpcPort(
env?: NodeJS.ProcessEnv,
options?: { findAvailablePort?: () => Promise<number> },
): Promise<number>;
export function makeEnv(): {
root: string;
env: {
HOME: string;
USERPROFILE: string;
OPENCLAW_HOME: string;
OPENCLAW_STATE_DIR: string;
OPENCLAW_CONFIG_PATH: string;
OPENCLAW_NO_ONBOARD: string;
OPENCLAW_SKIP_PROVIDERS: string;
OPENCLAW_KITCHEN_SINK_PERSONALITY: string;
};
};
export function cleanupKitchenSinkEnv(
root: string,
options?: {
attempts?: number;
delayMs?: number;
throwOnFailure?: boolean;
warn?: boolean;
},
): Promise<boolean>;
export function appendBoundedOutput(
buffer: { text: string; truncatedChars: number },
chunk: string | Uint8Array,
maxChars?: number,
): {
text: string;
truncatedChars: number;
};
export function runCommand(
command: string,
args: string[],
options?: Record<string, unknown>,
): Promise<{
stderr: string;
stdout: string;
stderrTruncatedChars: number;
stdoutTruncatedChars: number;
}>;
export function signalProcessGroup(
child: { pid?: number; kill(signal?: NodeJS.Signals): unknown },
signal: NodeJS.Signals,
{
platform,
runTaskkill,
useProcessGroup,
}?: {
platform?: NodeJS.Platform | undefined;
runTaskkill?:
| ((
command: string,
args: string[],
options: { stdio: "ignore" },
) => { error?: Error; status: number | null })
| undefined;
useProcessGroup?: boolean | undefined;
},
): void;
export function parseJsonOutput(stdout: string): Record<string, unknown>;
export function parseGatewayCliRequestFailure(error: unknown):
| (Error & {
retryAfterMs?: number;
retryable: boolean;
details?: Record<string, unknown>;
name: string;
gatewayCode: string;
})
| null;
export function unwrapRpcPayload(raw: unknown): Record<string, unknown>;
export function createRpcCliRunOptions(
method: string,
options?: { env?: NodeJS.ProcessEnv; commandResourceOptions?: Record<string, unknown> },
): Record<string, unknown> & { resourceLabel: string; timeoutMs: number };
export function findDistCallGatewayModuleFiles(cwd?: string): string[];
export function usesBuiltOpenClawEntry(
runner: unknown,
cwd?: string,
env?: NodeJS.ProcessEnv,
): boolean;
export function fetchJson(
url: unknown,
options?: Record<string, unknown>,
): Promise<{
ok: unknown;
status: unknown;
body: unknown;
}>;
export function readBoundedResponseText(
response: unknown,
byteLimit: number,
timeoutPromise?: Promise<never>,
): Promise<string>;
export function stopGateway(child: unknown, options?: Record<string, unknown>): Promise<void>;
export function hasChildExited(child: unknown): boolean;
export function signalGateway(
child: unknown,
signal: unknown,
killProcess?: typeof defaultKillProcess,
options?: Record<string, unknown>,
): boolean;
export function createGatewayReadyLogScanner(logPath: unknown, marker?: string): () => boolean;
export function waitForGatewayReady(
child: unknown,
port: unknown,
logPath: unknown,
options?: Record<string, unknown>,
): Promise<void>;
export function extractPluginCommandNames(payload: unknown): unknown[];
export function assertExpectedKitchenSinkToolEntries(
entries: unknown,
label: unknown,
{
requirePluginProvenance,
}?: {
requirePluginProvenance?: boolean | undefined;
},
): unknown;
export function assertChannelAccountRunning(payload: unknown): unknown;
export function extractTtsProviderIds(payload: unknown, surface: unknown): unknown[];
export function assertTtsProviderCoverage(payload: unknown, surface: unknown): void;
export function assertKitchenSinkSearchInvokeResult(payload: unknown): void;
export function assertKitchenSinkTextInvokeResult(payload: unknown): void;
export function assertKitchenSinkImageJobInvokeResult(payload: unknown): void;
export function listKitchenSinkToolInvokeNames(): string[];
export function listKitchenSinkReadOnlyRpcProbeNames(): string[];
export function listKitchenSinkAuthorizationRpcProbeNames(): string[];
export function assertOperatorRpcDenied(probe: unknown, call: unknown): Promise<void>;
export function assertCreatedKitchenSinkSession(payload: unknown, expectedKey?: string): unknown;
export function assertKitchenSinkUiDescriptors(
payload: unknown,
options?: Record<string, unknown>,
): unknown;
export function assertDiagnosticStabilityClean(payload: unknown): void;
export function assertGatewayHealthPayload(payload: unknown): void;
export function assertGatewayStatusPayload(payload: unknown): void;
export function sampleProcess(
pid: unknown,
options?: Record<string, unknown>,
): Promise<{
aggregateRssMiB: number;
rssMiB: number;
cpuPercent: unknown;
processId: unknown;
} | null>;
export function summarizeProcessSamples(samples: unknown): unknown;
export function sampleWindowsProcessByPort(
port: unknown,
options?: Record<string, unknown>,
): Promise<
| {
rssMiB: number;
aggregateRssMiB: number;
cpuPercent: null;
cpuSeconds: number | null;
processId: number;
}
| {
rssMiB: number;
cpuPercent: null;
cpuSeconds: null;
processId: number;
}
| null
>;
export function assertResourceCeiling(sample: unknown): void;
export function assertCommandResourceCeiling(sample: unknown): void;
export function findErrorLogFindings(logPath: string): Array<{ line: string; lineNumber: number }>;
export function tailFile(file: string, maxBytes?: number): string;
export function main(): Promise<void>;
export const MAX_KITCHEN_SINK_TIMER_TIMEOUT_MS: 2147000000;
declare function defaultKillProcess(pid: unknown, signal: unknown): true;
+3
View File
@@ -0,0 +1,3 @@
export function extractAgentReplyTexts(text: string): string[];
export function assertAgentReplyContainsMarker(marker: string, outputPath: string): void;
export function assertOpenAiRequestLogUsed(requestLogPath: string, label?: string): void;
@@ -0,0 +1,6 @@
export function readBoundedResponseText(
response: unknown,
label: unknown,
byteLimit: unknown,
timeoutPromise?: Promise<never>,
): Promise<string>;
+14
View File
@@ -0,0 +1,14 @@
export function stateDir(): string;
export function configPath(): string;
export function managedNpmRoot(): string;
export function realPathMaybe(filePath: string): string;
export function assertPathInside(parentPath: string, childPath: string, label: string): void;
import type { PluginInstallRecord } from "./plugin-index-sqlite.mjs";
export function readInstallRecords(
fallbackRecords?: Record<string, PluginInstallRecord>,
): Record<string, PluginInstallRecord>;
export function npmProjectRootForInstalledPackage(installPath: string, packageName: string): string;
export function findPackageJson(packageName: string, roots: string[]): string | undefined;
export { readJson };
import { readJson } from "./fixtures/common.mjs";
@@ -0,0 +1,6 @@
export function createJsonlRequestTailer(
filePath: string,
options?: { historyLimit?: number; maxReadBytes?: number; tailLineLimit?: number },
): {
read(): unknown[];
};
@@ -0,0 +1,6 @@
export function readPositiveIntEnv(
name: unknown,
fallback: unknown,
env?: NodeJS.ProcessEnv,
): number;
export function readTcpPortEnv(name: unknown, fallback: unknown, env?: NodeJS.ProcessEnv): number;
@@ -24,12 +24,12 @@ if (!codexRecord) {
if (codexRecord.source !== "npm") {
throw new Error(`expected npm codex install record, got ${codexRecord.source}`);
}
if (!String(codexRecord.spec || "").includes("@openclaw/codex")) {
if (!codexRecord.spec?.includes("@openclaw/codex")) {
throw new Error(`expected @openclaw/codex install spec, got ${codexRecord.spec}`);
}
const npmRoot = managedNpmRoot();
const installPath = String(codexRecord.installPath || "").replace(/^~(?=$|\/)/u, process.env.HOME);
const installPath = (codexRecord.installPath || "").replace(/^~(?=$|\/)/u, process.env.HOME);
if (!installPath) {
throw new Error(`missing codex installPath: ${JSON.stringify(codexRecord)}`);
}
@@ -0,0 +1,6 @@
export function createConfigReloadLogScanner(
logPath: string,
options?: { maxReadBytes?: number; tailLineLimit?: number },
): {
scan(): { reloadLines: string[]; restartLines: string[]; tailLines: string[] };
};
+11
View File
@@ -0,0 +1,11 @@
export type FixtureJson = Record<string, unknown> & {
bin?: string | { codex?: string };
name?: string;
};
export function json(value: unknown): string;
export function readJson(file: string): FixtureJson;
export function write(file: string, contents: string | NodeJS.ArrayBufferView): void;
export function writeJson(file: string, value: unknown): void;
export function requireArg(value: string | undefined, name: string): string;
export function assert(condition: unknown, message: string): asserts condition;
@@ -0,0 +1,2 @@
export function parseMockOpenAiPort(value: unknown, label?: string): number;
export function applyMockOpenAiModelConfig(cfg: unknown, params: unknown): void;
+4 -2
View File
@@ -72,12 +72,14 @@ function assertAgentsDeleteResult([outputPath]) {
const message = error instanceof Error ? error.message.split("\n").at(0) : String(error);
throw new Error(`agents delete --json parse failed: ${message}`, { cause: error });
}
for (const [actual, expected, label] of [
/** @type {Array<[unknown, unknown, string]>} */
const comparisons = [
[parsed.agentId, "ops", "agentId"],
[parsed.workspace, process.env.SHARED_WORKSPACE, "workspace"],
[parsed.workspaceRetained, true, "workspaceRetained"],
[parsed.workspaceRetainedReason, "shared", "workspaceRetainedReason"],
]) {
];
for (const [actual, expected, label] of comparisons) {
assert(actual === expected, `${label} mismatch: ${JSON.stringify(actual)}`);
}
assert(
@@ -0,0 +1 @@
export function resolveGatewaySuccessPayload(frame: unknown): unknown;
@@ -0,0 +1,37 @@
export type GatewayFrame = {
error?: {
code?: string;
details?: Record<string, unknown>;
message?: string;
retryable?: boolean;
};
id?: string;
ok?: boolean;
payload?: Record<string, unknown>;
type?: string;
};
export type GatewaySocket = { close(): void; send(payload: string): void };
export function assertReadySuspensionResponse(
response: Record<string, unknown>,
now?: number,
): Record<string, unknown>;
export function assertGatewaySuspendingError(response: GatewayFrame): void;
export function assertSuspendedProbes(
health: Record<string, unknown>,
readiness: Record<string, unknown>,
): void;
export function responseError(method: string, response: GatewayFrame): Error;
export function runGatewayNetworkClient(
options: { token: string; url: string; timeoutMs?: number },
deps?: {
delay?: (ms: number) => Promise<void>;
onceFrame?: (
ws: GatewaySocket,
predicate: (message: GatewayFrame) => boolean,
timeoutMs?: number,
) => Promise<GatewayFrame>;
openSocket?: (url: string, timeoutMs?: number) => Promise<GatewaySocket>;
protocolVersion?: number;
stdout?: (message: string) => void;
},
): Promise<void>;
@@ -0,0 +1 @@
export function readGatewayNetworkClientConnectTimeoutMs(env?: NodeJS.ProcessEnv): number;
@@ -0,0 +1,5 @@
export function onceFrame(
ws: unknown,
filter: (message: Record<string, unknown>) => boolean,
timeoutMs?: number,
): Promise<Record<string, unknown>>;
@@ -0,0 +1,10 @@
export function resolvePositiveInteger(value: unknown, fallback: number): number;
export function createIncrementalLineReader(
filePath: string,
options?: { maxReadBytes?: number },
): {
readLines(): {
lines: string[];
reset: boolean;
};
};
@@ -416,7 +416,7 @@ function pluginInstallPath() {
if (record.source !== "npm" || record.artifactKind !== "npm-pack") {
throw new Error(`expected npm-pack install record: ${JSON.stringify(record)}`);
}
return String(record.installPath || "").replace(/^~(?=$|\/)/u, process.env.HOME);
return (record.installPath || "").replace(/^~(?=$|\/)/u, process.env.HOME);
}
function writeFixture() {
+36
View File
@@ -0,0 +1,36 @@
export function readMockOpenAiHttpLimits(env?: NodeJS.ProcessEnv): {
requestMaxBytes?: number;
requestLogBodyMaxBytes?: number;
};
export function isRequestBodyTooLargeError(error: unknown): error is Error;
export function readBody(
req: unknown,
limits?: {
requestMaxBytes?: number;
requestLogBodyMaxBytes?: number;
},
): Promise<string>;
export function boundedRequestLogBody(
value: unknown,
bodyText: unknown,
limits?: {
requestMaxBytes?: number;
requestLogBodyMaxBytes: number;
},
): unknown;
export function writeRequestLogEntryOrFail(
res: unknown,
{
requestLog,
entry,
label,
required,
}: {
requestLog: unknown;
entry: unknown;
label?: string | undefined;
required?: boolean | undefined;
},
): boolean;
export function writeJson(res: unknown, status: unknown, body: unknown): void;
export function writeSse(res: unknown, events: unknown): void;
@@ -0,0 +1,2 @@
export function readLogTail(file: unknown, maxBytes?: number): string;
export function logTailContains(file: unknown, needle: unknown, maxBytes?: number): unknown;
@@ -0,0 +1,16 @@
export namespace testing {
export { DEFAULT_GATEWAY_SCHEMA_ERROR };
export { DEFAULT_RAW_SCHEMA_ERROR };
export { SUCCESS_MARKER };
export { extractSuccessReplyTexts };
export { resolveGatewayPort };
export { validateSuccessResult };
export { validateRejectResult };
}
declare const DEFAULT_GATEWAY_SCHEMA_ERROR: "provider rejected the request schema or tool payload";
declare const DEFAULT_RAW_SCHEMA_ERROR: "400 The following tools cannot be used with reasoning.effort 'minimal': web_search.";
declare const SUCCESS_MARKER: "OPENCLAW_SCHEMA_E2E_OK";
declare function extractSuccessReplyTexts(value: unknown): unknown[];
declare function resolveGatewayPort(env?: NodeJS.ProcessEnv): number;
declare function validateSuccessResult(result: unknown, marker?: string): void;
declare function validateRejectResult(result: unknown, expectedRawSchemaError?: string): string;
@@ -0,0 +1,13 @@
export function probeHttpStatus({
url,
expectedRaw,
timeoutMs,
bearer,
fetchImpl,
}: {
url: unknown;
expectedRaw?: string | undefined;
timeoutMs?: number | undefined;
bearer?: string | undefined;
fetchImpl?: typeof fetch | undefined;
}): Promise<boolean>;
+23
View File
@@ -0,0 +1,23 @@
export type PluginInstallRecord = Record<string, unknown> & {
artifactKind?: string;
gitCommit?: string;
installPath?: string;
resolvedSpec?: string;
resolvedVersion?: string;
source?: string;
sourcePath?: string;
spec?: string;
};
export function stateDir(): string;
export function configPath(): string;
export function readPluginInstallIndex(options?: Record<string, unknown>): unknown;
export function readPluginInstallRecords(options?: {
configPath?: string;
fallbackRecords?: Record<string, PluginInstallRecord>;
stateDir?: string;
}): Record<string, PluginInstallRecord>;
export function writePluginInstallIndexForE2E(
index: unknown,
options?: Record<string, unknown>,
): void;
@@ -0,0 +1,6 @@
export function waitForClickClackSocket(params: {
baseUrl: string;
timeoutMs: number;
pollIntervalMs?: number;
}): Promise<void>;
export function runReleaseUserJourneyAssertion(command: string, args?: string[]): Promise<void>;
+8
View File
@@ -0,0 +1,8 @@
export function tailText(text: string, maxBytes: number): string;
export function readTextFileTail(file: string, maxBytes: number): string;
export function readTextFileBounded(
file: string,
label: string,
maxBytes: number,
options?: { tailBytes?: number },
): string;
@@ -0,0 +1,37 @@
#!/usr/bin/env node
export function isReleaseBefore(version: unknown, minimum: unknown): boolean;
export function resolveUpgradeSurvivorOpenClawCommand(
argv: unknown,
params?: Record<string, unknown>,
):
| {
command: unknown;
args: string[];
commandLabel: string;
shell: boolean;
windowsVerbatimArguments: boolean;
}
| {
command: string;
args: unknown;
commandLabel: string;
shell: boolean;
windowsVerbatimArguments?: undefined;
};
export function runUpgradeSurvivorOpenClawStep(
step: unknown,
params?: Record<string, unknown>,
): {
id: unknown;
intent: unknown;
command: string;
status: unknown;
signal: unknown;
ok: boolean;
errorCode: string | undefined;
errorMessage: string | undefined;
stdout: string;
stderr: string;
};
export const CONFIG_COMMAND_TIMEOUT_MS: 120000;
export const CONFIG_COMMAND_MAX_BUFFER_BYTES: number;
+5
View File
@@ -0,0 +1,5 @@
export function waitForWebSocketOpen(
ws: unknown,
timeoutMs: unknown,
message?: string,
): Promise<unknown>;
+9 -2
View File
@@ -5,6 +5,7 @@ import { randomUUID } from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";
import type { QaProviderMode } from "../../extensions/qa-lab/src/run-config.ts";
function parseBoolean(value: string | undefined) {
const normalized = value?.trim().toLowerCase();
@@ -132,7 +133,7 @@ async function main() {
repoRoot,
outputDir,
sutOpenClawCommand,
providerMode: process.env.OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE,
providerMode: process.env.OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE as QaProviderMode | undefined,
primaryModel: process.env.OPENCLAW_NPM_TELEGRAM_MODEL,
alternateModel: process.env.OPENCLAW_NPM_TELEGRAM_ALT_MODEL,
fastMode: parseBoolean(process.env.OPENCLAW_NPM_TELEGRAM_FAST),
@@ -152,7 +153,13 @@ async function main() {
async function formatRunnerErrorMessage(error: unknown) {
try {
const { formatErrorMessage } = await import("../../dist/infra/errors.js");
// Widen the specifier so the source-only test-root program does not try to
// resolve dist (TS2307); the docker-e2e boundary guard requires importing
// built dist here, so the cast stays structural instead of a src reference.
const distErrorsPath = "../../dist/infra/errors.js" as string;
const { formatErrorMessage } = (await import(distErrorsPath)) as {
formatErrorMessage: (err: unknown) => string;
};
return formatErrorMessage(error);
} catch {
return error instanceof Error ? error.message : String(error);
+4
View File
@@ -6,6 +6,10 @@ export * from "./host-server.ts";
export * from "./lane-runner.ts";
export * from "./macos-users.ts";
export * from "./package-artifact.ts";
// host-server.ts and package-artifact.ts both export a module-private `testing` hook, which
// star re-exports silently drop as ambiguous. Re-export one explicitly so the barrel
// typechecks (TS2308); import either module's `testing` directly, never through this barrel.
export { testing } from "./host-server.ts";
export * from "./parallels-vm.ts";
export * from "./plugin-isolation.ts";
export * from "./provider-auth.ts";
+8 -12
View File
@@ -1,17 +1,19 @@
// Host Server script supports OpenClaw repository automation.
import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process";
import { spawn, type ChildProcess } from "node:child_process";
import { randomUUID } from "node:crypto";
import { rm } from "node:fs/promises";
import { createServer } from "node:http";
import { createConnection } from "node:net";
import { tmpdir } from "node:os";
import path from "node:path";
import type { Readable } from "node:stream";
import { sleep as delay } from "../../lib/sleep.mjs";
import { die, run, say, sh, warn } from "./host-command.ts";
import type { HostServer, NpmRegistryPackage, NpmRegistryServer } from "./types.ts";
const HOST_SERVER_STDERR_LIMIT_BYTES = 64 * 1024;
const HOST_SERVER_STDERR_DRAIN_MS = 5_000;
type HostServerChild = ChildProcess & { stderr: Readable };
export function resolveHostIp(explicit = ""): string {
if (explicit) {
@@ -132,7 +134,7 @@ export async function startNpmRegistryServer(input: {
}
async function stopHostServerChild(
child: ChildProcessWithoutNullStreams,
child: HostServerChild,
terminateTimeoutMs = 2_000,
killTimeoutMs = 1_500,
): Promise<boolean> {
@@ -147,10 +149,7 @@ async function stopHostServerChild(
return await waitForChildExit(child, killTimeoutMs);
}
async function waitForChildExit(
child: ChildProcessWithoutNullStreams,
timeoutMs: number,
): Promise<boolean> {
async function waitForChildExit(child: HostServerChild, timeoutMs: number): Promise<boolean> {
if (hasHostServerChildExited(child)) {
return true;
}
@@ -172,14 +171,11 @@ async function waitForChildExit(
});
}
function hasHostServerChildExited(child: ChildProcessWithoutNullStreams): boolean {
function hasHostServerChildExited(child: HostServerChild): boolean {
return child.exitCode != null || child.signalCode != null;
}
async function waitForHostServer(
child: ChildProcessWithoutNullStreams,
port: number,
): Promise<void> {
async function waitForHostServer(child: HostServerChild, port: number): Promise<void> {
let stderr = "";
child.stderr.on("data", (chunk: Buffer) => {
stderr = appendBoundedOutput(stderr, chunk, HOST_SERVER_STDERR_LIMIT_BYTES);
@@ -218,7 +214,7 @@ function appendBoundedOutput(previous: string, chunk: Buffer, limitBytes: number
return combined.subarray(combined.byteLength - limitBytes).toString("utf8");
}
function formatHostServerExit(child: ChildProcessWithoutNullStreams): string {
function formatHostServerExit(child: HostServerChild): string {
return child.signalCode ? `signal ${child.signalCode}` : `exit ${child.exitCode ?? "unknown"}`;
}
+2 -2
View File
@@ -4,10 +4,10 @@ export function parseMacosDsclUserHomeLine(line: string): { user: string; home:
if (!match) {
return null;
}
return { user: match[1], home: match[2] };
return { user: match[1]!, home: match[2]! };
}
export function isLikelyMacosDesktopHome(home: string | undefined): boolean {
const normalized = home?.trim();
return Boolean(normalized) && /(?:^|\/)Users\/[^/]+$/u.test(normalized);
return normalized !== undefined && /(?:^|\/)Users\/[^/]+$/u.test(normalized);
}
+1 -1
View File
@@ -571,7 +571,7 @@ export class NpmUpdateSmoke {
private tgzDir = "";
private latestVersion = "";
private packageSpec = "";
private currentHead = "";
currentHead = "";
private currentHeadShort = "";
private harnessCheckoutVersion = "";
private harnessTargetFamily = "";
+1 -1
View File
@@ -7,7 +7,7 @@ import { die, run } from "./host-command.ts";
import type { Mode, Platform, Provider, ProviderAuth } from "./types.ts";
type ResolveLatestVersionDeps = {
createTempDir?: typeof mkdtempSync;
createTempDir?: (prefix: string) => string;
removeDir?: typeof rmSync;
runCommand?: typeof run;
tempDir?: typeof tmpdir;
+17 -11
View File
@@ -630,7 +630,11 @@ export function signalCommandTree(
useProcessGroup = platform !== "win32",
}: {
platform?: NodeJS.Platform;
runTaskkill?: typeof spawnSync;
runTaskkill?: (
command: string,
args: readonly string[],
options: { stdio: "ignore" },
) => { error?: Error; status: number | null };
useProcessGroup?: boolean;
} = {},
) {
@@ -1206,10 +1210,11 @@ export async function startLocalSut(
cwd: params.repoRoot,
env: mockServerEnv({ ...params, requestLog }),
});
const runningMock = mock;
await waitForOutputReady(
mock.child,
runningMock.child,
/mock-openai listening/u,
() => mock.output,
() => runningMock.output,
"mock-openai",
10_000,
);
@@ -1219,23 +1224,24 @@ export async function startLocalSut(
repoRoot: params.repoRoot,
});
gateway = spawnLoggedCommand(gatewaySpec.command, gatewaySpec.args, gatewaySpec.options);
const runningGateway = gateway;
await waitForOutputReady(
gateway.child,
runningGateway.child,
/\[gateway\] ready/u,
() => gateway.output,
() => runningGateway.output,
"gateway",
60_000,
);
return {
...config,
drained,
gateway: gateway.child,
gateway: runningGateway.child,
get gatewayLog() {
return gateway.output;
return runningGateway.output;
},
mock: mock.child,
mock: runningMock.child,
get mockLog() {
return mock.output;
return runningMock.output;
},
requestLog,
};
@@ -1327,10 +1333,10 @@ async function startLocalSutDaemon(params: {
gatewayPid = spawnDaemon({
args: gatewaySpec.args,
command: gatewaySpec.command,
cwd: gatewaySpec.options.cwd ?? params.repoRoot,
cwd: (gatewaySpec.options.cwd ?? params.repoRoot) as string,
env: gatewaySpec.options.env ?? gatewayEnvVars,
logPath: gatewayLog,
shell: gatewaySpec.options.shell,
shell: gatewaySpec.options.shell as boolean | undefined,
windowsVerbatimArguments: gatewaySpec.options.windowsVerbatimArguments,
});
if (!gatewayPid) {
+7 -1
View File
@@ -5,6 +5,12 @@ import { resolveWindowsTaskkillPath } from "../lib/windows-taskkill.mjs";
export type JsonObject = Record<string, unknown>;
type RunTaskkill = (
command: string,
args: string[],
options: { stdio: "ignore" },
) => { error?: Error; status: number | null };
type FetchJsonParams = {
fetchImpl?: (url: string, init: RequestInit) => Promise<Response>;
init: RequestInit;
@@ -256,7 +262,7 @@ export function signalChildProcessTree(
useProcessGroup = platform !== "win32",
}: {
platform?: NodeJS.Platform;
runTaskkill?: typeof spawnSync;
runTaskkill?: RunTaskkill;
useProcessGroup?: boolean;
} = {},
) {
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env node
/**
* Resolves the CLI startup build timeout from environment.
*/
export type StartupBuildParams = {
env?: NodeJS.ProcessEnv;
nodeExecPath?: string;
rootDir?: string;
spawnSync?: (
command: string,
args: string[],
options: Record<string, unknown>,
) => { error?: Error; status?: number | null };
stdio?: "inherit" | "pipe";
};
export function resolveCliStartupBuildTimeoutMs(env?: NodeJS.ProcessEnv): number;
/**
* Reports whether required CLI startup build outputs exist.
*/
export function hasCliStartupBuild(params?: StartupBuildParams): boolean;
/**
* Builds CLI startup assets when required outputs are missing.
*/
export function ensureCliStartupBuild(params?: StartupBuildParams): {
built: boolean;
};
@@ -0,0 +1,27 @@
#!/usr/bin/env node
/**
* Resolves the extension memory build timeout from environment.
*/
export type ExtensionMemoryBuildParams = {
env?: NodeJS.ProcessEnv;
nodeExecPath?: string;
requiredExtensionIds?: string[];
rootDir?: string;
spawnSync?: (
command: string,
args: string[],
options: Record<string, unknown>,
) => { error?: Error; status: number | null };
stdio?: "inherit" | "pipe";
};
export function resolveExtensionMemoryBuildTimeoutMs(env?: NodeJS.ProcessEnv): number;
/**
* Reports whether built memory extension entries exist.
*/
export function hasBuiltExtensionMemoryEntries(params?: ExtensionMemoryBuildParams): boolean;
/**
* Builds memory extension entries when required outputs are missing.
*/
export function ensureExtensionMemoryBuild(params?: ExtensionMemoryBuildParams): {
built: boolean;
};
+11 -8
View File
@@ -1,29 +1,32 @@
import type { spawnSync, SpawnSyncOptions } from "node:child_process";
import type { existsSync } from "node:fs";
import type { resolvePnpmRunner } from "./pnpm-runner.mjs";
type Getuid = typeof process.getuid;
type SpawnSyncLike = (
command: string,
args: string[],
options?: Record<string, unknown>,
) => { error?: Error; status: number | null };
type ChromiumInstallOptions = {
comSpec?: string;
cwd?: string;
env?: NodeJS.ProcessEnv;
executablePath?: string;
existsSync?: typeof existsSync;
existsSync?: (path: string) => boolean;
getuid?: Getuid;
log?: (message: string) => void;
platform?: NodeJS.Platform;
spawnSync?: typeof spawnSync;
stdio?: SpawnSyncOptions["stdio"];
spawnSync?: SpawnSyncLike;
stdio?: "ignore" | "inherit" | "pipe";
};
export const systemChromiumExecutableCandidates: readonly string[];
export function canRunChromiumExecutable(
executablePath: string,
spawnSync?: typeof spawnSync,
spawnSync?: SpawnSyncLike,
): boolean;
export function resolveSystemChromiumExecutablePath(
existsSync?: typeof existsSync,
spawnSync?: typeof spawnSync,
existsSync?: (path: string) => boolean,
spawnSync?: SpawnSyncLike,
): string;
export function resolvePlaywrightInstallRunner(options?: {
comSpec?: string;
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env node
export function docsFiles(root?: string, deps?: Record<string, unknown>): string[];
export function chunkFilesForCommand(
files: unknown,
prefixArgs: unknown,
maxBytes?: number,
): unknown[][];
export function resolveOxfmtInvocation(
args: unknown,
params?: Record<string, unknown>,
):
| {
command: string;
args: string[];
shell: boolean;
windowsVerbatimArguments: boolean;
}
| {
command: string;
args: string[];
shell: boolean;
windowsVerbatimArguments?: undefined;
}
| {
command: string;
args: string[];
shell: boolean;
windowsVerbatimArguments?: undefined;
};
export function runOxfmt(
files: unknown,
params?: Record<string, unknown>,
deps?: Record<string, unknown>,
): void;
export function formatDocs(
params?: Record<string, unknown>,
deps?: Record<string, unknown>,
): {
changed: unknown[];
fileCount: number;
};
@@ -0,0 +1,16 @@
#!/usr/bin/env node
export function parseArgs(argv: unknown): {
sha: string;
workflowSha: string;
keepBranch: boolean;
dryRun: boolean;
inputs: {
provider: string;
mode: string;
release_profile: string;
rerun_group: string;
reuse_evidence: string;
};
};
export function releaseEvidenceVerificationArgs(parentRunId: unknown): string[];
export function releaseEvidenceVerifierPath(worktreeRoot: unknown): string;
@@ -0,0 +1,133 @@
#!/usr/bin/env node
/**
* Resolves the release tag when the release ref is a SHA or tag.
*/
export function resolveReleaseTag({
releaseRef,
packageVersion,
}: {
releaseRef: unknown;
packageVersion: unknown;
}): unknown;
/**
* Resolves the previous reachable release tag for dependency diffs.
*/
export function resolvePreviousReleaseTag({
rootDir,
execFileSyncImpl,
fetchOnMiss,
}?: {
rootDir?: string | undefined;
execFileSyncImpl?: ((command: string, args?: string[]) => string) | undefined;
fetchOnMiss?: boolean | undefined;
}): string;
/**
* Creates the dependency evidence manifest payload.
*/
export function createDependencyEvidenceManifest({
generatedAt,
releaseTag,
releaseRef,
releaseSha,
npmDistTag,
packageVersion,
workflowRunId,
workflowRunAttempt,
dependencyChangeBaseRef,
}?: {
generatedAt?: string | undefined;
releaseTag?: string;
releaseRef?: string;
releaseSha?: string;
npmDistTag?: string;
packageVersion?: string;
dependencyChangeBaseRef?: string;
workflowRunId?: string | undefined;
workflowRunAttempt?: string | undefined;
}): {
schemaVersion: number;
generatedAt: string;
releaseTag: unknown;
releaseRef: unknown;
releaseSha: unknown;
npmDistTag: unknown;
packageName: string;
packageVersion: unknown;
workflowRunId: string;
workflowRunAttempt: string;
dependencyChangeBaseRef: unknown;
reports: {
name: string;
command: string;
policy: string;
json: string;
markdown: string;
}[];
};
/**
* Reads generated reports and collects summary counts.
*/
export function collectDependencyEvidenceSummaryCounts(evidenceDir: unknown): Promise<{
vulnerabilityBlockers: unknown;
vulnerabilityFindings: unknown;
transitiveRiskSignals: unknown;
workspaceExcludedTransitiveSignals: unknown;
transitiveMetadataFailures: unknown;
ownershipLockfilePackages: unknown;
ownershipBuildRiskPackages: unknown;
dependencyFileChanges: unknown;
dependencyAddedPackages: unknown;
dependencyRemovedPackages: unknown;
dependencyChangedPackages: unknown;
}>;
/**
* Renders the dependency evidence Markdown summary.
*/
export function renderDependencyEvidenceSummary({
releaseTag,
releaseSha,
baseRef,
counts,
}: {
releaseTag: unknown;
releaseSha: unknown;
baseRef: unknown;
counts: unknown;
}): string;
/**
* Renders the GitHub Actions step summary for dependency evidence.
*/
export function renderDependencyEvidenceStepSummary({
evidenceArtifactName,
baseRef,
counts,
}: {
evidenceArtifactName: unknown;
baseRef: unknown;
counts: unknown;
}): string;
export function parseArgs(argv: string[]): {
help?: true;
rootDir: string;
outputDir: string | null;
releaseRef: string | null;
npmDistTag: string | null;
baseRef: string | null;
githubOutput: string | undefined;
githubStepSummary: string | undefined;
};
/**
* Runs the dependency release evidence generator CLI.
*/
export function main(argv?: string[]): Promise<number>;
/**
* Dependency evidence reports generated for release artifacts.
*/
export const DEPENDENCY_EVIDENCE_REPORTS: {
name: string;
command: string;
policy: string;
json: string;
markdown: string;
}[];
import { execFileSync } from "node:child_process";
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env node
export namespace testing {
export { cleanHeadingText };
}
declare function cleanHeadingText(value: unknown): unknown;
+131
View File
@@ -0,0 +1,131 @@
#!/usr/bin/env node
/**
* Resolves the npm command invocation used by shrinkwrap generation.
*/
export function createNpmShrinkwrapCommand(
args: string[],
options?: {
comSpec?: string;
env?: NodeJS.ProcessEnv;
execPath?: string;
existsSync?: (candidate: string) => boolean;
platform?: NodeJS.Platform;
},
): {
args: string[];
command: string;
env?: NodeJS.ProcessEnv;
shell: boolean;
windowsVerbatimArguments?: boolean;
};
/**
* Reads a positive integer env override for shrinkwrap subprocess limits.
*/
export function readPositiveIntEnv(
name: unknown,
fallback: unknown,
env?: NodeJS.ProcessEnv,
): number;
/**
* Builds execFileSync options with bounded timeout and output buffer limits.
*/
export function createNpmShrinkwrapExecOptions(
invocation: unknown,
cwd: unknown,
env?: NodeJS.ProcessEnv,
): {
cwd: unknown;
env: unknown;
maxBuffer: number;
shell: unknown;
stdio: string[];
timeout: number;
windowsVerbatimArguments: unknown;
};
export function resolvePackageDirs(args: string[]): {
check: unknown;
changedPaths: string[];
jobs: number;
packageDirs: unknown[];
};
export function runBoundedTasks<Item, Result>(
items: Item[],
jobs: number,
runTask: (item: Item) => Promise<Result>,
): Promise<Result[]>;
export function resolveShrinkwrapJobs(
rawValue: unknown,
env?: NodeJS.ProcessEnv,
fallback?: number,
): number;
export function collectCurrentShrinkwrapOverrides(
shrinkwrap: unknown,
declaredDependencies?: Set<unknown>,
pnpmLockPackages?: Set<unknown>,
): unknown;
export function collectOverrideViolations(
lockfile: unknown,
overrideRules: unknown,
): {
path: string;
packageName: unknown;
actualVersion: unknown;
expectedVersion: unknown;
packagePath: {
name: unknown;
path: string;
}[];
}[];
export function collectPnpmLockViolations(
shrinkwrap: unknown,
pnpmLockPackages?: Set<unknown>,
): {
path: string;
packageKey: string;
}[];
export function disableShrinkwrappedOverrideConflictSources(
lockfile: unknown,
overrideRules: unknown,
): string[];
export function exactOverrideRulesFromOverrides(overrides: unknown): unknown;
export function exactVersionFromOverrideSpec(spec: unknown): string | null;
export function mergeOverrides(
packageOverrides: unknown,
workspaceOverrides: unknown,
pnpmLockOverrides: unknown,
): unknown;
export function applyPackageExtensionPeerMetadata(
lockfile: unknown,
packageExtensions?: unknown,
): unknown;
export function normalizeNpmVersionDrift<T>(lockfile: T): T;
export function packageJsonForShrinkwrap(
packageJson: Record<string, unknown>,
shrinkwrapOverrides: Record<string, unknown>,
): {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
peerDependencies?: Record<string, string>;
[key: string]: unknown;
};
export function packageDependencyInputsChanged(packageDir: unknown, changedPaths: unknown): unknown;
export function pnpmLockOverrideVersionForVersions(versions: unknown): unknown;
export function parsePnpmPackageKey(packageKey: unknown): {
name: string;
version: string;
} | null;
export function parseLockPackagePath(lockPath: unknown): {
name: unknown;
path: string;
}[];
export function readShrinkwrapOverrides(): unknown;
export function restoreCurrentPnpmLockedPackages(
generated: unknown,
current: unknown,
pnpmLockPackages?: Set<unknown>,
): unknown;
export function shouldUseLegacyPeerDepsForShrinkwrap(
packageJson: unknown,
packageExtensions?: unknown,
): boolean;
export function shrinkwrapPackageDirsForChangedPaths(changedPaths: string[]): string[];
@@ -0,0 +1,21 @@
export const managedLabelSpecs: Record<string, { color: string; description: string }>;
export const candidateLabels: {
blankTemplate: string;
lowSignalDocs: string;
docsDiscoverability: string;
testOnlyNoBug: string;
refactorOnly: string;
needsPrContext: string;
dirtyCandidate: string;
riskyInfra: string;
externalPluginCandidate: string;
};
export function classifyPullRequestCandidateLabels(
pullRequest: Record<string, unknown>,
files: Array<{ filename: string; status: string }>,
): string[];
export function runBarnacleAutoResponse(params: {
github: Record<string, unknown>;
context: Record<string, unknown>;
core?: Pick<Console, "info">;
}): Promise<void>;
+105
View File
@@ -0,0 +1,105 @@
export const GITHUB_API_REQUEST_TIMEOUT_MS: number;
export const GITHUB_ERROR_BODY_MAX_BYTES: number;
export const GITHUB_RESPONSE_BODY_MAX_BYTES: number;
export const dependencyChangedLabel: "dependencies-changed";
type Comment = {
body?: string;
created_at?: string;
html_url?: string;
user?: { login?: string };
};
type PullRequest = {
head?: { ref?: string; repo?: { full_name?: string }; sha?: string };
maintainer_can_modify?: boolean;
user?: { login?: string };
};
type ActorCandidate = { login: string; source: string };
export function isDependencyFile(filename: string): boolean;
export function isDependencyManifest(filename: string): boolean;
export function isPackageLockfile(filename: string): boolean;
export function dependencyFieldChanges(
baseManifest: Record<string, unknown>,
headManifest: Record<string, unknown>,
): string[];
export function shouldAutoscrubDependencyLockfiles(options: {
dependencyFiles?: string[];
lockfileChanges: unknown[];
dependencyManifestChanges?: unknown[];
}): boolean;
export function canAutoscrubPullRequest(options: {
owner: string;
repo: string;
pullRequest: PullRequest;
}): boolean;
export function sanitizeDisplayValue(value: unknown): string;
export function markdownCode(value: unknown): string;
export function readBoundedGitHubJson(
response: Response,
maxBytes?: number,
options?: { signal?: AbortSignal },
): Promise<unknown>;
export function findDependencyOverrideCommand(options: {
comments: Comment[];
expectedSha: string;
isSecurityMember: (login: string) => boolean;
newerThan?: string;
}): { login: string; reason: string | null; sha: string; url?: string } | null;
export function findDependencyOverrideCommandAsync(options: {
comments: Comment[];
expectedSha: string;
isSecurityMember: (login: string) => Promise<boolean>;
newerThan: string;
}): Promise<{ login: string; reason: string | null; sha: string; url?: string } | null>;
export function dependencyGuardCommentHeadSha(comment: Comment): string | null;
export function dependencyOverrideExpectedSha(
existingGuardComment: Comment | null,
currentHeadSha: string,
): string | null;
export function isDependencyGuardAuthorizedForHead(
comment: Comment,
currentHeadSha: string,
): boolean;
export function isDependencyGuardTrustedForHead(comment: Comment, currentHeadSha: string): boolean;
export function securityApproverSet(value: unknown): Set<string>;
export function dependencyGuardCommentAuthors(value?: unknown): Set<string>;
export function isDependencyGuardMarkerComment(
comment: Comment,
marker: string,
trustedAuthors: Set<string>,
): boolean;
export function renderAuthorizedDependencyComment(override: Record<string, unknown>): string;
export function renderTrustedDependencyComment(options: {
actor: { login: string; reason: string };
headSha: string;
}): string;
export function renderAutoscrubbedDependencyComment(options: {
baseBranch: string;
lockfileChanges: string[];
commitSha: string;
}): string;
export function isAutoscrubbedDependencyComment(comment: Comment): boolean;
export function renderClearedDependencyGuardComment(options: { headSha: string }): string;
export function renderBlockedDependencyComment(options: Record<string, unknown>): string;
export function dependencyGuardTrustedActorCandidates(options: {
pullRequest: PullRequest;
event: Record<string, unknown>;
currentHeadSha: string;
}): ActorCandidate[];
export function findTrustedDependencyGuardActor(options: {
candidates: ActorCandidate[];
isDependencyApprover: (login: string) => Promise<string | null>;
}): Promise<{ login: string; reason: string } | null>;
export function githubApi(
token: string,
options?: {
fetchImpl?: typeof fetch;
responseMaxBodyBytes?: number;
timeoutMs?: number;
},
): { request(path: string, options?: Record<string, unknown>): Promise<unknown> };
export function createAutoscrubCommit(...args: unknown[]): Promise<unknown>;
export function readBoundedGitHubErrorText(...args: unknown[]): Promise<string>;
@@ -0,0 +1,40 @@
export const PROOF_OVERRIDE_LABEL: "proof: override";
export const PROOF_SUFFICIENT_LABEL: "proof: sufficient";
export const NEEDS_PR_CONTEXT_LABEL: "triage: needs-pr-context";
export const DEFAULT_GITHUB_API_TIMEOUT_MS: 30000;
type PullRequest = Record<string, unknown>;
type Comment = Record<string, unknown>;
type Evaluation = {
status: string;
reason: string;
applies: boolean;
passed: boolean;
missingSections: string[];
};
export function readBoundedGitHubApiJson(
response: Response,
label: string,
maxBytes?: number,
options?: { timeoutMs?: number },
): Promise<unknown>;
export function isMaintainerTeamMember(params?: {
token?: string;
org?: string;
login?: string;
teamSlug?: string;
fetch?: typeof globalThis.fetch;
timeoutMs?: number;
}): Promise<boolean>;
export function hasAuthoredPullRequestSection(heading: string, body?: string): boolean;
export function hasClawSweeperExactHeadProof(params?: {
pullRequest?: PullRequest;
comments?: Comment[];
}): boolean;
export function evaluateClawSweeperExactHeadProof(params?: {
pullRequest?: PullRequest;
comments?: Comment[];
}): Evaluation;
export function evaluatePullRequestContext(params?: { pullRequest?: PullRequest }): Evaluation;
export function labelsForPullRequestContext(evaluation: Evaluation): string[];

Some files were not shown because too many files have changed in this diff Show More