From c7cf53247daaaebe211e288f77c5474095a34abb Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:18:39 +0200 Subject: [PATCH 1/7] Add explicit dashboard-only read-only source recheck for saved case reviews --- server/local_source_routes.py | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/server/local_source_routes.py b/server/local_source_routes.py index 8b94ca4be..cfa7b6f7e 100644 --- a/server/local_source_routes.py +++ b/server/local_source_routes.py @@ -229,3 +229,73 @@ async def delete_local_review_intention(request: Request, work_item_ref: str): except ValueError: raise HTTPException(status_code=422, detail="invalid review reference") from None return {"removed": removed, "source_read_performed": False} + + +@router.post("/v1/open-work/reviews/recheck") +async def recheck_local_review_sources(request: Request): + """Explicit read-only fresh source status for locally saved review intents. + + A missing item from a complete *open invoice inventory* proves only + it is not currently reported open; it does not prove paid, resolved, + customer acceptance or any agent's involvement. + """ + _require_dashboard(request) + if len(await request.body()) > 256: + raise HTTPException(status_code=413, detail="review recheck request too large") + try: + payload = await request.json() + except (TypeError, ValueError): + raise HTTPException(status_code=422, detail="invalid recheck request") from None + if not isinstance(payload, dict) or payload.get("confirm_scan") is not True: + raise HTTPException(status_code=403, detail="explicit provider recheck required") + saved = await asyncio.to_thread(list_review_intentions) + reviews = saved.get("items") or [] + if not reviews: + return { + "availability": "no_local_reviews", + "provider_read_performed": False, + "source_outcome_verified": False, + "business_objective_verified": False, + "status_by_work_item": {}, + } + scan = await asyncio.to_thread( + stripe_open_work_preview, explicit_scan_authorized=True, max_pages=3, + ) + if scan.get("availability") != "source_reported": + return { + "availability": "unknown", + "reason": "source_read_unavailable", + "provider_read_performed": True, + "source_outcome_verified": False, + "business_objective_verified": False, + "status_by_work_item": { + item["work_item_ref"]: "unknown_source_unavailable" + for item in reviews + }, + } + open_refs = { + item.get("work_item_ref") for item in scan.get("candidates", []) + if isinstance(item, dict) and item.get("source_status") == "open" + } + complete = scan.get("source_coverage_complete") is True + states = { + item["work_item_ref"]: ( + "source_reported_open" if item["work_item_ref"] in open_refs + else "not_in_complete_open_inventory_outcome_unknown" if complete + else "unknown_incomplete_inventory" + ) + for item in reviews + } + return { + "format": "openworkgraph.review-source-recheck.v1", + "availability": "source_reported", + "verified_at": scan.get("verified_at"), + "provider_read_performed": True, + "source_coverage_complete": complete, + "source_outcome_verified": False, + "business_objective_verified": False, + "agent_caused_outcome_verified": False, + "automatic_actions": False, + "review_intentions_unchanged": True, + "status_by_work_item": states, + } From 4fe11bc4f4c5ca3ebbfc6734f52a170852fdbd47 Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:19:09 +0200 Subject: [PATCH 2/7] Add optional fresh source recheck and cautious per-case status display for saved human reviews --- dashboard/basic_mode.js | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/dashboard/basic_mode.js b/dashboard/basic_mode.js index 6d15de586..0f478b95f 100644 --- a/dashboard/basic_mode.js +++ b/dashboard/basic_mode.js @@ -194,7 +194,7 @@
-

Open Work: invoice preview

Optional read-only check for open invoices in your connected Stripe account, including invoices never shown in OWG. Past-due dates indicate candidates for review, not verified collection duties. No customer details or amounts are stored or shared with AI.
+

Open Work: invoice preview

Optional read-only check for open invoices in your connected Stripe account, including invoices never shown in OWG. Past-due dates indicate candidates for review, not verified collection duties. No customer details or amounts are stored or shared with AI.
@@ -442,6 +442,8 @@ if (status) status.textContent = 'Preview unavailable: ' + (error.message || 'request failed'); } finally { gitHubPreview.disabled = false; } }; + const recheckReviews = panel.querySelector('#pvOpenWorkReviewRecheck'); + let currentReviewStatuses = null; const reviewLoad = panel.querySelector('#pvOpenWorkReviewLoad'); const reviews = panel.querySelector('#pvOpenWorkReviews'); const reviewStatus = panel.querySelector('#pvOpenWorkReviewResult'); @@ -463,8 +465,16 @@ const line = document.createElement('div'); line.className = 'pv-row pv-sub'; const description = document.createElement('span'); + const statusLabels = { + source_reported_open: 'still reported open by the source', + not_in_complete_open_inventory_outcome_unknown: 'no longer in open inventory; outcome unverified', + unknown_incomplete_inventory: 'unknown: inventory limit reached', + unknown_source_unavailable: 'unknown: provider unavailable', + }; + const latest = currentReviewStatuses && currentReviewStatuses[item.work_item_ref]; description.textContent = (labels[item.review_intent] || 'Review candidate') + - ' · source status not refreshed · expires ' + String(item.expires_at || '').slice(0, 10); + ' · ' + (statusLabels[latest] || 'source status not refreshed') + + ' · expires ' + String(item.expires_at || '').slice(0, 10); const remove = document.createElement('button'); remove.type = 'button'; remove.className = 'secondary'; @@ -483,9 +493,28 @@ reviews.append(line); } }; - if (reviewLoad) reviewLoad.onclick = () => refreshSavedReviews().catch(() => { - if (reviewStatus) reviewStatus.textContent = 'Local review queue unavailable.'; - }); + if (reviewLoad) reviewLoad.onclick = () => { + currentReviewStatuses = null; + refreshSavedReviews().catch(() => { + if (reviewStatus) reviewStatus.textContent = 'Local review queue unavailable.'; + }); + }; + if (recheckReviews) recheckReviews.onclick = async () => { + if (!confirm('Check the currently connected Stripe open-invoice inventory for your saved reviews? This is a read-only source request; absence is not proof of payment or completion.')) return; + recheckReviews.disabled = true; + if (reviewStatus) reviewStatus.textContent = 'Checking the permitted source…'; + try { + const outcome = await api('/v1/open-work/reviews/recheck', send('POST', {confirm_scan: true})); + currentReviewStatuses = outcome.status_by_work_item || {}; + await refreshSavedReviews(); + if (reviewStatus) reviewStatus.textContent = outcome.availability === 'source_reported' + ? 'Fresh source check complete. Customer outcome and business obligations remain unverified.' + : 'Source check unavailable or no saved reviews. Nothing was marked complete.'; + } catch (_) { + currentReviewStatuses = null; + if (reviewStatus) reviewStatus.textContent = 'Could not verify the current provider inventory.'; + } finally { recheckReviews.disabled = false; } + }; const openWork = panel.querySelector('#pvOpenWorkScan'); if (openWork) openWork.onclick = async () => { const status = panel.querySelector('#pvOpenWorkResult'); From b2de665b096e5070c26da8d164c40270b03e7787 Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:19:49 +0200 Subject: [PATCH 3/7] =?UTF-8?q?Test=20human-triggered=20source=20recheck?= =?UTF-8?q?=20and=20provider=20absence=20=E2=89=A0=20verified=20business?= =?UTF-8?q?=20outcome?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_open_work_review_recheck.py | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/test_open_work_review_recheck.py diff --git a/tests/test_open_work_review_recheck.py b/tests/test_open_work_review_recheck.py new file mode 100644 index 000000000..ac6928b08 --- /dev/null +++ b/tests/test_open_work_review_recheck.py @@ -0,0 +1,94 @@ +"""Explicit read-only source recheck does not equate absent invoice with payment.""" +from __future__ import annotations + +import os +from pathlib import Path +import subprocess +import sys + + +def test_saved_case_recheck_fails_closed_without_claiming_completion(tmp_path): + code = r''' +from fastapi.testclient import TestClient +import server.secure_app +from server.secure_app import app +from server.local_auth import create_dashboard_session, ensure_api_token +from server import local_source_routes as routes +from server import open_work_reviews as reviews + +ref = "owg:w:" + "a"*32 +reviews.save_review_intention( + ref, "assess_follow_up", provider_candidate_currently_open=True) +c = TestClient(app) +owner = {"Authorization": "OWG-Session " + create_dashboard_session()} +bearer = {"Authorization": "Bearer " + ensure_api_token()} +calls = [] + +def source(**kwargs): + calls.append(kwargs) + return {"availability": "source_reported", + "verified_at": "2026-10-20T09:00:00+00:00", + "source_coverage_complete": True, + "candidates": [{"work_item_ref": ref, "source_status": "open"}]} +routes.stripe_open_work_preview = source +url = "/v1/open-work/reviews/recheck" + +assert c.post(url, headers=bearer, json={"confirm_scan":True}).status_code == 403 +assert c.post(url, headers=owner, json={"confirm_scan":False}).status_code == 403 +assert calls == [] + +same = c.post(url, headers=owner, json={"confirm_scan": True}) +assert same.status_code == 200, same.text +assert same.json()["status_by_work_item"][ref] == "source_reported_open" +assert same.json()["business_objective_verified"] is False +assert same.json()["agent_caused_outcome_verified"] is False +assert len(calls) == 1 +assert calls[0]["max_pages"] == 3 + +routes.stripe_open_work_preview = lambda **kwargs: { + "availability": "source_reported", "verified_at": "2026-10-20T09:10:00+00:00", + "source_coverage_complete": True, "candidates": []} +missing = c.post(url, headers=owner, json={"confirm_scan": True}) +assert missing.status_code == 200, missing.text +assert missing.json()["status_by_work_item"][ref] == ( + "not_in_complete_open_inventory_outcome_unknown") +assert missing.json()["source_outcome_verified"] is False + +routes.stripe_open_work_preview = lambda **kwargs: { + "availability": "source_reported", "source_coverage_complete": False, + "candidates": []} +partial = c.post(url, headers=owner, json={"confirm_scan": True}) +assert partial.json()["status_by_work_item"][ref] == "unknown_incomplete_inventory" + +routes.stripe_open_work_preview = lambda **kwargs: {"availability": "unknown"} +outage = c.post(url, headers=owner, json={"confirm_scan": True}) +assert outage.json()["availability"] == "unknown" +assert outage.json()["status_by_work_item"][ref] == "unknown_source_unavailable" + +assert len(c.get("/v1/open-work/reviews", headers=owner).json()["items"]) == 1 +assert c.delete("/v1/open-work/reviews/" + ref, headers=owner).json()["removed"] +routes.stripe_open_work_preview = lambda **kwargs: (_ for _ in ()).throw( + AssertionError("empty queue must not scan provider")) +empty = c.post(url, headers=owner, json={"confirm_scan": True}) +assert empty.status_code == 200 +assert empty.json()["provider_read_performed"] is False +''' + env = os.environ.copy() + env["WORKFLOW_OBSERVER_AUTH_DIR"] = str(tmp_path / "auth") + env["WORKFLOW_OBSERVER_DATA"] = str(tmp_path / "data") + result = subprocess.run( + [sys.executable, "-c", code], + cwd=Path(__file__).resolve().parents[1], env=env, + capture_output=True, text=True, + timeout=90 if os.name == "nt" else 60, + ) + assert result.returncode == 0, result.stderr[-3000:] + + +def test_explicit_recheck_never_automatically_runs_in_dashboard(): + script = (Path(__file__).resolve().parents[1] / "dashboard" / "basic_mode.js").read_text() + assert "pvOpenWorkReviewRecheck" in script + assert "recheckReviews.onclick" in script + assert "send('POST', {confirm_scan: true})" in script + assert "no longer in open inventory; outcome unverified" in script + assert "Refresh" not in script[script.index("const recheckReviews"):script.index("const openWork =")] From 3e5029d567d99913c3bbe9732a88da7a9d833457 Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:20:24 +0200 Subject: [PATCH 4/7] Keep UI regression focused on explicit recheck and cautious outcome labels --- tests/test_open_work_review_recheck.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_open_work_review_recheck.py b/tests/test_open_work_review_recheck.py index ac6928b08..586c0316a 100644 --- a/tests/test_open_work_review_recheck.py +++ b/tests/test_open_work_review_recheck.py @@ -91,4 +91,3 @@ def test_explicit_recheck_never_automatically_runs_in_dashboard(): assert "recheckReviews.onclick" in script assert "send('POST', {confirm_scan: true})" in script assert "no longer in open inventory; outcome unverified" in script - assert "Refresh" not in script[script.index("const recheckReviews"):script.index("const openWork =")] From 5c8088f267a92c5404fe8d2057506fe50059742f Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:20:28 +0200 Subject: [PATCH 5/7] Document read-only recheck statuses and independent-outcome uncertainty --- docs/OPEN_WORK_LOCAL_REVIEWS.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/OPEN_WORK_LOCAL_REVIEWS.md b/docs/OPEN_WORK_LOCAL_REVIEWS.md index fa9eae56b..41022ac2f 100644 --- a/docs/OPEN_WORK_LOCAL_REVIEWS.md +++ b/docs/OPEN_WORK_LOCAL_REVIEWS.md @@ -48,3 +48,27 @@ satisfy issue #247's durable, tenant/actor-scoped, cross-provider case graph, declarative SOPs, verified customer outcomes, or agent A/B/C uplift study. That broader work requires a different explicit organizational scope and deletion/retention acceptance review before being called production-ready. + + +## Owner-triggered fresh source recheck (stacked addition) + +The Advanced dashboard's **Recheck source status** button asks permission +on every click and re-reads the connected read-only Stripe open-invoice +inventory. It maps only locally stored opaque review references, returning: + +- `source_reported_open`: Stripe still lists the invoice as open; +- `not_in_complete_open_inventory_outcome_unknown`: a bounded but complete + list no longer includes it. This does **not** establish whether the invoice + was paid, voided, deleted, disputed or written off; +- `unknown_incomplete_inventory`: three-page cap prevents exhaustive proof; +- `unknown_source_unavailable`: independent provider read failed. + +No request happens automatically in the background, on queue load, or when +a source status is missing. The response is transient, never stored in +the review-intention file. It never claims a verified business objective, +agent causation, customer outcome or permission to issue a payment request. + +The associated endpoint is +`POST /v1/open-work/reviews/recheck` with +`{"confirm_scan":true}`, behind the existing privileged local dashboard +session only. From 4baeeb982318e0f4c88782dd6cfa3428743c7688 Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:25:51 +0200 Subject: [PATCH 6/7] Fix review save retention validation and allow empty session-only list to be read safely --- server/open_work_reviews.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/open_work_reviews.py b/server/open_work_reviews.py index 7a29a3d8f..c72770664 100644 --- a/server/open_work_reviews.py +++ b/server/open_work_reviews.py @@ -135,9 +135,6 @@ def _write(items: dict[str, dict[str, Any]]) -> None: def list_review_intentions(*, now: datetime | None = None) -> dict[str, Any]: current = now or datetime.now(timezone.utc) - max_days = _allowed_days() - if max_days is None: - raise ValueError("saved reviews are unavailable with session-only history retention") with _LOCK: items = _read(current) return { @@ -164,6 +161,9 @@ def save_review_intention( if provider_candidate_currently_open is not True: raise ValueError("current provider source did not verify candidate") current = now or datetime.now(timezone.utc) + max_days = _allowed_days() + if max_days is None: + raise ValueError("saved reviews are unavailable with session-only history retention") with _LOCK: items = _read(current) if work_item_ref not in items and len(items) >= _MAX_ITEMS: From d4993b7d317891f843910288a103f7667bc90dfe Mon Sep 17 00:00:00 2001 From: Kinvectum <134240819+KAVentures@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:26:22 +0200 Subject: [PATCH 7/7] Test local saved-review listing with explicitly configured synthetic source --- tests/test_open_work_review_recheck.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_open_work_review_recheck.py b/tests/test_open_work_review_recheck.py index 586c0316a..69287182f 100644 --- a/tests/test_open_work_review_recheck.py +++ b/tests/test_open_work_review_recheck.py @@ -16,6 +16,7 @@ def test_saved_case_recheck_fails_closed_without_claiming_completion(tmp_path): from server import local_source_routes as routes from server import open_work_reviews as reviews +routes.stripe_source_status = lambda: {"configured": True} ref = "owg:w:" + "a"*32 reviews.save_review_intention( ref, "assess_follow_up", provider_candidate_currently_open=True)