Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Claude's suggestion for code improvements
  • Loading branch information
seefeldb committed Jun 2, 2025
commit db282ab0f4c0b174d78c656bf0ae28077cb30da2
115 changes: 115 additions & 0 deletions docs/code-quality-tasks/ambiguous-types-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Ambiguous Types and Inappropriate 'any' Usage Report
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document hard-codes exact source line numbers (e.g. Line 31) which will quickly become stale as code evolves, making the report misleading and harder to maintain.


Based on the search through the TypeScript files in the packages/ directory, I've found several patterns of inappropriate type usage according to AGENTS.md guidelines:

## 1. Direct Usage of 'any' Type

### packages/runner/src/utils.ts
- **Line 31**: `extractDefaultValues(schema: any): any` - Function accepts and returns 'any' without proper type validation
- **Line 35**: `const obj: any = {}` - Local variable using 'any'
- **Line 58**: `mergeObjects(...objects: any[]): any` - Function accepts array of 'any' and returns 'any'
- **Line 64**: `const result: any = {}` - Local variable using 'any'
- **Line 107-110**: `sendValueToBinding(doc: DocImpl<any>, binding: any, value: any, log?: ReactivityLog)` - Multiple 'any' parameters
- **Line 137-139**: `setNestedValue(doc: DocImpl<any>, path: PropertyKey[], value: any, log?: ReactivityLog)` - 'any' in generic and parameter
- **Line 167-169**: Multiple functions in traverse.ts using 'any' parameters (lines ~221-224)
- **Line 256**: `unsafe_noteParentOnRecipes(recipe: Recipe, binding: any)` - Accepts 'any' parameter
- **Line 283**: `findAllAliasedCells(binding: any, doc: DocImpl<any>)` - Multiple 'any' usage
- **Line 540-546**: `maybeGetCellLink(value: any, parent?: DocImpl<any>)` - 'any' parameters
- **Line 555**: `followAliases(alias: any, doc: DocImpl<any>, log?: ReactivityLog)` - 'any' parameter
- **Line 583**: `diffAndUpdate(current: CellLink, newValue: any, log?: ReactivityLog, context?: any)` - Multiple 'any'
- **Line 616-620**: `normalizeAndDiff(current: CellLink, newValue: any, log?: ReactivityLog, context?: any)` - Multiple 'any'
- **Line 896**: `addCommonIDfromObjectID(obj: any, fieldName: string = "id")` - 'any' parameter
- **Line 915**: `maybeUnwrapProxy(value: any): any` - Accepts and returns 'any'
- **Line 932**: `containsOpaqueRef(value: any): boolean` - 'any' parameter
- **Line 941**: `deepCopy(value: any): any` - Accepts and returns 'any'

### packages/js-runtime/interface.ts
- **Line 12**: `invoke(...args: any[]): JsValue` - Array of 'any' as parameters
- **Line 13**: `inner(): any` - Returns 'any'

### packages/builder/src/built-in.ts
- **Line 24**: `error: any` - Property typed as 'any'
- **Line 44**: `error: any` - Property typed as 'any'
- **Line 55**: `error: any` - Property typed as 'any'
- **Line 57**: `ifElse<T = any, U = any, V = any>` - Generic parameters defaulting to 'any'
- **Line 69**: `let ifElseFactory: NodeFactory<[any, any, any], any> | undefined` - Multiple 'any' in generic
- **Line 74**: `(cell: OpaqueRef<any>) => OpaqueRef<string>` - 'any' in generic
- **Line 82**: `...values: any[]` - Array of 'any'
- **Line 89**: `values: any[]` - Array of 'any'

### packages/memory/traverse.ts
- **Line 167-169**: `[k, this.traverseDAG(doc, docRoot, v, tracker)]),` - Using 'any' in type assertion
- **Line 355**: `isPointer(value: any): boolean` - 'any' parameter
- **Line 365**: `isJSONCellLink(value: any): value is JSONCellLink` - 'any' parameter
- **Line 371-379**: Multiple functions accepting 'any' parameters

### packages/html/src/render.ts
- **Line 60-70**: Comments indicate potential issues with type handling but implementation uses proper types

## 2. Type Assertions Using 'as any'

### packages/runner/src/runner.ts
- **Line ~224**: Type assertion `as any` in runtime context

### packages/runner/src/cell.ts
- **Line ~118**: `(self.key as any)(key).set(value)` - Type assertion to bypass type checking

### packages/runner/src/query-result-proxy.ts
- **Line ~42**: `const target = valueCell.getAtPath(valuePath) as any` - Type assertion
- **Line ~120**: `undefined as unknown as any[]` - Multiple type assertions

### packages/builder/src/spell.ts
- **Line ~25**: `if (typeof prop === "symbol") return (target as any)[prop]` - Type assertion
- **Line ~48**: `[key, (self as any)[key]]` - Type assertion in mapping

### packages/builder/src/utils.ts
- **Line ~117**: `for (const key in value as any)` - Type assertion in loop

### packages/builder/src/recipe.ts
- **Lines ~182-186**: Multiple `as any` assertions when deleting properties

### packages/memory/traverse.ts
- **Line ~169**: Type assertion in mapping function

## 3. Overly Broad Union Types

While I didn't find the specific pattern `string | number | object | null`, there are several places with overly permissive types:

### packages/builder/src/types.ts
- **Line ~244**: `cell?: any` in Alias type - Should be more specific
- **Line ~263**: `implementation?: ((...args: any[]) => any) | Recipe | string` - Function signature with 'any'

## 4. Functions Accepting Overly Broad Types Without Validation

### packages/runner/src/utils.ts
- `extractDefaultValues`, `mergeObjects`, `sendValueToBinding`, `setNestedValue` - All accept 'any' without proper type guards or validation
- These functions perform operations on the values but don't validate the types first

### packages/memory/traverse.ts
- Multiple traversal functions accept 'any' or 'unknown' without proper validation

## 5. Unknown Types That Should Be More Specific

### packages/js-runtime/interface.ts
- **Lines 70-79**: `isJsModule` function uses 'unknown' but could use a more specific base type
- **Lines 97-104**: `isSourceMap` function uses 'unknown' but could use a more specific base type

### packages/memory/traverse.ts
- **Lines 371-389**: Multiple functions use 'unknown' parameters that could be more specific
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, do we not want unknown in predicate functions?


## Recommendations

1. **Replace 'any' with specific types or generics** where possible
2. **Add proper type guards** for functions that need to accept broad types
3. **Use discriminated unions** instead of 'any' for values that can be multiple types
4. **Avoid type assertions** (`as any`) - instead, use type guards or proper typing
5. **Document why 'any' is necessary** in the few cases where it truly is needed
6. **Consider using 'unknown'** instead of 'any' and add type guards for safety

## Priority Files to Fix

1. **packages/runner/src/utils.ts** - Has the most 'any' usage
2. **packages/builder/src/built-in.ts** - Core functionality with multiple 'any'
3. **packages/memory/traverse.ts** - Complex traversal logic with 'any'
4. **packages/builder/src/types.ts** - Type definitions themselves use 'any'
5. **packages/js-runtime/interface.ts** - Interface definitions with 'any'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File lacks a trailing newline, which can cause unnecessary diffs and violates POSIX text file conventions.

282 changes: 282 additions & 0 deletions docs/code-quality-tasks/inappropriate-error-handling-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
# Inappropriate Error Handling Report
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


Based on the analysis of the codebase against AGENTS.md guidelines, the
following inappropriate error handling patterns were found:

## 1. Try/catch Blocks That Silently Swallow Errors

### `packages/jumble/src/components/NetworkInspector.tsx`

**Lines**: 236-238

```typescript
} catch (e) {
return null;
}
```

**Issue**: Silently catches errors and returns null without any logging or
re-throwing. This makes debugging impossible and hides potential issues.

### `packages/toolshed/lib/otel.ts`

**Lines**: 60-62

```typescript
} catch (_) {
// ignored – not running on Deno with telemetry support
}
```

**Issue**: Empty catch block that completely swallows errors. Even if the error
is expected, it should at least be logged for debugging purposes.

## 2. Different Error Handling Approaches in the Same Code Path

### `packages/runner/src/runner.ts`

**Lines**: 358-363

```typescript
try {
cancel();
} catch (error) {
console.warn("Error canceling operation:", error);
}
```

**Issue**: Uses `console.warn` for errors in a method that should likely
propagate errors up to the caller for proper handling.

### `packages/js-runtime/typescript/compiler.ts`

**Lines**: 111-114

```typescript
} catch (e) {
console.warn(`There was an error parsing "${key}" source map: ${e}`);
}
```

**Issue**: Uses `console.warn` instead of throwing or properly handling the
parsing error. Source map parsing errors could indicate serious issues.

### `packages/llm/src/client.ts`

**Lines**: 101-103, 115-117

```typescript
} catch (error) {
console.error("Failed to parse JSON line:", line, error);
}
```

**Issue**: Logs errors to console instead of propagating them, while other parts
of the same method throw errors. This creates inconsistent error handling.

## 3. Functions Returning undefined/null on Error Instead of Throwing

### `packages/jumble/src/components/NetworkInspector.tsx`

**Lines**: 213-239

```typescript
const extractTransactionDetails = (value: any): any => {
try {
// ... processing logic ...
} catch (e) {
return null;
}
};
```

**Issue**: Returns null on any error instead of throwing or properly handling
specific error cases. Callers can't distinguish between "no data" and "error
occurred".

### `packages/ui/src/components/common-form.ts`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we may want to ignore ui in these agent flows; mostly older code that we're using a small subset of, and unique compared to the rest of the codebase (lit elements)


**Lines**: 64-66

```typescript
} catch {
return "Invalid reference format";
}
```

**Issue**: Returns an error string instead of throwing, inconsistent with other
validation patterns that throw errors.

### `packages/charm/src/spellbook.ts`

```typescript
} catch (error) {
console.error("Failed to save spell:", error);
return false;
}
```

**Issue**: Returns false on error instead of throwing, preventing callers from
understanding why the operation failed.

## 4. Overly Broad try/catch Blocks

### `packages/charm/src/manager.ts`

**Lines**: 500-700+

```typescript
try {
// Hundreds of lines of code including:
// - Multiple async operations
// - Complex data transformations
// - Nested function calls
} catch (error) {
console.debug("Error in findReferencedCharms:", error);
}
```

**Issue**: Try block covers too much code, making it difficult to understand
which operation actually failed. Errors from very different operations are
handled identically.

## 5. Low-level try/catch Where Errors Should Propagate

### `packages/charm/src/workflow.ts`

Multiple instances of:

```typescript
try {
// Some operation
} catch (error) {
console.warn("Operation failed:", error);
// Continues execution
}
```

**Issue**: Error handling at the workflow processing level prevents higher-level
error handlers from taking appropriate action (retry, fallback, user
notification).

### `packages/background-charm-service/src/worker.ts`

**Lines**: 186-188

```typescript
} catch (error) {
const errorMessage = String(error);
// Loses stack trace and error type information
}
```

**Issue**: Converts errors to strings, losing valuable debugging information
like stack traces and error types.

## 6. Missing Error Context or Unhelpful Error Messages

### `packages/toolshed/routes/integrations/google-oauth/google-oauth.utils.ts`

**Lines**: 162, 195

```typescript
throw new Error(`Failed to get auth cell: ${error}`);
throw new Error(`Error persisting tokens: ${error}`);
```

**Issue**: Simply wraps errors without adding meaningful context about what was
being attempted, what the inputs were, or suggestions for resolution.

## 7. Console Logging in Production Code

Multiple files use console methods for error handling instead of proper error
propagation:

- `packages/charm/src/format.ts` - Uses `console.error`
- `packages/charm/src/search.ts` - Uses `console.warn`
- `packages/charm/src/workflow.ts` - Mixed `console.warn` and `console.error`
- `packages/charm/src/iframe/recipe.ts` - Uses `console.log` for errors

**Issue**: Console logging is not appropriate for production error handling.
Errors should be propagated or logged through proper logging mechanisms.

## Recommendations Based on AGENTS.md

### 1. Let Errors Propagate

```typescript
// Good - let caller handle the error
async function getData(): Promise<string> {
const res = await fetch(URL);
if (res.ok) {
return res.text();
}
throw new Error("Unsuccessful HTTP response");
}

// Bad - swallowing errors
async function getData(): Promise<string | undefined> {
try {
const res = await fetch(URL);
if (res.ok) {
return res.text();
}
} catch (e) {
console.error(e);
}
}
```

### 2. Only Catch When You Can Handle

```typescript
// Good - specific error handling with retry
async function fetchWithRetry(url: string, retries = 3): Promise<Response> {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === retries - 1) throw error;
await delay(1000 * Math.pow(2, i)); // exponential backoff
}
}
throw new Error("Should not reach here");
}
```

### 3. Add Meaningful Context

```typescript
// Good - adds context to errors
try {
await saveUserData(userId, data);
} catch (error) {
throw new Error(
`Failed to save data for user ${userId}: ${error.message}`,
{ cause: error },
);
}
```

### 4. Use Type Guards for Expected Errors

```typescript
// Good - handle specific, expected scenarios
function isFeatureSupported(): boolean {
try {
// Try to use feature
crypto.subtle.importKey(...);
return true;
} catch {
// Expected error - feature not supported
return false;
}
}
```

## Priority Areas to Fix

1. **High Priority**: Error swallowing in core libraries (`runner`, `builder`,
`charm`)
2. **Medium Priority**: Console logging instead of proper error handling
3. **Low Priority**: Missing error context in utility functions
Loading