7e-1: Source-of-truth cutover — note writes parse to blocks first #109
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-api#109
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
plan-2026-02-26-tf-modularize-postgres→ Phase 7 (Block Content) → Phase 7e (Compiled Pages) → Phase 7e-1Repo
forgejo_admin/pal-e-docsUser Story
As an agent using block tools (get_section, update_block),
I want blocks to always reflect the latest note content,
So that block reads are never stale after an update_note() call.
Context
Block API endpoints exist (Phase 7d) and work correctly — block writes trigger recompilation of both
compiled_pagesandnotes.html_content. But the reverse path is broken:create_note()andupdate_note()write directly tohtml_contentwithout parsing to blocks. Every note write via the original API silently causes blocks and html_content to go out of sync.This makes block tools unreliable. An agent that calls
update_note(content=...)then later callsget_section()will get stale block data. The fix: make blocks canonical by having note writes parse to blocks first, then recompile.The parser (
parse_html_to_blocks) and compiler (compile_blocks_to_html) are already proven — they processed all 274 notes during the Phase 7c backfill. The_recompile()helper inroutes/blocks.pyalready handles the blocks→html_content sync. This phase wires up the reverse direction.File Targets
Files the agent should modify:
src/pal_e_docs/routes/notes.py—create_note()andupdate_note()functions. Whenhtml_contentis provided:parse_html_to_blocks()_recompile()pattern fromroutes/blocks.pyhtml_contentfrom compiled output (not from raw input — ensures round-trip consistency)Files the agent should reference (read, don't modify):
src/pal_e_docs/routes/blocks.py—_recompile()helper is the pattern to followsrc/pal_e_docs/blocks/parser.py—parse_html_to_blocks()src/pal_e_docs/blocks/compiler.py—compile_blocks_to_html()src/pal_e_docs/models.py—Block,CompiledPage,NotemodelsFiles the agent should NOT touch:
src/pal_e_docs/routes/blocks.py— block write endpoints already work correctlysrc/pal_e_docs/blocks/parser.py— parser is proven, no changes neededsrc/pal_e_docs/blocks/compiler.py— compiler is proven, no changes neededAcceptance Criteria
create_note(html_content=...)results in blocks + compiled_page created alongside the noteupdate_note(html_content=...)results in blocks matching the updated HTML (delete old blocks, parse new ones)Test Expectations
pytest tests/ -vConstraints
_recompile()pattern fromroutes/blocks.py— don't reinvent the sync logic_recompile()to a shared module if importing across route files is cleaner than duplicatingblock_type,content,anchor_id,position— these map directly to the Block modelhtml_contentstored on the note should be the COMPILED output, not the raw input — this ensures the round-trip is deterministicChecklist
Related
phase-postgres-7e-compiled-pages— phase note with full contextphase-postgres-7d-api-mcp-tools— block API (prerequisite, COMPLETED)benchmark-phase7-block-baseline— baseline measurements