Skip to content

Commit fe261b0

Browse files
authored
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 7ae5996 (#103975) replaced with the importTargetPlan fallback helper; the assertion fails on current main.
1 parent e681646 commit fe261b0

307 files changed

Lines changed: 8531 additions & 401 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,12 @@ jobs:
14721472
echo "Current CI targets must provide the tsgo:scripts package script." >&2
14731473
exit 1
14741474
fi
1475+
if pnpm run --silent 2>/dev/null | grep -q '^ tsgo:test:root$'; then
1476+
pnpm tsgo:test:root
1477+
elif [[ "$HISTORICAL_TARGET" != "true" ]]; then
1478+
echo "Current CI targets must provide the tsgo:test:root package script." >&2
1479+
exit 1
1480+
fi
14751481
;;
14761482
*)
14771483
echo "Unsupported check task: $TASK" >&2

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1963,9 +1963,10 @@
19631963
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:extensions",
19641964
"tsgo:profile": "node scripts/profile-tsgo.mjs",
19651965
"tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo",
1966-
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test",
1966+
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test && pnpm tsgo:test:root",
19671967
"tsgo:test:extensions": "pnpm tsgo:extensions:test",
19681968
"tsgo:test:packages": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages.tsbuildinfo",
1969+
"tsgo:test:root": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.root.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-root.tsbuildinfo",
19691970
"tsgo:test:src": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo",
19701971
"tsgo:test:ui": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-ui.tsbuildinfo",
19711972
"tui": "node scripts/run-node.mjs tui",

scripts/audit-seams.d.mts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env node
2+
export function describeSeamKinds(relativePath: unknown, source: unknown): string[];
3+
export function determineSeamTestStatus(
4+
seamKinds: unknown,
5+
relatedTestMatches: unknown,
6+
): {
7+
status: string;
8+
reason: string;
9+
};
10+
export function main(argv?: string[]): Promise<void>;
11+
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";

scripts/bench-test-changed.d.mts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export function parseArgs(argv: unknown): {
2+
maxWorkers?: unknown;
3+
cwd: string;
4+
mode: unknown;
5+
ref: unknown;
6+
rss: unknown;
7+
};
8+
export function parseMaxRssBytes(output: unknown): number | null;
9+
export function formatRss(valueBytes: unknown): string;
10+
export function resolveBenchRssResult({
11+
label,
12+
output,
13+
rss,
14+
status,
15+
}: {
16+
label: unknown;
17+
output: unknown;
18+
rss: unknown;
19+
status: unknown;
20+
}): {
21+
maxRssBytes: number | null;
22+
output: unknown;
23+
status: unknown;
24+
};

scripts/build-all.d.mts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import type fs from "node:fs";
2+
3+
export type BuildCacheEntry =
4+
| string
5+
| {
6+
path: string;
7+
extensions?: string[];
8+
recursive?: boolean;
9+
};
10+
11+
export type BuildAllStep = {
12+
label: string;
13+
kind?: "node" | "pnpm";
14+
args?: string[];
15+
pnpmArgs?: string[];
16+
env?: NodeJS.ProcessEnv;
17+
windowsNodeOptions?: string;
18+
cache?: {
19+
env?: string[];
20+
inputs: BuildCacheEntry[];
21+
outputs: BuildCacheEntry[];
22+
restore?: "always";
23+
};
24+
};
25+
26+
export type BuildAllCacheState = {
27+
cacheable: boolean;
28+
fresh: boolean;
29+
restorable?: boolean;
30+
reason: string;
31+
signature?: string;
32+
outputRoot?: string;
33+
stampPath?: string;
34+
inputFiles?: number;
35+
outputFiles?: number;
36+
relativeOutputFiles?: string[];
37+
stampedOutputs?: string[];
38+
};
39+
40+
export const BUILD_ALL_STEPS: BuildAllStep[];
41+
export const BUILD_ALL_PROFILES: Record<string, string[]>;
42+
export const BUILD_ALL_PROFILE_STEP_ENV: Record<string, Record<string, NodeJS.ProcessEnv>>;
43+
44+
export function buildAllUsage(): string;
45+
export function parseBuildAllArgs(argv: string[]): { help: boolean; profile: string };
46+
export function resolveBuildAllSteps(profile?: string): BuildAllStep[];
47+
export function resolveBuildAllEnvironment(
48+
env?: NodeJS.ProcessEnv,
49+
now?: () => Date,
50+
readGitCommit?: () => string | null,
51+
): { [key: string]: string | undefined; OPENCLAW_BUILD_TIMESTAMP: string };
52+
export function resolveBuildAllStep(
53+
step: BuildAllStep,
54+
params?: {
55+
platform?: NodeJS.Platform;
56+
env?: NodeJS.ProcessEnv;
57+
nodeExecPath?: string;
58+
npmExecPath?: string;
59+
comSpec?: string;
60+
},
61+
): {
62+
command: string;
63+
args: string[];
64+
options: {
65+
stdio: "inherit";
66+
env: NodeJS.ProcessEnv;
67+
shell?: boolean;
68+
windowsVerbatimArguments?: boolean;
69+
};
70+
};
71+
export function resolveBuildAllStepCacheState(
72+
step: BuildAllStep,
73+
params?: { rootDir?: string; fs?: typeof fs; env?: NodeJS.ProcessEnv },
74+
): BuildAllCacheState;
75+
export function writeBuildAllStepCacheStamp(
76+
step: BuildAllStep,
77+
cacheState: BuildAllCacheState,
78+
params?: { rootDir?: string; fs?: typeof fs },
79+
): void;
80+
export function resolveBuildAllStepCacheStampState(
81+
step: BuildAllStep,
82+
cacheState: BuildAllCacheState,
83+
params?: { rootDir?: string; fs?: typeof fs },
84+
): BuildAllCacheState;
85+
export function restoreBuildAllStepCacheOutputs(
86+
cacheState: BuildAllCacheState,
87+
params?: { rootDir?: string; fs?: typeof fs },
88+
): boolean;
89+
export function formatBuildAllDuration(durationMs: number): string;
90+
export function formatBuildAllTimingSummary(
91+
timings: Array<{ label: string; durationMs: number; status: string }>,
92+
): string;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Creates the esbuild plugin that neutralizes Pierre diffs' browser side-effect import.
4+
*/
5+
export function createPierreDiffsSideEffectImportPlugin(): {
6+
name: string;
7+
setup(buildContext: unknown): void;
8+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Reads bundled plugin asset hook commands for a build or copy phase.
4+
*/
5+
export function readBundledPluginAssetHooks(options?: Record<string, unknown>): Promise<
6+
{
7+
aliases: string[];
8+
command: string;
9+
packageName: unknown;
10+
phase: unknown;
11+
pluginDir: string;
12+
pluginId: string;
13+
}[]
14+
>;
15+
/**
16+
* Runs bundled plugin asset hook commands for the selected phase/plugins.
17+
*/
18+
export function runBundledPluginAssetHooks(options?: Record<string, unknown>): Promise<void>;
19+
/**
20+
* Parses `--phase` and repeated `--plugin` flags for asset hook scripts.
21+
*/
22+
export function parseBundledPluginAssetArgs(argv: unknown): {
23+
phase: unknown;
24+
plugins: unknown[];
25+
};

scripts/changed-lanes.d.mts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export type ChangedLane =
2+
| "core"
3+
| "coreTests"
4+
| "extensions"
5+
| "extensionTests"
6+
| "scripts"
7+
| "testRoot"
8+
| "apps"
9+
| "docs"
10+
| "tooling"
11+
| "liveDockerTooling"
12+
| "releaseMetadata"
13+
| "all";
14+
15+
export type ChangedLanes = Record<ChangedLane, boolean>;
16+
17+
export type ChangedLaneResult = {
18+
paths: string[];
19+
lanes: ChangedLanes;
20+
extensionImpactFromCore: boolean;
21+
docsOnly: boolean;
22+
reasons: string[];
23+
};
24+
25+
export type DetectChangedLanesOptions = {
26+
packageJsonChangeKind?: "liveDockerTooling" | "tooling" | null;
27+
};
28+
29+
export function normalizeChangedPath(inputPath: unknown): string;
30+
export function createEmptyChangedLanes(): ChangedLanes;
31+
export function isChangedLaneTestPath(changedPath: string): boolean;
32+
export function detectChangedLanes(
33+
changedPaths: string[],
34+
options?: DetectChangedLanesOptions,
35+
): ChangedLaneResult;
36+
export function detectChangedLanesForPaths(params: {
37+
paths: string[];
38+
base: string;
39+
head?: string;
40+
staged?: boolean;
41+
mergeHeadFirstParent?: boolean;
42+
}): ChangedLaneResult;
43+
export function listChangedPathsFromGit(params: {
44+
base: string;
45+
head?: string;
46+
includeWorktree?: boolean;
47+
cwd?: string;
48+
mergeHeadFirstParent?: boolean;
49+
}): string[];
50+
export function listStagedChangedPaths(cwd?: string): string[];
51+
export function isLiveDockerPackageScriptOnlyChange(before: string, after: string): boolean;
52+
export function isPackageScriptOnlyChange(before: string, after: string): boolean;
53+
54+
export const LIVE_DOCKER_AUTH_SHELL_TARGETS: string[];
55+
export const RELEASE_METADATA_PATHS: Set<string>;

scripts/changed-lanes.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const EXTENSION_PATH_RE = /^extensions\/[^/]+(?:\/|$)/u;
1515
const CORE_PATH_RE = /^(?:src\/|ui\/|packages\/)/u;
1616
const SCRIPTS_TYPECHECK_PATH_RE =
1717
/^(?:scripts\/.*\.(?:[cm]?ts|[cm]?tsx)|tsconfig\.scripts\.json)$/u;
18+
const TEST_ROOT_TYPECHECK_PATH_RE =
19+
/^(?:test\/(?!fixtures\/).*\.(?:[cm]?ts|[cm]?tsx)|test\/tsconfig\/tsconfig\.test\.root\.json)$/u;
1820
const TOOLING_PATH_RE =
1921
/^(?: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;
2022
const ROOT_GLOBAL_PATH_RE =
@@ -56,7 +58,7 @@ export const RELEASE_METADATA_PATHS = new Set([
5658
"package.json",
5759
]);
5860

59-
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
61+
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "testRoot" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
6062

6163
/**
6264
* @typedef {{
@@ -88,6 +90,7 @@ export function createEmptyChangedLanes() {
8890
extensions: false,
8991
extensionTests: false,
9092
scripts: false,
93+
testRoot: false,
9194
apps: false,
9295
docs: false,
9396
tooling: false,
@@ -145,6 +148,9 @@ export function detectChangedLanes(changedPaths, options = {}) {
145148
if (SCRIPTS_TYPECHECK_PATH_RE.test(changedPath)) {
146149
lanes.scripts = true;
147150
}
151+
if (TEST_ROOT_TYPECHECK_PATH_RE.test(changedPath)) {
152+
lanes.testRoot = true;
153+
}
148154

149155
if (DOCS_PATH_RE.test(changedPath)) {
150156
lanes.docs = true;
@@ -299,12 +305,14 @@ export function listChangedPathsFromGit(params) {
299305
let rangePaths;
300306
let noMergeBase = false;
301307
try {
308+
// oxlint-disable-next-line typescript/no-base-to-string, typescript/restrict-template-expressions -- resolveMergeHeadDiffBase returns a git ref string when present.
302309
rangePaths = runGitNameOnlyDiff([`${base}...${head}`], cwd);
303310
} catch (error) {
304311
if (!isGitNoMergeBaseError(error)) {
305312
throw error;
306313
}
307314
noMergeBase = true;
315+
// oxlint-disable-next-line typescript/no-base-to-string, typescript/restrict-template-expressions -- resolveMergeHeadDiffBase returns a git ref string when present.
308316
rangePaths = runGitNameOnlyDiff([`${base}..${head}`], cwd);
309317
}
310318
if (params.includeWorktree === false) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Collects architecture smell findings from the configured source roots.
4+
*/
5+
export function collectArchitectureSmells(): Promise<
6+
Array<{
7+
category: string;
8+
file: string;
9+
line: number;
10+
kind: string;
11+
specifier: string;
12+
reason: string;
13+
}>
14+
>;
15+
/**
16+
* Runs the architecture smell check and writes human/JSON output.
17+
*/
18+
export function main(argv: unknown, io: unknown): Promise<number>;

0 commit comments

Comments
 (0)