fix: require completed photo review before pdf render

This commit is contained in:
2026-03-28 01:43:34 -05:00
parent a88d960ec9
commit b1722a04fa
4 changed files with 27 additions and 1 deletions

View File

@@ -100,12 +100,14 @@ Current behavior:
- does not require recipient email(s) for the analysis-only run
- asks for recipient email(s) only when PDF rendering is explicitly requested
- does not render/send the PDF from a preliminary helper payload with `decision: pending`
- does not render/send the PDF when `photoReview.status` is not `completed`
- only renders the fixed-template PDF after a decision-grade verdict and fair-value range are actually present
Expected agent behavior:
- if the user asked for the full assessment, continue beyond the preliminary helper output
- fill the remaining gaps with listing facts, comp work, condition interpretation, and valuation logic
- require completed subject-unit photo review before treating the report as decision-grade enough for PDF delivery
- only stop early when there is a real blocker, not merely because the helper stopped at a checkpoint
Important limitation:

View File

@@ -120,12 +120,14 @@ scripts/property-assessor render-report --input "<report-payload-json>" --output
- only stop and ask for recipient email(s) when the user is explicitly rendering or sending the PDF
- render the PDF only after recipient email(s) are known
- do **not** render or send a PDF from the helper's preliminary payload while verdict is still `pending` or fair value is not established
- do **not** render or send a decision-grade PDF while `photoReview.status` is anything other than `completed`
- if comps, valuation, or decision-grade condition interpretation are still incomplete, return the preliminary payload and say that the PDF/send step must wait
Agent follow-through rule:
- When the user asked for a full property assessment or asked for the PDF/email result, do not stop at the helper output.
- After `assess` returns a preliminary payload, continue with the remaining manual/model-driven steps needed to reach a decision-grade report.
- Only after the verdict and fair-value range are established should you render/send the PDF.
- A verdict and fair-value range are still not enough by themselves; the subject-unit photo review must also be completed before the PDF/send step.
- If the analysis still cannot be completed, explain the first real blocker, not just that the helper was preliminary.
- If the user sends `update?`, `and?`, or similar mid-run, answer with status and keep the original assessment going. Do not treat that message as a reset or a cue to stop at the last helper checkpoint.
- In WhatsApp or similar messaging runs, do **not** start a background `assess` helper and then wait on repeated zero-output polls. That counts as a failed path; abandon it and continue with native search/fetch/browser work.

View File

@@ -28,8 +28,10 @@ export interface ReportPayload {
export function isDecisionGradeReportPayload(payload: ReportPayload): boolean {
const decision = String(payload.verdict?.decision || "").trim().toLowerCase();
const fairValueRange = String(payload.verdict?.fairValueRange || "").trim().toLowerCase();
const photoReviewStatus = String(payload.photoReview?.status || "").trim().toLowerCase();
if (!decision || decision === "pending") return false;
if (!fairValueRange || fairValueRange === "not established") return false;
if (photoReviewStatus !== "completed") return false;
return true;
}
@@ -79,7 +81,7 @@ export function validateReportPayload(payload: ReportPayload): string[] {
}
if (!isDecisionGradeReportPayload(payload)) {
throw new ReportValidationError(
"The report payload is still preliminary. Stop and complete the decision-grade analysis before generating or sending the property assessment PDF."
"The report payload is still preliminary. Stop and complete the decision-grade analysis, including subject-unit photo review, before generating or sending the property assessment PDF."
);
}
return recipients;

View File

@@ -87,3 +87,23 @@ test("renderReportPdf rejects a preliminary report with pending verdict", async
/decision-grade|preliminary|pending/i
);
});
test("renderReportPdf rejects a report when subject-unit photo review is not completed", async () => {
const outputPath = path.join(os.tmpdir(), `property-assessor-missing-photos-${Date.now()}.pdf`);
await assert.rejects(
() =>
renderReportPdf(
{
...samplePayload,
photoReview: {
status: "not completed",
source: "accessible listing-photo source not reliably exposed for unit 235",
attempts: ["Zillow and HAR photo review did not complete."],
summary: "Condition review is incomplete."
}
},
outputPath
),
/photo review|decision-grade|incomplete/i
);
});