chore(deps): finish toolchain upgrades and drop dead weight (#644)

* chore(deps): finish toolchain upgrades and drop dead weight

pino 9 to 10, @types/node 24 to 26, oxlint 1.73 to 1.87, knip 6.26
to 6.39, turbo 2.10 to 2.11. Narrow engines to supported majors
(22/24/26; vitest 5 refuses Node 25). Scope no-var-requires off for
Electron CJS hooks and fixtures.

Remove TypeDoc: incompatible with TypeScript 7 at install and
runtime, used by nothing in any gate. Drop the dep, docs:api
workflow, typedoc.json, CI artifact step, and related docs.

Replace graphology with a local call-graph adjacency plus BFS: the
only consumer is call-path search, and graphology-types ships no
types entry for TS7 NodeNext resolution. Delete both graphology
dependencies.

Remove dead re-exports newly flagged by knip 6.39.

* chore: drop stale typedoc and replay references

Remove the docs:api release-checklist step, the orphaned docs/api
ignore entry, and the nonexistent replay glob from the adapters
project.
This commit is contained in:
morluto 2026-10-06 06:02:02 +08:00 committed by GitHub
parent 5f27e02fae
commit 9b392bb2f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 552 additions and 542 deletions

1
.gitignore vendored
View File

@ -6,7 +6,6 @@ __pycache__/
# Distribution
dist/
build/
docs/api/
node_modules
*.egg-info/
*.egg

View File

@ -17,6 +17,15 @@
"no-var-requires": "error"
},
"overrides": [
{
"files": [
"scripts/electron-active-hook*.cjs",
"tests/conformance/readiness/electron/*.js"
],
"rules": {
"no-var-requires": "off"
}
},
{
"files": [
"src/{contracts,domain,server}/**/*.ts",

View File

@ -94,3 +94,14 @@ Keep tool catalogs complete and self-describing; prefer capability- and session-
## Commit & Pull Request Guidelines
Use Conventional Commit subjects because Release Please derives versions and changelogs from them. Examples: `feat: add historical source import`, `fix(process): stop timers after exit`, and `docs: update architecture`. Use `!` or a `BREAKING CHANGE:` footer for breaking changes. Pull request titles must follow the same format because squash merges use the title as the release commit. Pull requests should describe contract or behavior changes, list verification commands, link issues, and include sanitized MCP examples when schemas change. State whether real Hopper/Ghidra verification was performed. Never commit binaries, Hopper or Ghidra project documents, credentials, `dist/`, `node_modules/`, or local planning artifacts (e.g. `.codex/`).
<!-- BEGIN:turborepo-agent-rules -->
# This is NOT the Turborepo you know
Turborepo configuration, task behavior, and CLI commands can vary between installed versions and may differ from your training data. Resolve the `turbo` package from this file's directory or relevant workspace; in monorepos, it may not be visible from the repository root. For example, run `node -p "require.resolve('turbo/package.json')"` from a workspace that depends on `turbo`.
Read `docs/README.md` inside that installed package first, then read the relevant pages from its `docs/` directory before changing Turborepo configuration or commands. Heed deprecation notices. These bundled docs match the installed package version and are available without network access.
This block is written and re-added by `turbo` before repository-scoped commands when an AI agent is detected. In the Turborepo source repository, its template is defined in `crates/turborepo-cli/src/cli/agent_guidance.rs`. Removing the managed block while updates are enabled means a later qualifying invocation will add it again. Set `"agentGuidance": false` in the root `turbo.json` or `turbo.jsonc` to opt out; this does not remove an existing block. Keep the block committed with your work to avoid an uncommitted change on the next agent invocation.
<!-- END:turborepo-agent-rules -->

View File

@ -3,7 +3,6 @@
"entry": ["src/main.ts", "src/cli.ts", "src/contracts/errorSchemas.ts"],
"project": ["src/**/*.ts", "tests/**/*.ts", "scripts/**/*.mjs"],
"ignoreDependencies": ["electron"],
"ignoreBinaries": ["ps"],
"ignoreExportsUsedInFile": true,
"rules": {
"files": "error",

937
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
"rea-agents": "scripts/rea.mjs"
},
"engines": {
"node": "^22.19.0 || >=24.11.0"
"node": "^22.19.0 || ^24.11.0 || >=26.0.0"
},
"packageManager": "npm@11.16.0",
"files": [
@ -177,13 +177,11 @@
"canonicalize": "3.0.0",
"cross-spawn": "7.0.6",
"diff": "9.0.0",
"graphology": "0.26.0",
"graphology-shortest-path": "2.1.0",
"ignore": "7.0.6",
"incur": "0.4.13",
"isomorphic-git": "1.38.7",
"jsonc-parser": "3.3.1",
"pino": "9.14.0",
"pino": "10.4.0",
"playwright-core": "1.58.2",
"plist": "5.0.0",
"semver": "7.8.5",
@ -195,7 +193,7 @@
"devDependencies": {
"@fast-check/vitest": "0.5.0",
"@types/cross-spawn": "6.0.6",
"@types/node": "24.10.1",
"@types/node": "26.6.4",
"@types/semver": "7.7.1",
"@types/write-file-atomic": "4.0.3",
"@types/ws": "8.18.1",
@ -203,11 +201,11 @@
"ajv": "8.20.0",
"husky": "9.1.7",
"jscpd": "5.0.12",
"knip": "6.26.0",
"knip": "6.39.0",
"lint-staged": "16.4.0",
"oxfmt": "0.72.0",
"oxlint": "1.73.0",
"turbo": "2.10.5",
"oxlint": "1.87.0",
"turbo": "2.11.7",
"typescript": "7.0.2",
"vitest": "5.0.3",
"yaml": "2.9.0"

View File

@ -69,7 +69,6 @@ export {
changedBehaviorInputSchema,
closeBinaryInputSchema,
functionComparisonInputSchema,
jsonValueSchema,
openBinaryInputSchema,
processScenarioSchema,
reconstructionVerificationInputSchema,

View File

@ -10,18 +10,7 @@ import { OFFICIAL_TOOL_CONTRACTS } from "./officialToolContracts.js";
import { ENHANCED_TOOL_CONTRACTS } from "./enhancedToolContracts.js";
import { SESSION_TOOL_CONTRACTS } from "./sessionToolContracts.js";
export {
addressContextInputSchema,
binarySessionInputSchema,
importEvidenceBundleInputSchema,
listUnknownsInputSchema,
navigationContextInputSchema,
processComparisonInputSchema,
getEvidenceBundleInputSchema,
verifyUnknownResolutionInputSchema,
} from "./sessionToolSchemas.js";
export type { ToolContract, ToolExample } from "./toolContractTypes.js";
export type { ToolContract } from "./toolContractTypes.js";
/** Complete ordered public inventory used by registration and verification. */
export const TOOL_CONTRACTS = [

View File

@ -14,9 +14,6 @@ import {
} from "./browserScenarioValues.js";
export {
browserScenarioActionSchema,
browserScenarioUrlSchema,
browserScenarioValueSchema,
type BrowserScenarioAction,
type BrowserScenarioUrl,
type BrowserScenarioValue,

View File

@ -8,11 +8,9 @@ import {
export {
classifyBrowserScenarioCompleteness,
browserScenarioCompletenessSchema,
browserScenarioEventSchema,
browserScenarioStepSchema,
browserStepArtifactsSchema,
captureStateSchema,
type BrowserScenarioCompleteness,
type BrowserScenarioCompletenessSection,
type BrowserScenarioEvent,

View File

@ -1,6 +1,3 @@
import { DirectedGraph } from "graphology";
import { bidirectional } from "graphology-shortest-path/unweighted.js";
import {
callPathInputSchema,
callPathResultSchema,
@ -17,8 +14,58 @@ import {
export { callPathInputSchema, callPathResultSchema };
export type { CallPathInput, CallPathResult };
/** Minimal directed caller-to-callee adjacency for call-path search. */
class CallGraph {
private readonly successors = new Map<string, Set<string>>();
mergeNode(node: string): void {
if (!this.successors.has(node)) this.successors.set(node, new Set());
}
mergeDirectedEdge(source: string, target: string): void {
this.mergeNode(source);
this.mergeNode(target);
this.successors.get(source)?.add(target);
}
hasNode(node: string): boolean {
return this.successors.has(node);
}
outDegree(node: string): number {
return this.successors.get(node)?.size ?? 0;
}
outNeighbors(node: string): string[] {
return [...(this.successors.get(node) ?? [])];
}
}
/** Breadth-first shortest depth from start to goal, or null when unreachable. */
const shortestPathDepth = (
graph: CallGraph,
start: string,
goal: string,
): number | null => {
if (start === goal) return 0;
const depth = new Map<string, number>([[start, 0]]);
const queue = [start];
for (let index = 0; index < queue.length; index += 1) {
const node = queue[index] ?? "";
const next = (depth.get(node) ?? 0) + 1;
for (const neighbor of graph.outNeighbors(node)) {
if (neighbor === goal) return next;
if (!depth.has(neighbor)) {
depth.set(neighbor, next);
queue.push(neighbor);
}
}
}
return null;
};
interface SearchState {
readonly graph: DirectedGraph;
readonly graph: CallGraph;
readonly snapshots: ReadonlyMap<string, FunctionSnapshot>;
readonly reached: ReadonlyMap<string, number>;
readonly exhaustive: boolean;
@ -35,18 +82,18 @@ export const buildCallPath = (input: CallPathInput): CallPathResult => {
start: parsed.start.address,
goal: parsed.goal.address,
});
const shortest =
const shortestDepth =
graph.hasNode(parsed.start.address) && graph.hasNode(parsed.goal.address)
? bidirectional(graph, parsed.start.address, parsed.goal.address)
? shortestPathDepth(graph, parsed.start.address, parsed.goal.address)
: null;
const paths =
shortest === null
shortestDepth === null
? []
: enumeratePaths({
graph,
start: parsed.start.address,
goal: parsed.goal.address,
shortestDepth: shortest.length - 1,
shortestDepth,
}).paths.map((path) => citePath(path, snapshots));
const shortestHops = paths[0]?.hops;
const found = shortestHops !== undefined;
@ -80,7 +127,7 @@ export const buildCallPath = (input: CallPathInput): CallPathResult => {
};
const summarizeSearch = (
graph: DirectedGraph,
graph: CallGraph,
reached: ReadonlyMap<string, number>,
) => ({
nodes: reached.size,
@ -141,8 +188,8 @@ const assertCompatible = (
const createGraph = (
snapshots: ReadonlyMap<string, FunctionSnapshot>,
): DirectedGraph => {
const graph = new DirectedGraph({ allowSelfLoops: true, multi: false });
): CallGraph => {
const graph = new CallGraph();
for (const [address, snapshot] of snapshots) {
graph.mergeNode(address);
for (const callee of snapshot.collections.callees.items) {
@ -155,7 +202,7 @@ const createGraph = (
};
interface SearchInput {
readonly graph: DirectedGraph;
readonly graph: CallGraph;
readonly snapshots: ReadonlyMap<string, FunctionSnapshot>;
readonly start: string;
readonly goal: string;
@ -211,7 +258,7 @@ const inspectSearch = ({
};
interface EnumerationInput {
readonly graph: DirectedGraph;
readonly graph: CallGraph;
readonly start: string;
readonly goal: string;
readonly shortestDepth: number;
@ -238,7 +285,7 @@ const enumeratePaths = ({
};
interface EnumerationState {
readonly graph: DirectedGraph;
readonly graph: CallGraph;
readonly goal: string;
readonly path: string[];
readonly visited: Set<string>;

View File

@ -396,9 +396,3 @@ export {
PROCESS_COMPARISON_DIMENSIONS,
processCaptureComparisonSchema,
} from "./processComparison.js";
export {
compareProcessTraces,
processTraceComparisonResultSchema,
processTraceSourceSchema,
processTraceSpecificationSchema,
} from "./processTraceComparison.js";

View File

@ -12,12 +12,9 @@ import {
export {
processTraceComparisonResultSchema,
type ProcessTraceComparisonResult,
type ProcessTraceLocation,
} from "./processTraceEvaluation.js";
export {
processTraceSourceSchema,
processTraceSpecificationSchema,
type ProcessTraceSource,
type ProcessTraceSpecification,
} from "./processTraceSpecification.js";

View File

@ -100,4 +100,14 @@ describe("release configuration", () => {
],
});
});
it("keeps generated API HTML out of the tracked tree", async () => {
await expect(readFile("typedoc.json", "utf8")).rejects.toMatchObject({
code: "ENOENT",
});
const packageJson = (await readJson("package.json")) as {
scripts?: Record<string, string>;
};
expect(packageJson.scripts?.["docs:api"]).toBeUndefined();
});
});

View File

@ -11,11 +11,7 @@ import type {
FakeOptions,
} from "./fakeCdpBrowserTypes.js";
export type {
FakeCdpBrowser,
FakeCdpCommand,
FakeOptions,
} from "./fakeCdpBrowserTypes.js";
export type { FakeCdpBrowser, FakeOptions } from "./fakeCdpBrowserTypes.js";
/** Start a real HTTP/WebSocket fake at the same seams as a user-owned browser. */
export const startFakeCdpBrowser = async (
options: FakeOptions = {},

View File

@ -37,7 +37,7 @@ const TEST_PROJECTS = [
name: "adapters",
include: [
"src/*.test.ts",
"src/{artifacts,browser,dotnet,ghidra,hopper,native,process,reference,replay,server}/**/*.test.ts",
"src/{artifacts,browser,dotnet,ghidra,hopper,native,process,reference,server}/**/*.test.ts",
],
pool: "forks" as const,
maxWorkers: MAX_TEST_WORKERS,