Skip to content

Develop - #217

Merged
alex-struk merged 24 commits into
mainfrom
develop
Jun 29, 2026
Merged

Develop#217
alex-struk merged 24 commits into
mainfrom
develop

Conversation

@alex-struk

Copy link
Copy Markdown
Collaborator

Summary

AI-###

Changes

Testing

Checklist

By submitting this pull request, I acknowledge that I have attempted to meet the following:

  • a self-review of my code
  • commented code particularly in hard-to-understand areas
  • corresponding changes to the documentation where required
  • changes tested to the best of my ability
  • no new errors or non-functional code

dbarkowsky and others added 24 commits June 17, 2026 15:48
- 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>
…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
alex-struk merged commit 2ed9cec into main Jun 29, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants