Review: Embedding pipeline -- Solid Queue + Ollama + neighbor gem (retroactive)

review-1562-2026-06-23 Review

review approved

Verdict: APPROVED

Retroactive review of board item #1562. This item reached next_up with PR #65 open and rebased because the check-board-advance hook was fail-open. A prior review (review-1562-2026-06-22-r2) already reached APPROVED on 2026-06-22 after a two-round review-fix-re-review loop. This retroactive review confirms the prior approval still holds against the current state of the issue, board item, and PR.

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- depends on paldocs#49 (merged), search split to paldocs#61
  • [x] Repo -- ldraney/paldocs
  • [x] User Story -- "As the platform / I need Rails to generate vector embeddings / So that the Python embedding worker can be deprecated"
  • [x] Context -- thorough: describes current Python pipeline, Rails replacement architecture, and coexistence strategy with race-avoidance plan
  • [x] File Targets -- 5 files (3 new, 2 modified) with "do not touch" entries and rationale. Notes app/services/ may need to be created.
  • [x] Feature Flag -- "none" with justification (replaces existing functionality)
  • [x] Acceptance Criteria -- 4 ACs in testable When/Then format
  • [x] Test Expectations -- 3 unit tests plus run command (bundle exec rspec)
  • [x] Constraints -- Ollama endpoint, model (qwen3-embedding:4b), dimensions (2560), block granularity, mermaid skip, queue depth (~5600), Solid Queue
  • [x] Checklist -- 7 items
  • [x] Related -- project, story, arch note, upstream/downstream issues
All required sections for the Feature template are present and complete.

Traceability

  • [x] story:consolidation label -- present on board item
  • [x] story note verified -- story-paldocs-consolidation exists (note ID 2092, user-story type, project paldocs). Listed in project-paldocs user-stories section.
  • [x] arch:rails-jobs label -- present on board item
  • [x] arch note verified -- arch-rails-jobs exists (note ID 2095, architecture type, project paldocs). Contains sequence diagram matching the described flow.
  • [x] Forgejo issue -- ldraney/paldocs#52, state: open
Traceability triangle is complete.

File Targets

  • [x] app/models/block.rb -- verified on main (5 lines, belongs_to :note). PR branch adds has_neighbors + after_save callback as specified.
  • [x] app/jobs/embed_block_job.rb -- PR creates this. app/jobs/ exists on main with application_job.rb. Implementation includes mermaid skip, text extraction, retry logic.
  • [x] app/services/ollama_client.rb -- PR creates this. app/services/ did not exist; PR creates the directory. HTTP client with typed errors (Error, TimeoutError).
  • [x] config/initializers/ollama.rb -- PR creates this. ENV-based config for URL, model, dimensions, timeout, input prefix.
  • [x] Gemfile -- PR adds neighbor gem (line 18) and webmock for test HTTP stubbing (line 48). solid_queue already present (line 26).
All 5 file targets verified against both the issue spec and the actual PR diff (11 files changed, 483 insertions). PR also adds spec files and ci_schema.sql updates -- all appropriate for the scope.

Repo Placement

OK. Issue filed on ldraney/paldocs, all file targets within paldocs. Single-repo scope. No mismatch.

Dependencies

  • paldocs#49 (schema ownership transfer) -- board item #1559, now in done column (state: closed). Blocker resolved. structure.sql on main has the embedding column (vector(2560)), pgvector extension, and HNSW index.
  • Downstream: paldocs#61 (hybrid search) -- board item #1570, backlog. Depends on embeddings from this ticket. Correctly separated.
  • No blocking dependencies remain. Parallel sprint:1 items (#50 sprint schema, #67 docs) do not conflict.

Acceptance Criteria

4 ACs, all automatable:
  • AC1 (job enqueued on block save) -- verified in PR: spec/models/block_spec.rb has 4 tests including enqueue on create, enqueue on content update, skip on position-only change
  • AC2 (Ollama call + vector write) -- verified in PR: spec/jobs/embed_block_job_spec.rb has 8 tests covering the full job flow
  • AC3 (mermaid skip with embedding_status='skipped') -- verified in PR: job checks block_type == "mermaid" and also skips blank content
  • AC4 (retry with exponential backoff, 3 attempts) -- verified in PR: retry_on with polynomially_longer, attempts: 3, for both TimeoutError and Error
All ACs are covered by tests. PR reports 47 examples, 0 failures locally.

Blast Radius

  • No existing embedding code on main branch -- this is net-new Rails functionality replacing external Python worker.
  • Coexistence strategy is documented: both systems write to blocks.embedding, last-writer-wins during transition.
  • update_columns used in job to bypass callbacks -- avoids re-enqueue loop. Sound pattern.
  • No search endpoints included -- blast radius contained by the split to #61.

Decomposition Assessment

No decomposition needed.
  • File targets: 5 files (3 new, 2 modified) in 1 repo -- under threshold
  • Acceptance criteria: 4 ACs -- under 5 AC threshold
  • Estimated agent work: Under 5 minutes. PR is already implemented with 483 insertions across standard Rails patterns.

Recommendation

No action needed. Prior APPROVED verdict from review-1562-2026-06-22-r2 confirmed. Issue scope is clean, implementation matches spec, all traceability links verified, upstream dependency resolved.