Extraction layer: start and poll an extraction - #648
Merged
marcvergees merged 6 commits intoAug 5, 2026
Merged
Conversation
…500 on non-JSON body
…ut under input API
marcvergees
requested changes
Aug 4, 2026
marcvergees
left a comment
Member
There was a problem hiding this comment.
You should have a look at what happens with the linter before merging. There are some linter errors. Lmk if you need help with it.
Collaborator
Author
Very weird, ruff check passes the lint test locally. I will look into what went wrong. |
Collaborator
Author
|
High chances that it's related to ruff version difference. |
Collaborator
Author
|
There was two issues:
|
marcvergees
merged commit Aug 5, 2026
925e7e5
into
fireform-core:development-approach-c
2 checks passed
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.
Extraction layer: start and poll an extraction (#629)
Why
The extraction layer needs a way to kick off an extraction and check on it. This is the first slice of that layer. It gives the frontend a real entry point and a poll point to build against now, before the model side of extraction is ready. The work that turns a narrative into a full contract is a separate, larger piece (#630), so this change keeps the worker as a stub and focuses on the request flow, the states, and the errors.
What this adds
Two endpoints:
POST /api/v1/extract/{input_id}starts an extraction from an input that was already submitted. It checks the input exists and is ready, makes sure there is not already an extraction for it, and that the model service is reachable. On success it creates the extraction row, queues a job, and returns 202 with the ids and a poll url.GET /api/v1/extract/{extract_id}returns the current state. While the job runs it returns the processing shape with a retry hint. Once an extraction is done it returns the completed shape with the full contract, read from the linked incident row rather than from the extraction.The queued job runs a stub worker for now. It marks the job in flight and leaves the extraction in processing. The real worker that splits the narrative, calls the model, validates, and writes the contract and the draft incident is #630. So while testing this PR an extraction will sit on processing, which is the expected result here.
Errors
Both endpoints return the codes the contract lists:
INPUT_NOT_FOUNDINPUT_NOT_READYEXTRACTION_EXISTSLLM_UNAVAILABLEEXTRACT_NOT_FOUNDOne extra fix
While testing I found that sending a body with the wrong content type returned a 500 instead of a clean 422. The cause was in the shared validation error handler. It put the raw request body, which comes through as bytes, into the error response and then could not turn that into JSON. This affected any endpoint that takes a JSON body, not only the new ones. The handler now converts any value it cannot serialize into a safe string, so these cases return 422 as they should. There is a test for it.
Scope and what is next
This is the queue and poll slice only. The real extraction worker is #630. The manual correction endpoint and the readiness and validate endpoints are #631.
A small note for the reviewer that carries into #630 and #631: the completed read validates the stored contract against the incident contract model, so the worker must write a valid contract. Two states that only those later PRs produce, a completed extraction with no incident row and a
needs_reviewstatus, are not handled by the read yet because nothing in this PR can produce them.Closes: #629