feat(webui): notifications and human-attention routing (#648) #905

Merged
sysadmin merged 5 commits from feat/issue-648-notifications-console into master 2026-07-25 17:40:04 -05:00
Owner

Closes #648

Summary

Implements Phase 3 Web Console Notifications & Human-Attention Routing surface (/notifications, /api/v1/notifications).

  • Categorizes events into three attention classes: human-required (critical boundaries/hard stops/auth errors), operator (blockers/stale leases/collisions), and routine (background workflow transitions).
  • Provides an Attention Inbox UI filtering routine noise by default.
  • Includes unit tests (tests/test_webui_notifications.py) and operator documentation (docs/webui-notifications.md).
Closes #648 ## Summary Implements Phase 3 Web Console Notifications & Human-Attention Routing surface (`/notifications`, `/api/v1/notifications`). - Categorizes events into three attention classes: `human-required` (critical boundaries/hard stops/auth errors), `operator` (blockers/stale leases/collisions), and `routine` (background workflow transitions). - Provides an Attention Inbox UI filtering routine noise by default. - Includes unit tests (`tests/test_webui_notifications.py`) and operator documentation (`docs/webui-notifications.md`).
jcwalker3 added 1 commit 2026-07-25 15:42:43 -05:00
jcwalker3 added 1 commit 2026-07-25 17:11:10 -05:00
Keep notifications (#648) routes and nav alongside master requests (#643)
and other base updates.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: prgs-reviewer-78651-cbbd1dba
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/conflict-fix-pr-905
phase: claimed
candidate_head: bb8c3a537b
target_branch: master
target_branch_sha: 26f54851d1
last_activity: 2026-07-25T22:22:17Z
expires_at: 2026-07-25T22:32:17Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-reviewer session_id: prgs-reviewer-78651-cbbd1dba worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/conflict-fix-pr-905 phase: claimed candidate_head: bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9 target_branch: master target_branch_sha: 26f54851d1d20eff92c339e778125f31c09fa95f last_activity: 2026-07-25T22:22:17Z expires_at: 2026-07-25T22:32:17Z blocker: none
sysadmin requested changes 2026-07-25 17:23:28 -05:00
Dismissed
sysadmin left a comment
Owner

Review verdict: REQUEST_CHANGES at head bb8c3a537b.

Three code defects, one of which defeats the central acceptance criterion of #648. All three were re-verified by reading the code at the live head immediately before this verdict was recorded.

B1 — title text is matched against critical-boundary keywords, so benign work escalates to human-required

webui/notifications.py:162-173. classify_attention_event decides the attention class from explicit boolean flags and from three substring tests against summary:

or "hard stop" in summary.lower()
or "unauthorized" in summary.lower()
or "irrecoverable" in summary.lower()

Three call sites build that summary string out of the PR or issue title, and pass no escalation flags at all — they are the routine-transition paths:

  • webui/notifications.py:314-318f"PR #{pr.number} '{pr.title}' has had no activity for over 14 days."
  • webui/notifications.py:338-341f"PR #{pr.number} '{pr.title}' is in routine state {', '.join(pr.badges)}."
  • webui/notifications.py:385-388f"Issue #{issue.number} '{issue.title}' in state {', '.join(issue.badges)}."

So any PR or issue whose title happens to contain one of those three substrings is classified ATTENTION_HUMAN_REQUIRED with requires_human=True, purely because of how it was named.

This is not hypothetical in this repository. Work items here are routinely titled after the very mechanisms these keywords name — this codebase contains gitea_issue_irrecoverable_provenance_authorization and gitea_record_irrecoverable_decision_lock_provenance, so an issue titled along the lines of "record irrecoverable decision lock provenance" is ordinary tracked work. Under this code, its routine state transition renders in the Attention Inbox as HUMAN REQUIRED.

That inverts the stated purpose of the surface. The PR body describes an "Attention Inbox UI filtering routine noise by default"; this path manufactures the exact noise the issue asks to suppress, and it does so most often for the critical-boundary work whose real alerts most need to stay legible.

Suggested direction: classify from the structured flags and category only. If a text signal is genuinely wanted, match it against the machine-generated status/detail field (probe.status, probe.detail, collision.message) rather than any human-authored title, and keep the two out of the same string.

B2 — two notification ids are loop-invariant, so a published identifier is not unique

webui/notifications.py:237-246 iterates for probe_err in getattr(health_snap, "probe_errors", ()) and appends an item with id=f"notif-sys-err-{project.id}". The id depends only on the project, never on the loop variable. N probe errors yield N items carrying one identical id.

webui/notifications.py:433-443 has the same shape: for collision in lease_snap.duplicate_prs emits id=f"notif-collision-{collision.issue_number or 0}". Every collision lacking an issue_number collapses onto notif-collision-0, and two collisions of different kind on the same issue collide with each other.

Blast radius, stated precisely: id is exposed on the public payload of /api/v1/notifications via snapshot_to_dict, and is rendered as display text by _render_notification_row at webui/notification_views.py:31. No consumer inside this repository currently keys on it, so nothing is observably broken today. It is still a defect worth fixing before this contract is published, because id on a notification feed is the field any consumer will reasonably use for dedup, mark-as-read, or list keys — and each of those silently collapses or mis-targets rows here. Fix is small: fold the loop variable (an enumerate index, the probe error text, or collision.kind) into the id.

B3 — probe failures are reported as a fetch failure

webui/notifications.py:462:

fetch_err = queue_snap.fetch_error or lease_snap.fetch_error or getattr(health_snap, "probe_errors", None)

probe_errors describes probes that ran and reported a problem. It is not a failure to fetch. Assigning it to fetch_error makes webui/notification_views.py:90-91 render a red "Fetch Warning" banner when every fetch in fact succeeded, telling an operator their data may be incomplete when it is complete.

It also double-reports: those same probe_errors were already emitted as first-class notification items at webui/notifications.py:237-246. The operator sees the identical condition twice, once under a label that misstates what happened.

Non-blocking observations

  • Unused imports: os, Sequence, find_project.
  • as_dict redacts summary but leaves title and extra unredacted. If summary is considered sensitive enough to redact, the reasoning should be applied consistently or the asymmetry documented.
  • webui/notifications.py:225-231 probes a callable's signature by catching TypeError from the call itself, in a nested fallback. A TypeError raised from inside a correctly-called loader is indistinguishable from an arity mismatch, so a real error in the health loader is silently retried with a different arity and can surface as an unrelated failure. Prefer inspect.signature if the arity really must be discovered at runtime.

Canonical PR State

STATE: PR-open
WHO_IS_NEXT: author
NEXT_ACTION: Fix B1, B2, and B3 in webui/notifications.py, then push and request re-review.
NEXT_PROMPT:

Address the REQUEST_CHANGES verdict on PR #905 (Closes #648), prgs /
Scaled-Tech-Consulting / Gitea-Tools, reviewed at head
bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9.

B1 (webui/notifications.py:162-173) — classify_attention_event substring-matches
"hard stop" / "unauthorized" / "irrecoverable" against a summary that three call
sites build from the PR or issue title (lines 314-318, 338-341, 385-388), all of
which pass no escalation flags. Any work item whose title contains one of those
words escalates from routine to human-required on name alone, which defeats the
noise-filtering AC of #648. Classify from the structured flags and category; if a
text signal is needed, read a machine-generated status/detail field, never a
human-authored title.

B2 (webui/notifications.py:237-246 and 433-443) — notification ids are
loop-invariant: notif-sys-err-{project.id} repeats for every probe error, and
notif-collision-{collision.issue_number or 0} collapses every collision without an
issue number onto 0. id is published on /api/v1/notifications, so fold the loop
variable into it.

B3 (webui/notifications.py:462) — probe_errors is assigned to fetch_error, so
notification_views.py:90-91 renders a "Fetch Warning" when nothing failed to fetch,
and double-reports errors already emitted as items at lines 237-246. Keep the two
conditions distinct.

Also worth clearing: unused imports os, Sequence, find_project; as_dict redacts
summary but not title or extra; the TypeError-arity probing at lines 225-231 can
swallow a real TypeError raised inside the health loader.

Add a regression test per blocker. For B1 the test should assert that a routine
transition on an item whose title contains "irrecoverable" still classifies as
routine.

WHAT_HAPPENED: PR #905 was reviewed in full, first at head 4f06d30e07 and then re-verified at the current head bb8c3a537b. The read found three code defects and three lesser observations. The head advanced between those two passes, but the advance was a merge of master into the branch and carried no author change to the reviewed code: the blobs for webui/notifications.py and webui/notification_views.py are byte-identical at both heads (15753b9705 and e4b6ab91f6 respectively). Every finding and every cited line number therefore carries over unchanged. The verdict was prepared during an earlier cycle but could not reach the API because the serving runtime had started at an older master commit and the mutation gate fail-closed with blocker_kind=runtime_reconnect_required.
WHY: B1 defeats the central acceptance criterion of #648. The surface exists to separate genuine human-attention events from routine workflow noise, and this classifier promotes routine events to human-required based on words appearing in a human-authored title. In this repository, work items are commonly named after the exact mechanisms those keywords describe, so the misclassification lands on real, ordinary work rather than on a contrived edge case. B2 and B3 are narrower — an identifier-uniqueness violation on a published API field, and an operator-facing banner that misstates a healthy fetch as a failed one.
ISSUE: #648
HEAD_SHA: bb8c3a537b
REVIEW_STATUS: REQUEST_CHANGES
MERGE_READY: false
BLOCKERS: B1 title-substring escalation defeats the #648 filtering criterion; B2 loop-invariant notification ids on a published API field; B3 probe_errors misreported as fetch_error.
VALIDATION: Static re-verification of all three findings against the live head bb8c3a537b immediately before recording this verdict, by reading webui/notifications.py and webui/notification_views.py at that revision. The head move from 4f06d30e was audited by comparing blob hashes rather than assumed benign: both reviewed files are unchanged, and the difference between the two heads is confined to files brought in by the master merge. Live head SHA before this verdict: bb8c3a537b. Base master at that time: 26f54851d1. Author pushes containing code changes to the reviewed files during validation: none. The focused suite tests/test_webui_notifications.py returned 5 passed during the original review pass. No full-suite run was performed at this head in this session, and none is claimed; the three findings are static defects that a suite run would not settle either way, since the branch ships no test that exercises them.
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha bb8c3a537b. No offline, import, or helper path was used.

[THREAD STATE LEDGER]

what is true now

PR #905 remains in open state at head bb8c3a537b, targeting master at 26f54851d1. The branch reports no conflict against that base.

Server-side decision state: this REQUEST_CHANGES verdict is the first review decision recorded on PR #905; the PR carried no prior review of any kind and no prior discussion comments.
Local verdict/state: REQUEST_CHANGES, three code defects, re-verified against the live head.

what changed

The review verdict moved from a locally-held result to a recorded server-side decision. The PR head moved from 4f06d30e07 to bb8c3a537b while the verdict was held locally. That move brought master into the branch and was not an author remediation: the two reviewed files are byte-identical across it, so no finding required revision. A base-sync concern noted at the earlier head no longer applies at this one.

what is blocked

Blocker classification: code blocker

B1 — webui/notifications.py:162-173 escalates routine events to human-required when a human-authored title contains "hard stop", "unauthorized", or "irrecoverable", via the summary built at lines 314-318, 338-341, and 385-388. B2 — loop-invariant ids at lines 237-246 and 433-443 break uniqueness of a field published on /api/v1/notifications. B3 — line 462 assigns probe_errors to fetch_error, so a healthy fetch renders an operator-facing failure banner.

who/what acts next

Next actor: author
Required action: Fix B1, B2, and B3 in webui/notifications.py, add a regression test per blocker, push, and request re-review.
Do not do: Do not treat the focused-suite result of 5 passed as evidence against these findings — the branch ships no test that exercises any of the three paths, which is itself part of what needs fixing. Do not narrow B1 to a keyword-list tweak; the defect is that a human-authored title reaches the classifier at all.

Review verdict: REQUEST_CHANGES at head bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9. Three code defects, one of which defeats the central acceptance criterion of #648. All three were re-verified by reading the code at the live head immediately before this verdict was recorded. ## B1 — title text is matched against critical-boundary keywords, so benign work escalates to human-required `webui/notifications.py:162-173`. `classify_attention_event` decides the attention class from explicit boolean flags **and** from three substring tests against `summary`: ```python or "hard stop" in summary.lower() or "unauthorized" in summary.lower() or "irrecoverable" in summary.lower() ``` Three call sites build that `summary` string out of the PR or issue **title**, and pass no escalation flags at all — they are the routine-transition paths: - `webui/notifications.py:314-318` — `f"PR #{pr.number} '{pr.title}' has had no activity for over 14 days."` - `webui/notifications.py:338-341` — `f"PR #{pr.number} '{pr.title}' is in routine state {', '.join(pr.badges)}."` - `webui/notifications.py:385-388` — `f"Issue #{issue.number} '{issue.title}' in state {', '.join(issue.badges)}."` So any PR or issue whose **title** happens to contain one of those three substrings is classified `ATTENTION_HUMAN_REQUIRED` with `requires_human=True`, purely because of how it was named. This is not hypothetical in this repository. Work items here are routinely titled after the very mechanisms these keywords name — this codebase contains `gitea_issue_irrecoverable_provenance_authorization` and `gitea_record_irrecoverable_decision_lock_provenance`, so an issue titled along the lines of "record irrecoverable decision lock provenance" is ordinary tracked work. Under this code, its routine state transition renders in the Attention Inbox as HUMAN REQUIRED. That inverts the stated purpose of the surface. The PR body describes an "Attention Inbox UI filtering routine noise by default"; this path manufactures the exact noise the issue asks to suppress, and it does so most often for the critical-boundary work whose real alerts most need to stay legible. Suggested direction: classify from the structured flags and category only. If a text signal is genuinely wanted, match it against the machine-generated status/detail field (`probe.status`, `probe.detail`, `collision.message`) rather than any human-authored title, and keep the two out of the same string. ## B2 — two notification ids are loop-invariant, so a published identifier is not unique `webui/notifications.py:237-246` iterates `for probe_err in getattr(health_snap, "probe_errors", ())` and appends an item with `id=f"notif-sys-err-{project.id}"`. The id depends only on the project, never on the loop variable. N probe errors yield N items carrying one identical id. `webui/notifications.py:433-443` has the same shape: `for collision in lease_snap.duplicate_prs` emits `id=f"notif-collision-{collision.issue_number or 0}"`. Every collision lacking an `issue_number` collapses onto `notif-collision-0`, and two collisions of different `kind` on the same issue collide with each other. Blast radius, stated precisely: `id` is exposed on the public payload of `/api/v1/notifications` via `snapshot_to_dict`, and is rendered as display text by `_render_notification_row` at `webui/notification_views.py:31`. No consumer inside this repository currently keys on it, so nothing is observably broken today. It is still a defect worth fixing before this contract is published, because `id` on a notification feed is the field any consumer will reasonably use for dedup, mark-as-read, or list keys — and each of those silently collapses or mis-targets rows here. Fix is small: fold the loop variable (an enumerate index, the probe error text, or `collision.kind`) into the id. ## B3 — probe failures are reported as a fetch failure `webui/notifications.py:462`: ```python fetch_err = queue_snap.fetch_error or lease_snap.fetch_error or getattr(health_snap, "probe_errors", None) ``` `probe_errors` describes probes that ran and reported a problem. It is not a failure to fetch. Assigning it to `fetch_error` makes `webui/notification_views.py:90-91` render a red "Fetch Warning" banner when every fetch in fact succeeded, telling an operator their data may be incomplete when it is complete. It also double-reports: those same `probe_errors` were already emitted as first-class notification items at `webui/notifications.py:237-246`. The operator sees the identical condition twice, once under a label that misstates what happened. ## Non-blocking observations - Unused imports: `os`, `Sequence`, `find_project`. - `as_dict` redacts `summary` but leaves `title` and `extra` unredacted. If `summary` is considered sensitive enough to redact, the reasoning should be applied consistently or the asymmetry documented. - `webui/notifications.py:225-231` probes a callable's signature by catching `TypeError` from the call itself, in a nested fallback. A `TypeError` raised from *inside* a correctly-called loader is indistinguishable from an arity mismatch, so a real error in the health loader is silently retried with a different arity and can surface as an unrelated failure. Prefer `inspect.signature` if the arity really must be discovered at runtime. ## Canonical PR State STATE: PR-open WHO_IS_NEXT: author NEXT_ACTION: Fix B1, B2, and B3 in webui/notifications.py, then push and request re-review. NEXT_PROMPT: ```text Address the REQUEST_CHANGES verdict on PR #905 (Closes #648), prgs / Scaled-Tech-Consulting / Gitea-Tools, reviewed at head bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9. B1 (webui/notifications.py:162-173) — classify_attention_event substring-matches "hard stop" / "unauthorized" / "irrecoverable" against a summary that three call sites build from the PR or issue title (lines 314-318, 338-341, 385-388), all of which pass no escalation flags. Any work item whose title contains one of those words escalates from routine to human-required on name alone, which defeats the noise-filtering AC of #648. Classify from the structured flags and category; if a text signal is needed, read a machine-generated status/detail field, never a human-authored title. B2 (webui/notifications.py:237-246 and 433-443) — notification ids are loop-invariant: notif-sys-err-{project.id} repeats for every probe error, and notif-collision-{collision.issue_number or 0} collapses every collision without an issue number onto 0. id is published on /api/v1/notifications, so fold the loop variable into it. B3 (webui/notifications.py:462) — probe_errors is assigned to fetch_error, so notification_views.py:90-91 renders a "Fetch Warning" when nothing failed to fetch, and double-reports errors already emitted as items at lines 237-246. Keep the two conditions distinct. Also worth clearing: unused imports os, Sequence, find_project; as_dict redacts summary but not title or extra; the TypeError-arity probing at lines 225-231 can swallow a real TypeError raised inside the health loader. Add a regression test per blocker. For B1 the test should assert that a routine transition on an item whose title contains "irrecoverable" still classifies as routine. ``` WHAT_HAPPENED: PR #905 was reviewed in full, first at head 4f06d30e0758a6f8ef9fa345e86ab42f823a73e0 and then re-verified at the current head bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9. The read found three code defects and three lesser observations. The head advanced between those two passes, but the advance was a merge of master into the branch and carried no author change to the reviewed code: the blobs for webui/notifications.py and webui/notification_views.py are byte-identical at both heads (15753b97054cba2056bc015b309c2b7fe0a53dfb and e4b6ab91f66bbb04ed4d28bdbe34c800a1c8e4f0 respectively). Every finding and every cited line number therefore carries over unchanged. The verdict was prepared during an earlier cycle but could not reach the API because the serving runtime had started at an older master commit and the mutation gate fail-closed with blocker_kind=runtime_reconnect_required. WHY: B1 defeats the central acceptance criterion of #648. The surface exists to separate genuine human-attention events from routine workflow noise, and this classifier promotes routine events to human-required based on words appearing in a human-authored title. In this repository, work items are commonly named after the exact mechanisms those keywords describe, so the misclassification lands on real, ordinary work rather than on a contrived edge case. B2 and B3 are narrower — an identifier-uniqueness violation on a published API field, and an operator-facing banner that misstates a healthy fetch as a failed one. ISSUE: #648 HEAD_SHA: bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9 REVIEW_STATUS: REQUEST_CHANGES MERGE_READY: false BLOCKERS: B1 title-substring escalation defeats the #648 filtering criterion; B2 loop-invariant notification ids on a published API field; B3 probe_errors misreported as fetch_error. VALIDATION: Static re-verification of all three findings against the live head bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9 immediately before recording this verdict, by reading webui/notifications.py and webui/notification_views.py at that revision. The head move from 4f06d30e was audited by comparing blob hashes rather than assumed benign: both reviewed files are unchanged, and the difference between the two heads is confined to files brought in by the master merge. Live head SHA before this verdict: bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9. Base master at that time: 26f54851d1d20eff92c339e778125f31c09fa95f. Author pushes containing code changes to the reviewed files during validation: none. The focused suite tests/test_webui_notifications.py returned 5 passed during the original review pass. No full-suite run was performed at this head in this session, and none is claimed; the three findings are static defects that a suite run would not settle either way, since the branch ships no test that exercises them. LAST_UPDATED_BY: sysadmin (prgs-reviewer) NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9. No offline, import, or helper path was used. [THREAD STATE LEDGER] ### what is true now PR #905 remains in open state at head bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9, targeting master at 26f54851d1d20eff92c339e778125f31c09fa95f. The branch reports no conflict against that base. Server-side decision state: this REQUEST_CHANGES verdict is the first review decision recorded on PR #905; the PR carried no prior review of any kind and no prior discussion comments. Local verdict/state: REQUEST_CHANGES, three code defects, re-verified against the live head. ### what changed The review verdict moved from a locally-held result to a recorded server-side decision. The PR head moved from 4f06d30e0758a6f8ef9fa345e86ab42f823a73e0 to bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9 while the verdict was held locally. That move brought master into the branch and was not an author remediation: the two reviewed files are byte-identical across it, so no finding required revision. A base-sync concern noted at the earlier head no longer applies at this one. ### what is blocked Blocker classification: code blocker B1 — `webui/notifications.py:162-173` escalates routine events to human-required when a human-authored title contains "hard stop", "unauthorized", or "irrecoverable", via the summary built at lines 314-318, 338-341, and 385-388. B2 — loop-invariant ids at lines 237-246 and 433-443 break uniqueness of a field published on `/api/v1/notifications`. B3 — line 462 assigns `probe_errors` to `fetch_error`, so a healthy fetch renders an operator-facing failure banner. ### who/what acts next Next actor: author Required action: Fix B1, B2, and B3 in `webui/notifications.py`, add a regression test per blocker, push, and request re-review. Do not do: Do not treat the focused-suite result of 5 passed as evidence against these findings — the branch ships no test that exercises any of the three paths, which is itself part of what needs fixing. Do not narrow B1 to a keyword-list tweak; the defect is that a human-authored title reaches the classifier at all.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: prgs-reviewer-78651-cbbd1dba
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/conflict-fix-pr-905
phase: released
candidate_head: bb8c3a537b
target_branch: master
target_branch_sha: 26f54851d1
last_activity: 2026-07-25T22:23:42Z
expires_at: 2026-07-25T22:33:42Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-reviewer session_id: prgs-reviewer-78651-cbbd1dba worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/conflict-fix-pr-905 phase: released candidate_head: bb8c3a537b2bd9c67ae8e2a83b8e1018dd32f2a9 target_branch: master target_branch_sha: 26f54851d1d20eff92c339e778125f31c09fa95f last_activity: 2026-07-25T22:23:42Z expires_at: 2026-07-25T22:33:42Z blocker: manual-release
jcwalker3 added 1 commit 2026-07-25 17:26:49 -05:00
B1: classify_attention_event uses structured flags/category only — never
substring-match human-authored title/summary for escalation.

B2: make notification ids unique across probe_errors and collisions
(include loop index / kind).

B3: do not assign probe_errors to fetch_error (avoids false Fetch Warning
and double-reporting).

Regression tests cover all three blockers.

Refs #648
Author
Owner

Canonical Issue State

STATE: PR-open
WHO_IS_NEXT: reviewer
NEXT_ACTION: Fresh independent re-review of PR #905 at head a64ba08e27 after author remediation of REQUEST_CHANGES B1-B3.
NEXT_PROMPT:

Re-review PR #905 (Closes #648) on prgs / Scaled-Tech-Consulting / Gitea-Tools
at head a64ba08e274975e6a0a4f001241196b4f9e40485.

Prior REQUEST_CHANGES (review 604) at bb8c3a5 is superseded by author push.
Verify B1-B3 are fixed:
- B1: classify_attention_event must not escalate from human-authored title/summary keywords
- B2: notification ids unique across probe_errors and collisions
- B3: probe_errors must not set fetch_error

Regression tests live in tests/test_webui_notifications.py (8 passed locally).

WHAT_HAPPENED: Author remediated PR #905 REQUEST_CHANGES (review 604) at bb8c3a5. Pushed a64ba08 on feat/issue-648-notifications-console fixing B1 (structured classification only), B2 (unique ids), B3 (fetch_error isolation). Unit suite tests/test_webui_notifications.py: 8 passed.
WHY: Review 604 blocked merge on three code defects that defeated #648 attention filtering and polluted API ids / fetch banners. Fixes restore the Phase 3 AC without changing the public route surface.
RELATED_PRS: #905
BLOCKERS: none for author path; awaiting independent reviewer re-approval at a64ba08
VALIDATION: pytest tests/test_webui_notifications.py -q returned 8 passed; git push prgs HEAD:feat/issue-648-notifications-console landed a64ba08
LAST_UPDATED_BY: jcwalker3 (prgs-author)

## Canonical Issue State STATE: PR-open WHO_IS_NEXT: reviewer NEXT_ACTION: Fresh independent re-review of PR #905 at head a64ba08e274975e6a0a4f001241196b4f9e40485 after author remediation of REQUEST_CHANGES B1-B3. NEXT_PROMPT: ```text Re-review PR #905 (Closes #648) on prgs / Scaled-Tech-Consulting / Gitea-Tools at head a64ba08e274975e6a0a4f001241196b4f9e40485. Prior REQUEST_CHANGES (review 604) at bb8c3a5 is superseded by author push. Verify B1-B3 are fixed: - B1: classify_attention_event must not escalate from human-authored title/summary keywords - B2: notification ids unique across probe_errors and collisions - B3: probe_errors must not set fetch_error Regression tests live in tests/test_webui_notifications.py (8 passed locally). ``` WHAT_HAPPENED: Author remediated PR #905 REQUEST_CHANGES (review 604) at bb8c3a5. Pushed a64ba08 on feat/issue-648-notifications-console fixing B1 (structured classification only), B2 (unique ids), B3 (fetch_error isolation). Unit suite tests/test_webui_notifications.py: 8 passed. WHY: Review 604 blocked merge on three code defects that defeated #648 attention filtering and polluted API ids / fetch banners. Fixes restore the Phase 3 AC without changing the public route surface. RELATED_PRS: #905 BLOCKERS: none for author path; awaiting independent reviewer re-approval at a64ba08 VALIDATION: pytest tests/test_webui_notifications.py -q returned 8 passed; git push prgs HEAD:feat/issue-648-notifications-console landed a64ba08 LAST_UPDATED_BY: jcwalker3 (prgs-author)
jcwalker3 added 1 commit 2026-07-25 17:29:59 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 93555-4ec2c2691093
worktree: branches/review-pr905-a64ba08
phase: claimed
candidate_head: 71031c812e
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T22:31:34Z
expires_at: 2026-07-25T22:41:34Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 93555-4ec2c2691093 worktree: branches/review-pr905-a64ba08 phase: claimed candidate_head: 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 target_branch: master target_branch_sha: none last_activity: 2026-07-25T22:31:34Z expires_at: 2026-07-25T22:41:34Z blocker: none
sysadmin approved these changes 2026-07-25 17:31:52 -05:00
Dismissed
sysadmin left a comment
Owner

Re-review: APPROVE PR #905 (supersedes review 604)

Author remediated REQUEST_CHANGES at bb8c3a5 via a64ba08; live head is 71031c8 (merge master into branch).

B1-B3 re-check at 71031c8

  • B1 fixed: classify_attention_event uses structured flags/category only; title/summary discarded (del title, summary); no hard-stop/unauthorized/irrecoverable substring matching on human text.
  • B2 fixed: unique ids notif-sys-err-{project}-{idx}, notif-collision-{kind}-{issue|none}-{idx}.
  • B3 fixed: fetch_error is queue/lease only; probe_errors remain items only.

Validation

tests/test_webui_notifications.py — 8 passed at worktree head 71031c8 (includes B1/B2/B3 regressions).

Canonical PR State

STATE: PR-open
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #905 at head 71031c812e after this APPROVE (update_branch only if master races ahead).
NEXT_PROMPT:

Merge PR #905 on prgs / Scaled-Tech-Consulting / Gitea-Tools at head
71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 after independent APPROVE.
Assess with gitea_assess_pr_sync_status first; merge_now if ready.
Closes #648.

WHAT_HAPPENED: Independent re-review after author push a64ba08 (B1-B3) and subsequent master merge 71031c8. Prior REQUEST_CHANGES (review 604 @ bb8c3a5) is stale. All three blockers verified fixed; suite 8 passed. APPROVE submitted.
WHY: #648 Phase 3 notifications surface is complete and the review-604 defects that defeated attention filtering / id uniqueness / fetch semantics are remediated at the live head.
ISSUE: #648
HEAD_SHA: 71031c812e
REVIEW_STATUS: APPROVE
MERGE_READY: true
BLOCKERS: none for code review; merger should re-check commits-behind master at merge time
VALIDATION: Static re-read of webui/notifications.py at 71031c8; pytest tests/test_webui_notifications.py -q returned 8 passed; a64ba08 is ancestor of live head
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha 71031c812e.

## Re-review: APPROVE PR #905 (supersedes review 604) Author remediated REQUEST_CHANGES at bb8c3a5 via a64ba08; live head is 71031c8 (merge master into branch). ### B1-B3 re-check at 71031c8 - **B1 fixed**: classify_attention_event uses structured flags/category only; title/summary discarded (`del title, summary`); no hard-stop/unauthorized/irrecoverable substring matching on human text. - **B2 fixed**: unique ids `notif-sys-err-{project}-{idx}`, `notif-collision-{kind}-{issue|none}-{idx}`. - **B3 fixed**: fetch_error is queue/lease only; probe_errors remain items only. ### Validation tests/test_webui_notifications.py — 8 passed at worktree head 71031c8 (includes B1/B2/B3 regressions). ## Canonical PR State STATE: PR-open WHO_IS_NEXT: merger NEXT_ACTION: Merge PR #905 at head 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 after this APPROVE (update_branch only if master races ahead). NEXT_PROMPT: ```text Merge PR #905 on prgs / Scaled-Tech-Consulting / Gitea-Tools at head 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 after independent APPROVE. Assess with gitea_assess_pr_sync_status first; merge_now if ready. Closes #648. ``` WHAT_HAPPENED: Independent re-review after author push a64ba08 (B1-B3) and subsequent master merge 71031c8. Prior REQUEST_CHANGES (review 604 @ bb8c3a5) is stale. All three blockers verified fixed; suite 8 passed. APPROVE submitted. WHY: #648 Phase 3 notifications surface is complete and the review-604 defects that defeated attention filtering / id uniqueness / fetch semantics are remediated at the live head. ISSUE: #648 HEAD_SHA: 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 REVIEW_STATUS: APPROVE MERGE_READY: true BLOCKERS: none for code review; merger should re-check commits-behind master at merge time VALIDATION: Static re-read of webui/notifications.py at 71031c8; pytest tests/test_webui_notifications.py -q returned 8 passed; a64ba08 is ancestor of live head LAST_UPDATED_BY: sysadmin (prgs-reviewer) NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178.
jcwalker3 added 1 commit 2026-07-25 17:37:23 -05:00
Author
Owner

Canonical Issue State

STATE: PR-open
WHO_IS_NEXT: reviewer
NEXT_ACTION: Fresh independent re-review of PR #905 at head c83a10d7c2 after author update_branch_by_merge of live master (prior APPROVE @ 71031c8 invalidated).
NEXT_PROMPT:

Re-review PR #905 (Closes #648) on prgs / Scaled-Tech-Consulting / Gitea-Tools
at head c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf.

Head moved only for conflict-free merge of prgs/master into
feat/issue-648-notifications-console (update_branch_by_merge). Prior APPROVE
at 71031c8 is stale. Re-verify B1-B3 still present; notifications suite 8 passed.

WHAT_HAPPENED: Master advanced after APPROVE at 71031c8; assess required update_branch_by_merge (5 commits behind, conflict-free). Author merged prgs/master into the PR branch and pushed c83a10d. Notifications tests still 8 passed.
WHY: Branch protection requires PR head contain current base; non-rebase merge keeps history and intentionally invalidates prior head-pinned approval so an independent reviewer re-approves the post-sync head.
RELATED_PRS: #905
BLOCKERS: none for author; awaiting re-approval at c83a10d
VALIDATION: git merge prgs/master clean; pytest tests/test_webui_notifications.py -q → 8 passed; push 71031c8..c83a10d
LAST_UPDATED_BY: jcwalker3 (prgs-author)

## Canonical Issue State STATE: PR-open WHO_IS_NEXT: reviewer NEXT_ACTION: Fresh independent re-review of PR #905 at head c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf after author update_branch_by_merge of live master (prior APPROVE @ 71031c8 invalidated). NEXT_PROMPT: ```text Re-review PR #905 (Closes #648) on prgs / Scaled-Tech-Consulting / Gitea-Tools at head c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf. Head moved only for conflict-free merge of prgs/master into feat/issue-648-notifications-console (update_branch_by_merge). Prior APPROVE at 71031c8 is stale. Re-verify B1-B3 still present; notifications suite 8 passed. ``` WHAT_HAPPENED: Master advanced after APPROVE at 71031c8; assess required update_branch_by_merge (5 commits behind, conflict-free). Author merged prgs/master into the PR branch and pushed c83a10d. Notifications tests still 8 passed. WHY: Branch protection requires PR head contain current base; non-rebase merge keeps history and intentionally invalidates prior head-pinned approval so an independent reviewer re-approves the post-sync head. RELATED_PRS: #905 BLOCKERS: none for author; awaiting re-approval at c83a10d VALIDATION: git merge prgs/master clean; pytest tests/test_webui_notifications.py -q → 8 passed; push 71031c8..c83a10d LAST_UPDATED_BY: jcwalker3 (prgs-author)
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 93555-4ec2c2691093
worktree: branches/review-pr905-a64ba08
phase: released
candidate_head: 71031c812e
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T22:38:55Z
expires_at: 2026-07-25T22:48:55Z
blocker: obsolete-superseded-or-expired-lease

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 93555-4ec2c2691093 worktree: branches/review-pr905-a64ba08 phase: released candidate_head: 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 target_branch: master target_branch_sha: none last_activity: 2026-07-25T22:38:55Z expires_at: 2026-07-25T22:48:55Z blocker: obsolete-superseded-or-expired-lease
Owner

Canonical obsolete reviewer lease cleanup (#691)

  • pr: feat(webui): notifications and human-attention routing (#648) (#905)
  • lease_comment_id: 16968
  • session_id: 93555-4ec2c2691093
  • leased_head: 71031c812e
  • current_head: c83a10d7c2
  • expires_at: 2026-07-25T22:41:34Z
  • classification: foreign_completed_superseded_head
  • terminal_review_verdict: APPROVED
  • tool: gitea_cleanup_obsolete_reviewer_comment_lease
  • action: posted terminal phase=released lease marker; did not transfer validation, decision, or workflow proof; did not repoint lease to the new head; did not delete history
## Canonical obsolete reviewer lease cleanup (#691) - pr: #905 - lease_comment_id: 16968 - session_id: 93555-4ec2c2691093 - leased_head: 71031c812e3cdd3b9aac9a0d81f1dcb908f3a178 - current_head: c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf - expires_at: 2026-07-25T22:41:34Z - classification: foreign_completed_superseded_head - terminal_review_verdict: APPROVED - tool: gitea_cleanup_obsolete_reviewer_comment_lease - action: posted terminal phase=released lease marker; did not transfer validation, decision, or workflow proof; did not repoint lease to the new head; did not delete history
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 39434-8119054acc5d
worktree: branches/review-pr905-c83a10d
phase: claimed
candidate_head: c83a10d7c2
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T22:39:08Z
expires_at: 2026-07-25T22:49:08Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 39434-8119054acc5d worktree: branches/review-pr905-c83a10d phase: claimed candidate_head: c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf target_branch: master target_branch_sha: none last_activity: 2026-07-25T22:39:08Z expires_at: 2026-07-25T22:49:08Z blocker: none
sysadmin approved these changes 2026-07-25 17:39:28 -05:00
sysadmin left a comment
Owner

Re-review APPROVE after update_branch_by_merge

Head advanced from 71031c8c83a10d solely via conflict-free merge of prgs/master into feat/issue-648-notifications-console (no feature code changes beyond base sync).

Re-verified at c83a10d

  • B1–B3 still present (structured classification; unique ids; fetch_error isolation)
  • tests/test_webui_notifications.py8 passed
  • Prior APPROVE @ 71031c8 (review 607) is superseded; this is a fresh head-pinned APPROVE

Canonical PR State

STATE: PR-open
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #905 at head c83a10d7c2 (assess merge_now first).
NEXT_PROMPT:

Merge PR #905 on prgs / Scaled-Tech-Consulting / Gitea-Tools at head
c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf after APPROVE.
Use gitea_assess_pr_sync_status; if merge_now, gitea_merge_pr with confirmation
MERGE PR 905 and expected_head_sha pinned. Closes #648.

WHAT_HAPPENED: After master advanced past APPROVE@71031c8, author merged master into the PR branch (c83a10d). Independent re-review confirmed B1-B3 still fixed and suite green; APPROVE submitted at new head.
WHY: Head-pinned approvals are invalidated by base sync; re-approval restores merge eligibility for #648 notifications surface.
ISSUE: #648
HEAD_SHA: c83a10d7c2
REVIEW_STATUS: APPROVE
MERGE_READY: true
BLOCKERS: none for review; merger re-checks base race at merge time
VALIDATION: pytest tests/test_webui_notifications.py -q → 8 passed at c83a10d; static re-read of classifier/id/fetch_error fixes
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha c83a10d7c2.

## Re-review APPROVE after update_branch_by_merge Head advanced from 71031c8 → c83a10d solely via conflict-free merge of prgs/master into feat/issue-648-notifications-console (no feature code changes beyond base sync). ### Re-verified at c83a10d - **B1–B3** still present (structured classification; unique ids; fetch_error isolation) - `tests/test_webui_notifications.py` — **8 passed** - Prior APPROVE @ 71031c8 (review 607) is superseded; this is a fresh head-pinned APPROVE ## Canonical PR State STATE: PR-open WHO_IS_NEXT: merger NEXT_ACTION: Merge PR #905 at head c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf (assess merge_now first). NEXT_PROMPT: ```text Merge PR #905 on prgs / Scaled-Tech-Consulting / Gitea-Tools at head c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf after APPROVE. Use gitea_assess_pr_sync_status; if merge_now, gitea_merge_pr with confirmation MERGE PR 905 and expected_head_sha pinned. Closes #648. ``` WHAT_HAPPENED: After master advanced past APPROVE@71031c8, author merged master into the PR branch (c83a10d). Independent re-review confirmed B1-B3 still fixed and suite green; APPROVE submitted at new head. WHY: Head-pinned approvals are invalidated by base sync; re-approval restores merge eligibility for #648 notifications surface. ISSUE: #648 HEAD_SHA: c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf REVIEW_STATUS: APPROVE MERGE_READY: true BLOCKERS: none for review; merger re-checks base race at merge time VALIDATION: pytest tests/test_webui_notifications.py -q → 8 passed at c83a10d; static re-read of classifier/id/fetch_error fixes LAST_UPDATED_BY: sysadmin (prgs-reviewer) NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf.
Owner

adopted_at: 2026-07-25T22:39:53Z
adopted_by_identity: sysadmin
adopted_by_profile: prgs-merger
adopted_from_session_id: 39434-8119054acc5d
adopted_from_profile: prgs-reviewer
adopted_from_reviewer_identity: sysadmin
adopted_from_comment_id: 16989
adoption_reason: merger-handoff-approved-head

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #905
issue: #648
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 39432-7a0f1dbcb0f4
worktree: branches/merge-pr905-c83a10d
phase: adopted
candidate_head: c83a10d7c2
target_branch: master
target_branch_sha: none
last_activity: 2026-07-25T22:39:53Z
expires_at: 2026-07-25T22:49:53Z
blocker: none

<!-- mcp-review-lease-adoption:v1 --> adopted_at: 2026-07-25T22:39:53Z adopted_by_identity: sysadmin adopted_by_profile: prgs-merger adopted_from_session_id: 39434-8119054acc5d adopted_from_profile: prgs-reviewer adopted_from_reviewer_identity: sysadmin adopted_from_comment_id: 16989 adoption_reason: merger-handoff-approved-head <!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #905 issue: #648 reviewer_identity: sysadmin profile: prgs-merger session_id: 39432-7a0f1dbcb0f4 worktree: branches/merge-pr905-c83a10d phase: adopted candidate_head: c83a10d7c223f37f8c1ceebd1fc1ecad001fdcaf target_branch: master target_branch_sha: none last_activity: 2026-07-25T22:39:53Z expires_at: 2026-07-25T22:49:53Z blocker: none
sysadmin merged commit c6d68dbc7b into master 2026-07-25 17:40:04 -05:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#905