Develop - #217
Merged
Merged
Conversation
- Revert template-model upload endpoint from /documents back to /upload.
The /documents route (addDocumentToTemplateModel) expects
AddDocumentDto { labelingDocumentId } and attaches an existing labeling
document; it rejects the file-upload payload (400) and returns
labeling_document (snake_case) rather than the labelingDocument the
handler reads, breaking model-detail document uploads.
- Remove the remote Figma html-to-design capture <script> from index.html;
it shipped to all environments as uncontrolled third-party JS.
- Fix CSS specificity so selected rows highlight their sticky checkbox/
actions cells: the nth-of-type(odd) striped rule (0,4,0) was overriding
the selected rule (0,3,0); raise it via .rows-tab-row.rows-tab-row--selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update frontend components and styles
…ters A prod outage occurred when WAL filled the app-pg data volume: the pgBackRest repo filled with huge hourly incrementals (~256MB each, re-copying whole changed file segments of the high-churn ocr_results table), which stalled WAL archiving, so Postgres stopped recycling WAL until pgdata hit 100% and the DB crashed. Enable block incremental (repo1-block) + bundling (repo1-bundle, required) on both the app and temporal Postgres clusters. Block incremental backs up only the changed blocks within a file instead of the whole file segment, which collapses those 256MB incrementals to a few MB and keeps the repo from filling. These were applied live during incident recovery; this codifies them so a redeploy does not revert the change. (pgBackRest 2.56 in cluster; needs 2.46+.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prod app Postgres data volume was expanded in-place from 1.5Gi to 5Gi after pg_wal accumulation filled the original volume and crashed the database (prod outage). The base manifest still requests 1.5Gi, so the Crunchy operator would emit the recurring "field can not be less than previous value" reconcile error. Pin app-pg pgdata to 5Gi via the prod-resources component (same pattern as temporal-pg). base stays 1.5Gi for ephemeral/test instances. Note: this only codifies the storage size. The underlying cause of the WAL growth is the pgBackRest backup repo (repo1) being full, which blocks WAL archiving — that must be addressed separately or the volume will refill. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Documents could be orphaned in `ongoing_ocr` ("Processing") forever: the
graph workflow set that status up front, but on failure it re-threw without
resetting it, and the Azure submit activity retried deterministic 4xx errors
(e.g. a password-protected PDF) before failing. Such documents could neither
finish nor be deleted (deleteDocument refuses in-flight docs).
Three guards so a failed run always reaches a terminal status:
- Reject password-protected PDFs at normalization via mupdf `needsPassword()`
-> `conversion_failed`, so they never enter OCR. Only open-password PDFs are
rejected; permission-only encrypted PDFs (readable by OCR) still pass, so the
pdf-lib pass keeps `ignoreEncryption: true`.
- Make deterministic Azure 4xx (except 429) non-retryable in the submit
activity so the workflow fails fast instead of burning retries; 429/5xx stay
retryable.
- On workflow failure, transition the document from an in-flight status to
`failed` (guarded against clobbering progressed/cancelled docs; never masks
the original error).
Also surface the specific failure reason to the upload caller: a
password-protected PDF now returns `code: "password_protected"` with an
actionable message instead of the generic `conversion_failed`.
Both `failed` and `conversion_failed` are terminal/purgeable, so the ephemeral
cleanup janitor reclaims blobs + Temporal records as usual.
Tests: submit-to-azure-ocr (retryable vs non-retryable), graph-workflow
failure-path hook, pdf-normalization password probe + code, document.service
and upload.controller code/reason surfacing. Docs in docs-md updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
POST /api/documents/:documentId/reprocess re-runs a document's workflow from the beginning using its existing normalized PDF. This is the supported way to retry a broken or stuck run, and (looped over IDs) to clear stuck backlogs without direct DB/Temporal edits. Eligible only for `failed` or stuck `ongoing_ocr` documents. Each guard failure returns 409 with a specific reason: wrong state, missing/purged source file, in-flight run, or no workflow configuration. 404 if missing, 403 if not a group member, 202 on success with the new workflow execution id. The route lives on OcrController (whose base path is `api`, so the URL is unchanged) rather than DocumentController: DocumentModule importing OcrModule would create a module-evaluation cycle (OcrService already depends on DocumentService). OcrController already has both services available. - OcrService.reprocessDocument: guards + delegate to requestOcr, which starts graph-<id> (Temporal default ALLOW_DUPLICATE reuse permits a new run since the prior one is closed) and sets the document back to ongoing_ocr. - TemporalClientService.isWorkflowRunning: live-run check; false when no execution exists (orphaned doc whose prior run already closed). Pairs with the OCR failure-handling fixes on this branch: a re-run of a permanently-bad document now fails fast and lands in `failed` instead of re-stranding in `ongoing_ocr`, so looping the endpoint over the backlog converges. Tests: OcrService guards + delegate, isWorkflowRunning (running/closed/ not-found), and OcrController route (404/403/202). Design spec under docs/superpowers/specs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconciles the OCR-results work that diverged: develop's ExtractedTextView (markdown rendering via react-markdown + sanitize, with a rendered/raw toggle) and this branch's OcrResults toggle (Extracted / Text / JSON). - OcrResults keeps the 3-way toggle shell + JSON debug view; its Text view now delegates to ExtractedTextView so Azure layout markdown renders safely instead of being dumped as split-by-newline <p> tags. - OcrResult.content uses develop's OcrContent type; dropped the duplicate inline content shape introduced here. - Fixed conditional-hook ordering (useState now runs before the null guard) and disabled toggles for views with no data. - DocumentViewerModal renders <OcrResults> guarded by develop's hasOcrData, preserving purged-document handling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revert the non-retryable ApplicationFailure for deterministic 4xx Azure responses so Temporal applies the activity retry policy for all submit failures (4xx and 5xx alike); the graph-workflow failure-path hook still drives the document to terminal failed once retries are exhausted, so documents no longer strand in Processing. Update the submit-to-azure-ocr test and OCR_FAILURE_HANDLING.md, reformat graph-workflow.test.ts to satisfy biome, and regenerate the OpenAPI spec to pick up the reprocess endpoint and password_protected upload descriptions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clicking the already-active toggle in the OCR Results view deselected it in react-aria's single-selection mode, leaving an empty selection that rendered the "Invalid results selection" fallback. Add disallowEmptySelection so a view is always selected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(infra): pgBackRest block incremental + prod Postgres data-volume sizing
fix(ocr): stop documents getting stuck in "Processing" on OCR failure
AI-1445 More OCR Results Views
alex-struk
requested review from
NoorChasib,
antsand,
dbarkowsky and
kmandryk
as code owners
June 29, 2026 21:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AI-###
Changes
Testing
Checklist
By submitting this pull request, I acknowledge that I have attempted to meet the following: