Attention points close with a verdict: approved / rejected #16

Merged
hermes-agent merged 4 commits from feature/flag-disposition into main 2026-10-29 18:50:05 +00:00
Owner

On the manager's entry page the two free-text boxes under an attention point made no sense as a workflow - the owner called it out: a toelichting and a reden, with no decision, means the point is never handled. Looking is not deciding.

What the two boxes were

Toelichting was a free note stored on the flag (resolution_note); Reden fed the audit trail (record_audit(reason=...)) - a code-audit field leaking into the UI. Two vague boxes, no outcome.

The fix (owner advice implemented)

  • Flag.disposition: approved / rejected (Postgres enum flagdisposition, migration 0010), NULL while open. The verdict is what closes the point.
  • The resolve form: a required decision dropdown (Kies… / Goedgekeurd / Afgekeurd) plus one optional Toelichting. The second box is gone; its audit role moves to the toelichting, which the flag.resolve audit row stores as the reason.
  • No choice, no handling: an empty verdict is refused - the flag stays open and no audit row is written. The dropdown is required in the UI too.
  • A verdict is bookkeeping, not scoring: a rejection changes no score; consequences belong to the existing manual score-adjustment tool (T5.2), per the never-auto-reject rule.
  • Legacy resolutions without a disposition still read as handled; new ones always carry a verdict.

Verified live

Entry 4 (PD9MODE, two MODE_NOT_ALLOWED flags): flagged one Afgekeurd with "Geen geldige modes voor de NLC" - verdict + note render on the page - the other left open with its dropdown; an empty-verdict POST was refused (flag untouched).

Tests: 315 (3 new, 1 updated to the verdict API).

On the manager's entry page the two free-text boxes under an attention point made no sense as a workflow - the owner called it out: a toelichting and a reden, with no decision, means the point is never handled. Looking is not deciding. ## What the two boxes were `Toelichting` was a free note stored on the flag (`resolution_note`); `Reden` fed the audit trail (`record_audit(reason=...)`) - a code-audit field leaking into the UI. Two vague boxes, no outcome. ## The fix (owner advice implemented) - `Flag.disposition`: **approved / rejected** (Postgres enum `flagdisposition`, migration 0010), NULL while open. The verdict is what *closes* the point. - The resolve form: a **required decision dropdown** (Kies… / Goedgekeurd / Afgekeurd) plus **one** optional Toelichting. The second box is gone; its audit role moves to the toelichting, which the `flag.resolve` audit row stores as the reason. - **No choice, no handling**: an empty verdict is refused - the flag stays open and no audit row is written. The dropdown is required in the UI too. - **A verdict is bookkeeping, not scoring**: a rejection changes no score; consequences belong to the existing manual score-adjustment tool (T5.2), per the never-auto-reject rule. - Legacy resolutions without a disposition still read as handled; new ones always carry a verdict. ## Verified live Entry 4 (PD9MODE, two MODE_NOT_ALLOWED flags): flagged one Afgekeurd with "Geen geldige modes voor de NLC" - verdict + note render on the page - the other left open with its dropdown; an empty-verdict POST was refused (flag untouched). Tests: **315** (3 new, 1 updated to the verdict API).
The manager's entry drill-in showed no mode, so the mode could not be controlled
there at all. The shared per-QSO table (preview, confirmation, manager drill-in and
the live sessions view) gets a Mode column fed by a display helper:

- The mode is rendered in the reglement's own vocabulary: FM, SSB, CW. SSB's
  emission labels USB/LSB are ACCEPTED and read as "SSB" (owner: do not disapprove
  them), the same normalisation the flag layer and the live logger apply - so a
  logged USB is an ordinary SSB row, no finding.
- EDI's numeric mode codes never reach the table (1/2/6 are translated at parse
  time); a mode outside the reglement keeps its RAW value ("DG", "RY") with a
  MODE_NOT_ALLOWED marker on that row, so the manager can adjudicate what was
  actually logged.
- A blank mode renders as an em dash - EDI allows an empty mode column by the
  standard, so absence is not a finding.

Verified on the running stack: entry 1 (PD1SCO) shows FM/SSB per row; entry 4
(PD9MODE) keeps DG and RY with the marker. Tests: 312 (5 new).
On the manager's entry page the two free-text boxes under an attention point made
no sense as a workflow - the owner called it out: a toelichting and a reden, with
no decision, means the point is never handled. Looking is not deciding.

- The Flag gains a disposition: approved or rejected, NULL while open. Postgres
  enum type flagdisposition (migration 0010; the type is created and referenced
  per the SAEnum lesson, so SQLite's create_all and the real database agree).
- The resolve form is now: a required decision dropdown (Kies + Goedgekeurd +
  Afgekeurd) and one optional toelichting. The second box is gone; its audit role
  moves to the toelichting, which the flag.resolve audit row stores as the reason.
- No disposition, no resolution: an empty choice is refused (redirect, flag stays
  open, no audit row) and the UI demands the dropdown.
- A verdict is bookkeeping, not scoring: a rejection changes no score; the
  manual score-adjustment tool (T5.2) remains where consequences live.
- Existing resolutions (resolved_by_manager without a disposition) read as
  afgehandeld as before; new ones always carry the verdict.

Verified on the running stack with entry 4's two MODE_NOT_ALLOWED flags: one
rejected with the toelichting stored (disposition=rejected, resolved, note on the
page), the other untouched; an empty verdict refused. Tests: 315 (3 new, 1
updated to the verdict API).
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
public/vrza-contestrobot!16
No description provided.