fix(dn): show an open site question as the headline in Needs attention

The inbox list took its reason from documentProgress, which listed the
model's old identity doubts ("Is MEGCPO9376 correct?", "No matching PO
found") ahead of the question an agent asked the site. While a site
question is open it is now the only reason, labelled 'Waiting for site'
with the action 'Answer the site question'; once answered the normal
reasons return.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DEls 2026-10-09 11:54:54 +02:00
parent 9a6aed50a4
commit 3cd4101ca6
2 changed files with 16 additions and 0 deletions

View file

@ -42,3 +42,15 @@ it('distinguishes a missing printed PO number from a printed number with no matc
expect(documentProgress({...base,po_number_raw:'MEGCPO9381'}).shortReason).toBe('No matching PO found');
expect(documentProgress({...linked,checks:[{id:'site_identity',passed:false,reason:long}]}).shortReason).toBe('PO link needs confirmation');
});
it('shows an open site question as the headline instead of older model doubts',()=>{
const p=documentProgress({...linked,purchase_order:'',checks:[{id:'po_resolved',passed:false,reason:'Is MEGCPO9376 the correct PO?'},{id:'page_grouping_confirmed',passed:false},{id:'site_decision',passed:false,reason:'Which PO covers these 10 junctions?',detail:{question:'Which PO covers these 10 junctions?'}}]});
expect(p.reasons).toEqual(['Which PO covers these 10 junctions?']);
expect(p.shortReason).toBe('Question for site');
expect(p.label).toBe('Waiting for site');
expect(p.action).toBe('Answer the site question');
});
it('goes back to the normal reasons once the site question is answered',()=>{
const p=documentProgress({...linked,purchase_order:'',checks:[{id:'po_resolved',passed:false,reason:'No PO'},{id:'site_decision',passed:true,reason:'Answered: PO 9430',detail:{question:'Which PO?',answer:'PO 9430'}}]});
expect(p.reasons).toEqual(['No PO']);
expect(p.shortReason).not.toBe('Question for site');
});

View file

@ -1,6 +1,7 @@
import {allocationNeedsHelp} from './delivery-ready';
import type {PreviewAllocation} from './ai-preview';
import { displayCandidateStage } from './stages';
import { openSiteDecision } from './site-decision-model';
export type DocumentStep='identify'|'reconcile'|'ready_to_post'|'posted'|'dismissed';
export interface ProgressCheck {label:string;status:'passed'|'attention'|'pending'}
export interface DocumentProgress {step:DocumentStep;label:string;reasons:string[];action:string;readyLines:number;reviewLines:number;history:ProgressCheck[];groupingPending:boolean;warnings:string[];shortReason?:string}
@ -53,6 +54,9 @@ export function documentProgress(note:ProgressEvidence):DocumentProgress {
{label:'Document identified',status:closed?'passed':groupingPending?'pending':typeKnown?'passed':'attention'},
{label:'Identity & PO confirmed',status:closed||identified?'passed':groupingPending?'pending':typeKnown?'attention':'pending'},
{label:'Delivery reconciled',status:closed?'passed':!identified?'pending':step==='ready_to_post'&&!reviewLines?'passed':stage==='matching'?'pending':'attention'}];
// An open site question is what the site has to act on; older model doubts would only bury it.
const siteQuestion=closed?null:openSiteDecision(checks);
if(siteQuestion)return {step,label:'Waiting for site',reasons:[siteQuestion.question],readyLines,reviewLines,history,shortReason:'Question for site',groupingPending:groupingPending&&!closed,warnings,action:'Answer the site question'};
return {step,label:groupingPending&&!closed?'Check grouping':DOCUMENT_STEP_LABELS[step],reasons:[...new Set(reasons)],readyLines,reviewLines,history,shortReason,groupingPending:groupingPending&&!closed,warnings,
action:groupingPending&&!closed?'Confirm grouping in View batch':step==='identify'?'Confirm document, supplier and PO':step==='reconcile'?'Review lines or retry processing':step==='ready_to_post'?'Confirm and post clear lines':closed?'View record':'Open document'};
}