fix: prevent JSONB double-encoding on methodology save #6

Merged
chaim merged 2 commits from fix/methodology-jsonb-double-encoding into main 2026-05-10 18:34:03 +00:00
Owner

Summary

  • Remove json.dumps() from asyncpg call — pass req.value (Python list/dict) directly with ::jsonb so asyncpg serializes it correctly as a JSONB array/object
  • Old code stored a JSONB string instead of a JSONB array; the frontend spread operator split it into individual characters — one textarea per character
  • Fix typo in DISCUSSION_RULES default: "אסה רציפה""מאסה רציפה"

Root Cause

json.dumps(list) produces a Python str. When asyncpg receives a Python str for a ::jsonb-typed parameter, it encodes it as a JSONB string value — not a JSONB array.

Test plan

  • Save a rule in "כללי" section of /methodology → verifies saves and reloads as array
  • Check GET /api/methodology/discussion_rulesuniversal.value should be a JSON array

🤖 Generated with Claude Code

## Summary - Remove `json.dumps()` from asyncpg call — pass `req.value` (Python list/dict) directly with `::jsonb` so asyncpg serializes it correctly as a JSONB array/object - Old code stored a JSONB *string* instead of a JSONB array; the frontend spread operator split it into individual characters — one textarea per character - Fix typo in `DISCUSSION_RULES` default: `"אסה רציפה"` → `"מאסה רציפה"` ## Root Cause `json.dumps(list)` produces a Python `str`. When asyncpg receives a Python `str` for a `::jsonb`-typed parameter, it encodes it as a JSONB *string value* — not a JSONB array. ## Test plan - [ ] Save a rule in "כללי" section of `/methodology` → verifies saves and reloads as array - [ ] Check `GET /api/methodology/discussion_rules` — `universal.value` should be a JSON array 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 2 commits 2026-05-10 18:31:50 +00:00
Two bugs caused all 5 interim blocks to fail with "Claude CLI failed
(exit 1): unknown error":

1. source_context was embedded BOTH inside the prompt template (via
   {source_context}) AND prepended again in write_block — doubling every
   block's context size (232K chars × 2 = 465K chars).

2. _build_source_context loaded all 9 case documents for every block
   regardless of relevance.

Fixes:
- Remove the duplicate source_context prepend in write_block; the
  template already contains it via {source_context}
- Add per-block document filtering (_BLOCK_DOC_TYPES): block-he/zayin →
  empty, block-chet → protocol only, block-tet → appraisals only
- Add 400K char guard before calling claude -p with a descriptive error
  (vs opaque "exit 1: unknown error")
- Add prompt-size warning and size info in claude_session error messages

Result: block-he 0 chars, block-zayin 0 chars, block-vav ~172K,
block-chet ~45K, block-tet ~300K (all under 400K limit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass req.value directly to asyncpg instead of json.dumps(req.value).
When a Python string was passed with ::jsonb, asyncpg encoded it as a
JSONB string (not an array), causing the frontend spread operator to
split it into individual characters — one textarea per character.

Also fix typo in DISCUSSION_RULES default: "אסה" → "מאסה".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chaim merged commit d983cfdd3b into main 2026-05-10 18:34:03 +00:00
chaim deleted branch fix/methodology-jsonb-double-encoding 2026-05-10 18:34:03 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#6