Skip to content

Commit a69a898

Browse files
author
StackMemory Bot (CLI)
committed
refactor: reduce as-any casts by 25% (276 → 206) across 10 core modules
Replace unsafe `as any` with proper types: - SQLite query results → typed row interfaces or Record<string, unknown> - trace-store: added TraceRow/ToolCallRow private interfaces - sqlite-adapter: added typed row casts for detectPatterns, aggregate, importData - database-adapter: fixed EventRow/AnchorRow to match actual SQL columns - dual-stack-manager: typed stack_contexts/handoff_requests query results - Remaining `as any` in dual-stack-manager annotated with eslint-disable (API mismatch)
1 parent 5114ecc commit a69a898

10 files changed

Lines changed: 204 additions & 94 deletions

File tree

src/cli/commands/context.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function createContextCommands(): Command {
4646
SELECT value FROM metadata WHERE key = 'project_id'
4747
`
4848
)
49-
.get() as any;
49+
.get() as Record<string, unknown> | undefined;
5050
if (projectRow?.value) projectId = projectRow.value;
5151
} catch {
5252
// metadata table doesn't exist, use default
@@ -130,7 +130,7 @@ export function createContextCommands(): Command {
130130
try {
131131
const projectRow = db
132132
.prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)
133-
.get() as any;
133+
.get() as Record<string, unknown> | undefined;
134134
if (projectRow?.value) projectId = projectRow.value;
135135
} catch {}
136136

@@ -196,7 +196,7 @@ export function createContextCommands(): Command {
196196
try {
197197
const projectRow = db
198198
.prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)
199-
.get() as any;
199+
.get() as Record<string, unknown> | undefined;
200200
if (projectRow?.value) projectId = projectRow.value;
201201
} catch {}
202202

@@ -257,7 +257,7 @@ export function createContextCommands(): Command {
257257
try {
258258
const projectRow = db
259259
.prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)
260-
.get() as any;
260+
.get() as Record<string, unknown> | undefined;
261261
if (projectRow?.value) projectId = projectRow.value;
262262
} catch {}
263263

@@ -331,7 +331,7 @@ export function createContextCommands(): Command {
331331
try {
332332
const projectRow = db
333333
.prepare(`SELECT value FROM metadata WHERE key = 'project_id'`)
334-
.get() as any;
334+
.get() as Record<string, unknown> | undefined;
335335
if (projectRow?.value) projectId = projectRow.value;
336336
} catch {}
337337

@@ -352,7 +352,7 @@ export function createContextCommands(): Command {
352352
LIMIT 10
353353
`
354354
)
355-
.all(projectId) as any[];
355+
.all(projectId) as Record<string, unknown>[];
356356

357357
console.log('\n🌳 Worktree Contexts\n');
358358
if (worktreeFrames.length === 0) {
@@ -418,7 +418,9 @@ export function createContextCommands(): Command {
418418
LIMIT 1
419419
`
420420
)
421-
.get(projectId, `%"instanceId":"${instanceId}"%`) as any;
421+
.get(projectId, `%"instanceId":"${instanceId}"%`) as
422+
| Record<string, unknown>
423+
| undefined;
422424

423425
if (worktreeFrame) {
424426
const inputs = JSON.parse(worktreeFrame.inputs || '{}');

src/core/context/dual-stack-manager.ts

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,13 @@ export class DualStackManager {
173173
// Execute schema creation using raw SQL
174174
if (this.adapter.isConnected()) {
175175
// Note: This is a temporary workaround - proper schema creation would use adapter methods
176+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
176177
(await (this.adapter as any).execute?.(createStackContextsTable)) ||
177178
this.executeSchemaQuery(createStackContextsTable);
179+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
178180
(await (this.adapter as any).execute?.(createHandoffRequestsTable)) ||
179181
this.executeSchemaQuery(createHandoffRequestsTable);
182+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
180183
(await (this.adapter as any).execute?.(createStackSyncLogTable)) ||
181184
this.executeSchemaQuery(createStackSyncLogTable);
182185
}
@@ -747,30 +750,32 @@ export class DualStackManager {
747750
): Promise<void> {
748751
// Create frame in target stack
749752
await targetStack.createFrame({
750-
type: frame.type as any,
753+
type: frame.type,
751754
name: frame.name,
752755
inputs: frame.inputs,
753756
});
754757

755758
// Copy events
756759
const events = await this.individualStack.getFrameEvents(frame.frame_id);
757760
for (const event of events) {
761+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
758762
await targetStack.addEvent(frame.frame_id, {
759-
type: event.type as any,
763+
type: event.type,
760764
text: event.text,
761765
metadata: event.metadata,
762-
});
766+
} as any);
763767
}
764768

765769
// Copy anchors
766770
const anchors = await this.individualStack.getFrameAnchors(frame.frame_id);
767771
for (const anchor of anchors) {
772+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
768773
await targetStack.addAnchor(frame.frame_id, {
769-
type: anchor.type as any,
774+
type: anchor.type,
770775
text: anchor.text,
771776
priority: anchor.priority,
772777
metadata: anchor.metadata,
773-
});
778+
} as any);
774779
}
775780
}
776781

@@ -784,23 +789,25 @@ export class DualStackManager {
784789
sourceFrame.frame_id
785790
);
786791
for (const event of sourceEvents) {
792+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
787793
await targetStack.addEvent(existingFrame.frame_id, {
788-
type: event.type as any,
794+
type: event.type,
789795
text: event.text,
790796
metadata: { ...event.metadata, merged: true },
791-
});
797+
} as any);
792798
}
793799

794800
const sourceAnchors = await this.individualStack.getFrameAnchors(
795801
sourceFrame.frame_id
796802
);
797803
for (const anchor of sourceAnchors) {
804+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
798805
await targetStack.addAnchor(existingFrame.frame_id, {
799-
type: anchor.type as any,
806+
type: anchor.type,
800807
text: anchor.text,
801808
priority: anchor.priority,
802809
metadata: { ...anchor.metadata, merged: true },
803-
});
810+
} as any);
804811
}
805812
}
806813

@@ -823,14 +830,26 @@ export class DualStackManager {
823830
WHERE stack_id = ?
824831
`);
825832

826-
const row = query.get(stackId) as any;
833+
const row = query.get(stackId) as
834+
| {
835+
stack_id: string;
836+
type: string;
837+
project_id: string;
838+
owner_id: string;
839+
team_id: string;
840+
permissions: string;
841+
metadata: string;
842+
created_at: string;
843+
last_active: string;
844+
}
845+
| undefined;
827846
if (!row) {
828847
return null;
829848
}
830849

831850
return {
832851
stackId: row.stack_id,
833-
type: row.type,
852+
type: row.type as 'individual' | 'shared',
834853
projectId: row.project_id,
835854
ownerId: row.owner_id,
836855
teamId: row.team_id,
@@ -934,7 +953,19 @@ export class DualStackManager {
934953
SELECT * FROM handoff_requests WHERE request_id = ?
935954
`);
936955

937-
const row = query.get(requestId) as any;
956+
const row = query.get(requestId) as
957+
| {
958+
request_id: string;
959+
source_stack_id: string;
960+
target_stack_id: string;
961+
frame_ids: string;
962+
status: string;
963+
created_at: string;
964+
expires_at: string;
965+
target_user_id: string;
966+
message: string;
967+
}
968+
| undefined;
938969
if (row) {
939970
const request: HandoffRequest = {
940971
requestId: row.request_id,
@@ -1028,12 +1059,22 @@ export class DualStackManager {
10281059
WHERE type = 'shared' AND project_id = ?
10291060
`);
10301061

1031-
const rows = query.all(this.activeContext.projectId) as any[];
1062+
const rows = query.all(this.activeContext.projectId) as Array<{
1063+
stack_id: string;
1064+
type: string;
1065+
project_id: string;
1066+
owner_id: string;
1067+
team_id: string;
1068+
permissions: string;
1069+
metadata: string;
1070+
created_at: string;
1071+
last_active: string;
1072+
}>;
10321073

10331074
for (const row of rows) {
10341075
const context: StackContext = {
10351076
stackId: row.stack_id,
1036-
type: row.type,
1077+
type: row.type as 'individual' | 'shared',
10371078
projectId: row.project_id,
10381079
ownerId: row.owner_id,
10391080
teamId: row.team_id,

src/core/context/enhanced-rehydration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export class CompactionHandler {
168168

169169
// Store in frame manager as high-priority anchor
170170
this.frameManager.addAnchor(
171-
'CONSTRAINT' as any, // Using CONSTRAINT type for now
171+
'CONSTRAINT',
172172
JSON.stringify(anchor),
173173
10,
174174
{

src/core/database/database-adapter.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,18 @@ export interface FrameRow {
7979

8080
export interface EventRow {
8181
event_id: string;
82+
run_id: string;
8283
frame_id: string;
8384
seq: number;
84-
type: string;
85-
text: string;
86-
metadata: string;
85+
event_type: string;
86+
payload: string;
87+
ts: number;
8788
}
8889

8990
export interface AnchorRow {
9091
anchor_id: string;
9192
frame_id: string;
93+
project_id: string;
9294
type: string;
9395
text: string;
9496
priority: number;

src/core/database/sqlite-adapter.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {
1515
CountResult,
1616
VersionResult,
1717
FrameRow,
18+
EventRow,
19+
AnchorRow,
1820
ProjectRegistryRow,
1921
} from './database-adapter.js';
2022
import type { Frame, Event, Anchor } from '../context/index.js';
@@ -283,7 +285,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
283285
const needsCascade = (table: string): boolean => {
284286
const rows = this.db!.prepare(
285287
`PRAGMA foreign_key_list(${table})`
286-
).all() as any[];
288+
).all() as Array<{ table: string; on_delete: string }>;
287289
// If any FK points to frames without cascade, we need migration
288290
return rows.some(
289291
(r) =>
@@ -831,7 +833,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
831833

832834
query += ' ORDER BY depth ASC, created_at ASC';
833835

834-
const rows = this.db.prepare(query).all(...params) as any[];
836+
const rows = this.db.prepare(query).all(...params) as FrameRow[];
835837

836838
return rows.map((row) => ({
837839
...row,
@@ -896,7 +898,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
896898
);
897899
query += this.buildLimitClause(options?.limit, options?.offset);
898900

899-
const rows = this.db.prepare(query).all(frameId) as any[];
901+
const rows = this.db.prepare(query).all(frameId) as EventRow[];
900902

901903
return rows.map((row) => ({
902904
...row,
@@ -958,7 +960,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
958960
ORDER BY priority DESC, created_at ASC
959961
`
960962
)
961-
.all(frameId) as any[];
963+
.all(frameId) as AnchorRow[];
962964

963965
return rows.map((row) => ({
964966
...row,
@@ -1063,7 +1065,9 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
10631065
if (options.projectId) params.push(options.projectId);
10641066
params.push(limit, offset);
10651067

1066-
const rows = this.db!.prepare(sql).all(...params) as any[];
1068+
const rows = this.db!.prepare(sql).all(...params) as (FrameRow & {
1069+
score: number;
1070+
})[];
10671071

10681072
// Note: scoreThreshold is not applied to FTS results because BM25 scores
10691073
// are on a different scale than LIKE-based scores. FTS results are already
@@ -1100,7 +1104,9 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
11001104
const params: any[] = Array(6).fill(likeParam);
11011105
if (options.projectId) params.push(options.projectId);
11021106

1103-
let rows = this.db!.prepare(sql).all(...params) as any[];
1107+
let rows = this.db!.prepare(sql).all(...params) as (FrameRow & {
1108+
score: number;
1109+
})[];
11041110

11051111
if (options.scoreThreshold) {
11061112
rows = rows.filter((row) => row.score >= options.scoreThreshold);
@@ -1147,7 +1153,9 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
11471153

11481154
const rows = this.db
11491155
.prepare(sql)
1150-
.all(JSON.stringify(embedding), limit) as any[];
1156+
.all(JSON.stringify(embedding), limit) as (FrameRow & {
1157+
similarity: number;
1158+
})[];
11511159

11521160
return rows.map((row) => ({
11531161
...row,
@@ -1371,7 +1379,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
13711379
if (sinceRowid != null) params.push(sinceRowid);
13721380
params.push(limit);
13731381

1374-
const rows = this.db.prepare(sql).all(...params) as any[];
1382+
const rows = this.db.prepare(sql).all(...params) as FrameRow[];
13751383
return rows.map((row) => ({
13761384
...row,
13771385
inputs: JSON.parse(row.inputs || '{}'),
@@ -1532,7 +1540,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
15321540

15331541
return this.db
15341542
.prepare(sql)
1535-
.all(...Object.values(options.having || {})) as any[];
1543+
.all(...Object.values(options.having || {})) as Record<string, unknown>[];
15361544
}
15371545

15381546
// Pattern detection (basic)
@@ -1566,7 +1574,12 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
15661574

15671575
sql += ' GROUP BY type HAVING COUNT(*) > 1 ORDER BY frequency DESC';
15681576

1569-
const rows = this.db.prepare(sql).all(...params) as any[];
1577+
const rows = this.db.prepare(sql).all(...params) as Array<{
1578+
pattern: string;
1579+
type: string;
1580+
frequency: number;
1581+
last_seen: number;
1582+
}>;
15701583

15711584
return rows.map((row) => ({
15721585
pattern: row.pattern,
@@ -1909,7 +1922,7 @@ export class SQLiteAdapter extends FeatureAwareDatabaseAdapter {
19091922
this.db!.prepare(`DELETE FROM ${table}`).run();
19101923
}
19111924

1912-
for (const row of rows as any[]) {
1925+
for (const row of rows as Record<string, unknown>[]) {
19131926
const cols = Object.keys(row);
19141927
const placeholders = cols.map(() => '?').join(',');
19151928

0 commit comments

Comments
 (0)