feat(ui): review an inbox note from its own page
The inbox card only edits the body, so correcting frontmatter an agent got wrong — a bad type, invented tags, a malformed valid_from — means opening the note and using the full edit form. But the note page had no Approve or Reject, so the owner had to navigate back to the inbox to act on what they had just fixed. Both now appear on the note page while the note is in the inbox, posting to the same routes the inbox uses, so revision merges and supersede chains behave identically. An active note still shows only edit/archive/delete. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0139vHnNpS2sLNELjrAHX5Cu
This commit is contained in:
1 parent
10acfe76e6
commit
85783c360b
2 files changed
+53
No files matched your search
@@ -60,6 +60,18 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="actions">
|
||||
{% if note.state == 'inbox' %}
|
||||
{# Review without a round trip: having come here from the inbox to fix the
|
||||
frontmatter, the decision belongs on this page too. Same route the inbox
|
||||
posts to, so revision merges and supersede chains behave identically. #}
|
||||
<form method="post" action="/ui/n/{{ note.id }}/approve">
|
||||
<button class="primary" type="submit">Approve</button>
|
||||
</form>
|
||||
<form method="post" action="/ui/n/{{ note.id }}/reject">
|
||||
<input type="text" name="reason" placeholder="Reason (optional)">
|
||||
<button class="danger" type="submit">Reject</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<a class="button" href="/ui/n/{{ note.id }}/edit">Edit</a>
|
||||
{% if note.state != 'archive' %}
|
||||
<form method="post" action="/ui/n/{{ note.id }}/state"><input type="hidden" name="state" value="archive"><button type="submit">Archive</button></form>
|
||||
|
||||
@@ -476,3 +476,44 @@ async def test_search_state_filter_still_finds_matches_below_the_first_page(ui):
|
||||
r = await client.get("/ui/search", params={"q": "Bifrost routet Modelle", "state": "inbox"})
|
||||
assert r.status_code == 200
|
||||
assert needle["id"] in r.text
|
||||
|
||||
|
||||
async def test_an_inbox_note_can_be_reviewed_from_its_own_page(ui):
|
||||
"""Fixing an LLM's frontmatter happens on the note page; without approve here
|
||||
the owner has to navigate back to the inbox to act on what they just fixed."""
|
||||
client, svc = ui
|
||||
w = await svc.write_note(title="Needs a fix", body="v1", type="fact")
|
||||
|
||||
page = await client.get(f"/ui/n/{w['id']}")
|
||||
assert "Approve" in page.text and "Reject" in page.text
|
||||
|
||||
r = await client.post(f"/ui/n/{w['id']}/approve", data={})
|
||||
assert r.status_code == 303
|
||||
assert svc.get_note(w["id"]).state == "active"
|
||||
|
||||
# and an active note offers no review buttons, only archive/edit/delete
|
||||
page = await client.get(f"/ui/n/{w['id']}")
|
||||
assert "/approve" not in page.text and "/reject" not in page.text
|
||||
|
||||
|
||||
async def test_frontmatter_fixed_on_the_note_page_survives_approval(ui):
|
||||
"""The whole point of the button: correct what the agent got wrong, then
|
||||
accept it, without the fix being lost on the way."""
|
||||
client, svc = ui
|
||||
w = await svc.write_note(title="Wrong type", body="v1", type="note", tags=["bogus"])
|
||||
note = svc.get_note(w["id"])
|
||||
fm = note.to_text().split("---\n")[1].replace("type: note", "type: fact")
|
||||
fm = fm.replace("- bogus", "- homelab")
|
||||
|
||||
saved = await client.post(
|
||||
f"/ui/n/{w['id']}/edit",
|
||||
data={"body": "v1 corrected", "frontmatter": fm, "expected_version": note.file_hash},
|
||||
)
|
||||
assert saved.status_code in (200, 303)
|
||||
|
||||
assert (await client.post(f"/ui/n/{w['id']}/approve", data={})).status_code == 303
|
||||
approved = svc.get_note(w["id"])
|
||||
assert approved.state == "active"
|
||||
assert approved.type == "fact"
|
||||
assert approved.tags == ["homelab"]
|
||||
assert approved.body.strip() == "v1 corrected"
|
||||
Reference in new issue
Block a user