refactor: eliminate ~400 no-explicit-any warnings across the workspace

Parallel subagent pass: four typescript-pro agents on non-overlapping scopes.

Patterns applied:
- catch (err: any) { ... err.message ... } → catch (err) { ... getErrorMessage(err) ... }
  using the new @fusion/core helper. Bare catch {} where the error was unused.
- SQLite row types: defined typed XxxRow interfaces per table and cast
  .all()/.get() results via `as unknown as XxxRow[]` (the double cast is
  required because better-sqlite3 returns Record<string, SQLOutputValue>).
- rowToX(row: any) converters: typed argument with the matching row interface.
- Dynamic settings key writes: (settings as Record<string, unknown>)[key].
- React event handlers and setState callbacks: inferred types or concrete
  React.{Mouse,Change,Form}Event<...> where needed.
- pi-claude-cli: local PiMessage / PiContext duck types to avoid re-typing
  pi-ai concrete shapes; typed Claude stream event message fields.

72 files changed, ~400 anys eliminated. Typecheck passes across the workspace.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-23 18:57:31 -07:00
parent d1bd02b2c9
commit 4cabe7f613
72 changed files with 1298 additions and 783 deletions

View File

@@ -153,20 +153,20 @@ const upload = multer({
const execFileAsync = promisify(execFile);
function readJsonObject(path: string): Record<string, any> {
function readJsonObject(path: string): Record<string, unknown> {
if (!nodeFs.existsSync(path)) {
return {};
}
try {
const parsed = JSON.parse(nodeFs.readFileSync(path, "utf-8"));
return parsed && typeof parsed === "object" ? parsed as Record<string, any> : {};
return parsed && typeof parsed === "object" ? parsed as Record<string, unknown> : {};
} catch {
return {};
}
}
function hasPackageManagerSettings(settings: Record<string, any>): boolean {
function hasPackageManagerSettings(settings: Record<string, unknown>): boolean {
return Array.isArray(settings.packages) || Array.isArray(settings.npmCommand);
}
@@ -215,6 +215,7 @@ async function discoverDashboardPiExtensions(cwd: string): Promise<PiExtensionSe
getNpmCommand: () => Array.isArray(mergedSettings.npmCommand)
? [...mergedSettings.npmCommand]
: undefined,
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- settingsManager shape varies across pi-coding-agent versions; typed as any per upstream API
} as any,
});
const resolved = await packageManager.resolve(async () => "skip");
@@ -15153,7 +15154,7 @@ async function persistImportedSkills(
await central.init();
const localNodes = await central.listNodes();
const localNode = localNodes.find((n: any) => n.type === "local");
const localNode = localNodes.find((n: { type?: string; id?: string }) => n.type === "local");
if (localNode && localNode.id === nodeId) {
// Local node — fall through to existing filesystem logic below
@@ -15198,11 +15199,12 @@ async function persistImportedSkills(
}
res.status(proxyRes.status);
res.send(body);
} catch (fetchErr: any) {
if (fetchErr.name === "AbortError" || fetchErr.code === "ETIMEDOUT") {
throw new ApiError(504, `Remote node timeout: ${fetchErr.message}`);
} catch (fetchErr) {
const e = fetchErr as { name?: string; code?: string; message?: string };
if (e.name === "AbortError" || e.code === "ETIMEDOUT") {
throw new ApiError(504, `Remote node timeout: ${e.message ?? String(fetchErr)}`);
}
throw new ApiError(502, `Remote node error: ${fetchErr.message}`);
throw new ApiError(502, `Remote node error: ${e.message ?? String(fetchErr)}`);
}
return;
}

View File

@@ -219,85 +219,84 @@ export function createSSE(
};
// --- Event handler definitions ---
/* eslint-disable @typescript-eslint/no-explicit-any -- EventEmitter handlers receive untyped event data */
const onCreated = (task: any) => {
const onCreated = (task: unknown) => {
send(`event: task:created\ndata: ${JSON.stringify(stripTaskListHeavyFields(task))}\n\n`);
};
const onMoved = (data: any) => {
const onMoved = (data: unknown) => {
send(`event: task:moved\ndata: ${JSON.stringify(stripTaskEventHeavyFields(data))}\n\n`);
};
const onUpdated = (task: any) => {
const onUpdated = (task: unknown) => {
send(`event: task:updated\ndata: ${JSON.stringify(stripTaskListHeavyFields(task))}\n\n`);
};
const onDeleted = (task: any) => {
const onDeleted = (task: unknown) => {
send(`event: task:deleted\ndata: ${JSON.stringify(stripTaskListHeavyFields(task))}\n\n`);
};
const onMerged = (result: any) => {
const onMerged = (result: unknown) => {
send(`event: task:merged\ndata: ${JSON.stringify(stripTaskEventHeavyFields(result))}\n\n`);
};
const onMissionCreated = (data: any) => {
const onMissionCreated = (data: unknown) => {
send(`event: mission:created\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMissionUpdated = (data: any) => {
const onMissionUpdated = (data: unknown) => {
send(`event: mission:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMissionDeleted = (data: any) => {
const onMissionDeleted = (data: unknown) => {
send(`event: mission:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMilestoneCreated = (data: any) => {
const onMilestoneCreated = (data: unknown) => {
send(`event: milestone:created\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMilestoneUpdated = (data: any) => {
const onMilestoneUpdated = (data: unknown) => {
send(`event: milestone:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMilestoneDeleted = (data: any) => {
const onMilestoneDeleted = (data: unknown) => {
send(`event: milestone:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
const onSliceCreated = (data: any) => {
const onSliceCreated = (data: unknown) => {
send(`event: slice:created\ndata: ${JSON.stringify(data)}\n\n`);
};
const onSliceUpdated = (data: any) => {
const onSliceUpdated = (data: unknown) => {
send(`event: slice:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onSliceDeleted = (data: any) => {
const onSliceDeleted = (data: unknown) => {
send(`event: slice:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
const onSliceActivated = (data: any) => {
const onSliceActivated = (data: unknown) => {
send(`event: slice:activated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onFeatureCreated = (data: any) => {
const onFeatureCreated = (data: unknown) => {
send(`event: feature:created\ndata: ${JSON.stringify(data)}\n\n`);
};
const onFeatureUpdated = (data: any) => {
const onFeatureUpdated = (data: unknown) => {
send(`event: feature:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onFeatureDeleted = (data: any) => {
const onFeatureDeleted = (data: unknown) => {
send(`event: feature:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
const onFeatureLinked = (data: any) => {
const onFeatureLinked = (data: unknown) => {
send(`event: feature:linked\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAssertionCreated = (data: any) => {
const onAssertionCreated = (data: unknown) => {
send(`event: assertion:created\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAssertionUpdated = (data: any) => {
const onAssertionUpdated = (data: unknown) => {
send(`event: assertion:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAssertionDeleted = (data: any) => {
const onAssertionDeleted = (data: unknown) => {
send(`event: assertion:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAssertionLinked = (data: any) => {
const onAssertionLinked = (data: unknown) => {
send(`event: assertion:linked\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAssertionUnlinked = (data: any) => {
const onAssertionUnlinked = (data: unknown) => {
send(`event: assertion:unlinked\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMissionEvent = (data: any) => {
const onMissionEvent = (data: unknown) => {
send(`event: mission:event\ndata: ${JSON.stringify(data)}\n\n`);
};
const onMilestoneValidationUpdated = (data: any) => {
const onMilestoneValidationUpdated = (data: unknown) => {
send(`event: milestone:validation:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
@@ -313,15 +312,13 @@ export function createSSE(
send(`event: fix-feature:created\ndata: ${JSON.stringify(payload)}\n\n`);
};
const onAiSessionUpdated = (data: any) => {
const onAiSessionUpdated = (data: unknown) => {
send(`event: ai_session:updated\ndata: ${JSON.stringify(data)}\n\n`);
};
const onAiSessionDeleted = (data: any) => {
const onAiSessionDeleted = (data: unknown) => {
send(`event: ai_session:deleted\ndata: ${JSON.stringify(data)}\n\n`);
};
/* eslint-enable @typescript-eslint/no-explicit-any */
// --- Unified plugin lifecycle handler ---
// Instead of emitting individual plugin events, we normalize all plugin
// lifecycle changes into a single `plugin:lifecycle` SSE event with
@@ -358,11 +355,11 @@ export function createSSE(
};
// --- Agent lifecycle event handlers ---
const onAgentCreated = (agent: any) => {
const onAgentCreated = (agent: unknown) => {
send(`event: agent:created\ndata: ${JSON.stringify(agent)}\n\n`);
};
const onAgentUpdated = (agent: any) => {
const onAgentUpdated = (agent: unknown) => {
send(`event: agent:updated\ndata: ${JSON.stringify(agent)}\n\n`);
};
@@ -392,11 +389,11 @@ export function createSSE(
};
// --- Chat store event handlers ---
const onChatSessionCreated = (session: any) => {
const onChatSessionCreated = (session: unknown) => {
send(`event: chat:session:created\ndata: ${JSON.stringify(session)}\n\n`);
};
const onChatSessionUpdated = (session: any) => {
const onChatSessionUpdated = (session: unknown) => {
send(`event: chat:session:updated\ndata: ${JSON.stringify(session)}\n\n`);
};
@@ -404,7 +401,7 @@ export function createSSE(
send(`event: chat:session:deleted\ndata: ${JSON.stringify({ id: sessionId })}\n\n`);
};
const onChatMessageAdded = (message: any) => {
const onChatMessageAdded = (message: unknown) => {
send(`event: chat:message:added\ndata: ${JSON.stringify(message)}\n\n`);
};