Skip to content

fix(autonomous): guard rowTo* JSON.parse with safe fallback (AUDIT-H1)#261

Merged
xlabtg merged 4 commits intoxlabtg:mainfrom
konard:issue-260-bcb12162f200
Apr 22, 2026
Merged

fix(autonomous): guard rowTo* JSON.parse with safe fallback (AUDIT-H1)#261
xlabtg merged 4 commits intoxlabtg:mainfrom
konard:issue-260-bcb12162f200

Conversation

@konard
Copy link
Copy Markdown

@konard konard commented Apr 22, 2026

Fixes #260AUDIT-H1: JSON.parse in rowTo* has no try/catch — one bad row DoSes listing.

Problem

rowToTask, rowToCheckpoint, and rowToLogEntry in src/memory/agent/autonomous-tasks.ts called JSON.parse(...) on ten different columns without any error handling. A single row with corrupt JSON (manual DB edits, crashed writes, buggy backfills) propagated a SyntaxError out of listTasks / getTask / getCheckpoint / getExecutionLogs, breaking the entire /api/autonomous page and leaving the operator no in-UI path to diagnose which row was bad.

Fix

Added a safeJSONParse<T>(value, fallback, context?) helper at the top of autonomous-tasks.ts:

  • Returns the fallback when the value is not a string or JSON.parse throws.
  • Logs a warn via the module logger with taskId / checkpointId / column context and a truncated copy of the offending value so operators can locate the bad row.
  • Each call site picks a typed fallback that matches the column's intent: [] for array columns (success_criteria, failure_conditions, tool_calls), {} for object columns (constraints, context, state), a sane default RetryPolicy for retry_policy, and undefined for the optional execution_logs.data.

Reproduction + Test Coverage

New src/memory/__tests__/autonomous-tasks.test.ts with 13 tests covering the acceptance criteria:

  • listTasks with one corrupt row returns all three rows (two good + the corrupt one with fallback fields) and does not throw.
  • A warning is logged whose context includes the corrupt row's taskId.
  • rowToTask fallbacks verified per column: corrupt context{}, success_criteria[], failure_conditions[], constraints{}, retry_policy → default {maxRetries, backoff}.
  • rowToCheckpoint fallbacks: corrupt state{}, corrupt tool_calls[], warning includes checkpointId.
  • rowToLogEntry: corrupt data column → undefined; NULL data does not log a warning.
  • Happy-path (valid JSON) parsing continues to work unchanged.

Acceptance criteria

  • All JSON.parse in rowTo* are wrapped in safeJSONParse with a safe fallback.
  • Unit test: table with one corrupt row → listTasks returns all remaining rows and logs a warning instead of throwing.
  • Unit test: rowToTask on corrupt metadata/context returns fallback {}.
  • Unit test: rowToCheckpoint on corrupt state returns fallback {}.
  • Log line includes taskId for diagnostics.

Verification

  • npx vitest run src/memory/__tests__/autonomous-tasks.test.ts → 13/13 ✅
  • npx vitest run → 2943/2943 ✅
  • npm run lint → clean ✅
  • npx tsc --noEmit → clean ✅
  • npx prettier --check … → clean ✅

Test plan

  • Run npm test locally
  • Run npm run lint
  • Run npm run typecheck
  • CI green on this PR

konard added 2 commits April 22, 2026 19:58
Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: xlabtg#260
A single row with malformed JSON in success_criteria, failure_conditions,
constraints, retry_policy, context, state, tool_calls, or data would throw
out of rowToTask/rowToCheckpoint/rowToLogEntry and DoS /api/autonomous.
Wrap every parse in a safeJSONParse helper that logs a warning with
task/checkpoint context and returns a typed fallback so one bad row no
longer takes down listing.
@konard konard changed the title [WIP] audit-h1-json-parse-no-try-catch fix(autonomous): guard rowTo* JSON.parse with safe fallback (AUDIT-H1) Apr 22, 2026
@konard konard marked this pull request as ready for review April 22, 2026 20:07
@konard
Copy link
Copy Markdown
Author

konard commented Apr 22, 2026

Solution summary

Done. PR #261 is ready: #261

Summary of changes

  • src/memory/agent/autonomous-tasks.ts — added module logger and safeJSONParse<T>(value, fallback, context?) helper. Wrapped all 10 JSON.parse call sites in rowToTask (5), rowToCheckpoint (2), and rowToLogEntry (1) with typed fallbacks ([], {}, default RetryPolicy, undefined) and contextual warning logs that include taskId / checkpointId / column.
  • src/memory/__tests__/autonomous-tasks.test.ts — new vitest suite (13 tests) verifying that one corrupt row no longer DoSes listTasks, each rowTo* returns the documented fallback, valid JSON parses normally, and warnings include the row identifier.

Verification: full vitest run (2943/2943), lint, prettier, and tsc all pass.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Author

konard commented Apr 22, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $2.344123

📊 Context and tokens usage:

Claude Opus 4.7:

  • 77.4K / 1M (8%) input tokens, 15.0K / 128K (12%) output tokens

Total: (86.6K + 2.6M cached) input tokens, 15.0K output tokens, $2.235939 cost

Claude Haiku 4.5:

  • 4.2K / 64K (7%) output tokens

Total: (35.5K + 428.3K cached) input tokens, 4.2K output tokens, $0.108184 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Main model: Claude Opus 4.7 (claude-opus-4-7)
  • Additional models:
    • Claude Haiku 4.5 (claude-haiku-4-5-20251001)

📎 Log file uploaded as Gist (1617KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Author

konard commented Apr 22, 2026

🔄 Auto-restart triggered (iteration 1)

Reason: Merge conflicts detected

Starting new session to address the issues.


Auto-restart-until-mergeable mode is active. Will continue until PR becomes mergeable.

@konard
Copy link
Copy Markdown
Author

konard commented Apr 22, 2026

🔄 Auto-restart-until-mergeable Log (iteration 1)

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $2.173186

📊 Context and tokens usage:

  • 66.0K / 1M (7%) input tokens, 13.5K / 128K (11%) output tokens

Total: (60.6K + 2.9M cached) input tokens, 13.5K output tokens, $2.173186 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Model: Claude Opus 4.7 (claude-opus-4-7)

📎 Log file uploaded as Gist (2978KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

audit-h1-json-parse-no-try-catch

2 participants