Review: Port template rendering from Jinja2 to ERB for create_note_from_template

review-1602-2026-06-24 Review

review ready

Verdict: READY

Scope is solid. File targets verified against committed codebase. Traceability complete (story note exists; arch note missing but pre-existing gap across all rails-api tickets). Single-repo, 3 file targets, 3 ACs — fits a single agent pass well under 5 minutes.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Spike #75 (PR #76) Gap 7
  • [x] Repo — ldraney/paldocs
  • [x] User Story — present, well-formed
  • [x] Context — clear description of silent failure mode
  • [x] File Targets — 3 targets listed with descriptions
  • [x] Feature Flag — "none" (correct, internal API change)
  • [x] Acceptance Criteria — 3 criteria, verifiable
  • [x] Test Expectations — 3 unit tests + run command
  • [x] Constraints — ERB/Liquid preference, data dict compat, migration path noted
  • [x] Checklist — standard PR/test/no-unrelated
  • [x] Related — project + spike references

Traceability

  • [x] story:consolidation label — present on board item
  • [x] story note verified — story-paldocs-consolidation found in project-paldocs user-stories section: "absorb pal-e-docs into Rails monolith (schema, API, embeddings)"
  • [x] arch:rails-api label — present on board item
  • [ ] arch note MISSING — no arch-rails-api note exists in pal-e-docs. However, this is a pre-existing gap shared across all 6+ board items with the arch:rails-api label (items #1568, #1569, #1570, #1599, #1600, #1601, #1602). Not a blocker for this ticket specifically — the arch note should be created as a separate backlog item.
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/ldraney/paldocs/issues/81, state: open

File Targets

  • [x] app/controllers/api/notes_controller.rb — verified: exists in git HEAD (commit 311f4a4). Contains from_template action at line 126. Currently copies template.html_content verbatim; data param is permitted in template_params but never used. Confirmed silent failure.
  • [x] app/services/template_renderer.rb (new) — confirmed does not exist yet. app/services/ directory also does not exist. Both need to be created.
  • [x] Reference: pal-e-docs/src/pal_e_docs/routes/notes.py — verified: exists at /home/ldraney/pal-e-docs/src/pal_e_docs/routes/notes.py. /from-template endpoint at line 551-585 calls render_template() service.
  • [x] Reference: pal-e-docs/src/pal_e_docs/services/template_renderer.py — verified: complete Jinja2 implementation. Finds code block with language: "jinja2", renders with data dict, raises 3 custom exceptions (TemplateNotFoundError, TemplateBlockNotFoundError, TemplateRenderError).

Repo Placement

OK. Issue filed on ldraney/paldocs, all file targets are in paldocs. Reference files in pal-e-docs are read-only reference, not modified. Single-repo change.

Dependencies

  • Depends on sprint:1 item #1567 (API namespace + Notes controller, 12 endpoints) — DONE. The from_template action and route already exist.
  • Spike #75 (MCP endpoint compatibility) is in_progress — this ticket was identified as Gap 7 from that spike. No hard blocker; spike validates the gap exists but implementation can proceed independently.
  • No downstream blockers identified on the board.

Acceptance Criteria

All 3 ACs are verifiable by an agent:
  • AC1: POST with data param renders variables — testable via request spec
  • AC2: Templates without renderable blocks copy verbatim — testable via request spec (existing test already covers this path)
  • AC3: Invalid/missing data keys produce clear error — testable via request spec
Test run command is accurate: bin/rails test test/requests/api/notes_* test/services/template_renderer_*. Existing spec at spec/requests/api/notes_spec.rb has 2 from_template tests (create success + 404) that will need to be extended.
Note: Test command uses bin/rails test (Minitest path convention) but existing tests are in spec/ (RSpec). Agent should use bundle exec rspec spec/requests/api/notes_spec.rb spec/services/ instead. Minor issue — agent will adapt.

Blast Radius

  • MCP tool consumers: The create_note_from_template MCP tool (used by all Claude agents) currently sends a data JSON string. The pal-e-docs FastAPI server renders it; the paldocs Rails server silently ignores it. After this fix, both servers will render templates. Behavior change is the intended fix.
  • Existing templates: Templates in pal-e-docs use Jinja2 syntax in code blocks. The issue's constraint section correctly notes the need to handle existing Jinja2 syntax or define a migration path. ERB uses different delimiters (<%= %> vs {{ }}), so existing templates would need updating if ERB is chosen. Liquid uses {{ }} like Jinja2, which would be more compatible.
  • Hook reference: claude-custom/hooks/block-docs-writes.sh line 33 references mcp__pal-e-docs__create_note_from_template — no change needed, this is a tool name reference not a template format.
  • Backward compatibility: AC2 covers this — templates without renderable blocks must copy verbatim. This is critical since many templates have no code blocks.

Decomposition Assessment

No decomposition needed.
  • 3 file targets in 1 repo — under threshold
  • 3 acceptance criteria — under threshold
  • Estimated agent work: straightforward port of well-documented Python logic to Ruby equivalent, well under 5 minutes
  • Clear reference implementation exists

Recommendation

No action needed. Ticket is READY for implementation.
Advisory notes (non-blocking):
  • [SCOPE] Create architecture note arch-rails-api for the Rails API component — shared gap across 6+ board items. Should be a separate backlog item, not a blocker for this ticket.
  • The test run command in the issue uses Minitest conventions but the project uses RSpec. Agent will adapt at implementation time.