fix(documents): keep an incomplete extraction on the document

A long document read in parts can end with a part cut at the provider's
output limit, a part never read, or more facts than one review takes.
That was told once, as a notice when the run finished; a review opened
later looked complete.

InboundDocument.extractionIncomplete (migration 0483) is written with
the facts by both stagings, the extract route or run and lab
auto-staging. The document detail publishes it and the review shows the
same note whenever it is opened. The disaster-recovery backup carries
it; an older file restores it as false.

Refs #1257
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 01:01:13 +02:00
1 parent 5cfaf4869d
commit 958d230b9f
15 files changed
+233 -44

No files matched your search

@@ -97,6 +97,7 @@ function doc(
summary: null,
summaryGeneratedAt: null,
summaryState: "NONE",
extractionIncomplete: false,
...overrides,
};
}
@@ -114,6 +115,19 @@ describe("<DocumentFactsSection>", () => {
expect(html).toContain("Review extracted value");
});
it("says the review may not be the whole document when the extraction was cut", () => {
const cut = render(
<DocumentFactsSection
doc={doc({ extractionIncomplete: true })}
{...baseProps}
/>,
);
expect(cut).toContain('data-slot="document-facts-incomplete"');
expect(cut).toContain("could not be read in full");
const whole = render(<DocumentFactsSection doc={doc()} {...baseProps} />);
expect(whole).not.toContain('data-slot="document-facts-incomplete"');
});
it("offers the stored-text extract for a read lab document with nothing staged", () => {
const html = render(
<DocumentFactsSection
@@ -493,6 +493,37 @@ function announceExtract(
}
}
/** The review panel's title and how to use it. */
function ReviewHeading() {
const { t } = useTranslations();
return (
<div className="space-y-1">
<p className="text-sm font-medium">{t("documents.review.title")}</p>
<p className="text-muted-foreground text-xs">
{t("documents.review.hint")}
</p>
</div>
);
}
/**
* The staged facts may leave part of the document out. Kept on the document
* by the extraction, so a review opened later says what the notice at the
* end of the run said.
*/
function ExtractionIncompleteNote() {
const { t } = useTranslations();
return (
<p
role="note"
data-slot="document-facts-incomplete"
className="text-foreground text-sm"
>
{t("documents.review.extractIncomplete")}
</p>
);
}
export function DocumentFactsSection({
doc,
canManage,
@@ -598,6 +629,9 @@ export function DocumentFactsSection({
return (
<div className="space-y-3" data-slot="document-facts-section">
{pending.length > 0 && doc.extractionIncomplete ? (
<ExtractionIncompleteNote />
) : null}
{pending.length > 0 ? (
<>
{!open ? (
@@ -617,14 +651,7 @@ export function DocumentFactsSection({
data-slot="document-facts-review"
className="border-border bg-muted/30 space-y-3 rounded-lg border p-3 md:p-4"
>
<div className="space-y-1">
<p className="text-sm font-medium">
{t("documents.review.title")}
</p>
<p className="text-muted-foreground text-xs">
{t("documents.review.hint")}
</p>
</div>
<ReviewHeading />
<ul className="space-y-2">
{pending.map((fact) => (
<FactRow