Skip to content

RE /next: per-answer feedback, and a disagreement lands in the gaps collection - #117

Merged
dwolfson merged 2 commits into
mainfrom
re/feedback-gaps
Sep 17, 2026
Merged

dwolfson merged 2 commits into
mainfrom
re/feedback-gaps

Conversation

@dwolfson

Copy link
Copy Markdown
Owner

PLAN-FINISH-REPOS.md item 8 — Feedback: present, not used. Done test: per-answer feedback exists, and a disagreement lands in the gaps collection as destination ours.

What this adds

  • next/feedback.js — "Was this right? · Right · Partly · Wrong" under every answered question row. No app.js edit: a MutationObserver on #question-rows plus delegated clicks, so it survives the app.js split and re-attaches after replaceRow rewrites a row's innerHTML. Idempotence is keyed on the injected bar, not a flag on the row.
  • POST /api/feedback/answer — resolves which analyses answer the question from the catalog rather than trusting the client; rejects an analysis_id the catalog does not list for it. Every verdict is stored; only disagree raises a gap.
  • gaps.py: record_disagreement — same upsert_gap as the measured gaps, marked ours. Identity (slug, analysis_id, disagreement, question:<text>), so two people disagreeing is one row. Gap rows now carry destination: ours and source: measured | person, plus a disputed_by_a_person count (a subset of the disagreement count).
  • docs/design-notes/ITEM-8-FEEDBACK-IMPLEMENTED.md — what it replies to, what was scoped out, what could not be tested.

Not verified on screen. :8810 serves from the main checkout on main; the control has not been seen rendering. First things to check after fast-forward: the [data-evidence] row selector and re-attachment after replaceRow.

Tests. 13 new (test_gaps.py::TestAPersonsDisagreement, test_answer_feedback_gap.py). Full suite 4762 passed; the one failure (test_fact_answer_rendering.py, an index.html byte-window assertion) is pre-existing and fixed in #115/#116.

🤖 Generated with Claude Code

dwolfson and others added 2 commits September 16, 2026 22:24
…ollection

PLAN-FINISH-REPOS.md item 8. Feedback existed twice — a floating product
button and chat-turn votes — and neither was about an answer to a catalogued
question, which is the surface a curator actually reads.

Adds a "Was this right? · Right · Partly · Wrong" control under every
answered question row, and POST /api/feedback/answer behind it. A
disagreement becomes a gap about the ANALYSIS, marked `ours` —
destinations.py's rule 1: the repository is not at fault for our answer
about it.

The control lives in next/feedback.js and does not touch app.js: that file
is being split into per-stage modules, and it rewrites a row's innerHTML in
place as each answer lands, so the bar is re-attached by a MutationObserver
and idempotence is keyed on the bar rather than a flag on the row (which
would survive the row's own innerHTML being replaced and stop it coming
back).

The route resolves which analyses answer a question from the question
catalog rather than trusting the client, and rejects an analysis_id the
catalog does not list for it — a stale page must not be able to charge a
dispute to an analysis that never answered. Every verdict is stored, not
only disagreements: "nobody has questioned this" and "someone confirmed it"
must not look alike. A question naming no analysis records analysis_id ""
rather than a guessed one.

Gap identity is (slug, analysis_id, disagreement, "question:<text>"), so a
second person disagreeing refreshes one row — the count stays "answers
disputed", not "clicks" — and the question: prefix cannot collide with a
check_registry.yaml check name, so record_gaps_for leaves it standing.
Gap rows now state destination `ours` and source measured|person, with a
disputed_by_a_person count that is a subset of the disagreement count.

Not verified on screen: :8810 serves from the main checkout, which is on
main. The two fragile points are named in the design note.

13 new tests; full suite 4762 passed, 1 pre-existing failure in
test_fact_answer_rendering.py (a byte-distance assertion on app.js, which
this branch does not modify).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
@dwolfson
dwolfson merged commit bd30b34 into main Sep 17, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant