Skip to content

feat: a thread reply can resolve the thread it verified as fixed - #105

Merged
Zaimwa9 merged 1 commit into
mainfrom
feat/discuss-resolve-thread
Jul 28, 2026
Merged

Zaimwa9 merged 1 commit into
mainfrom
feat/discuss-resolve-thread

Conversation

@Zaimwa9

@Zaimwa9 Zaimwa9 commented Jul 28, 2026

Copy link
Copy Markdown
Owner

What

A thread reply can now resolve the thread it is replying in, when the agent verified in the checkout that its own finding is fixed.

Why

The discuss path had no resolve capability at all — it parses reply.md and nothing else, so gh.resolve_thread() was reachable only from the review path. Asked in a thread "is this fixed now?", the agent would reply "Confirmed fixed in abc1234 — resolving." and nothing would happen.

That is worse than not resolving: the bot narrates an action the harness cannot perform, so a maintainer reads "resolving", moves on, and the thread stays open. Observed live on a PR where all 12 bot threads remained open after several such replies.

How

  • resolution.json — a new optional output file ({"resolved": true}), added to OUTPUT_FILES in lockstep as that comment requires. parse_resolution mirrors parse_learning's contract: absent means no claim, malformed raises OutputError which the caller treats as no-resolution rather than a job failure.
  • Prompt (thread kind only — a conversation comment has no thread): write the file only when the fix is verified in the current checkout, and never claim to be resolving without writing it. The bar stays "an open thread costs far less than one closed over a live defect".
  • discuss() acts on it after the reply is posted, and only for threads whose first comment is bot-authored — closing a human's thread would answer their question on their behalf. Reuses the same _bot_logins ownership rule as the review path.

Resolution is best-effort by construction: the reply is the deliverable, so a malformed file, a non-bot thread, or a failing GraphQL call logs and moves on.

Tests

Own thread + verified → resolved; no file / resolved: false → left open; human thread → refused and logged; malformed JSON → reply still posts; failing resolve call → reply still succeeds; conversation comment → never attempted. Plus parse_resolution unit coverage (absent, valid, five malformed shapes) and the OUTPUT_FILES guard.

Note

Stacked on #104 (both touch build_discussion_prompt); base retargets to main once that merges.

@themis-lezgo

themis-lezgo Bot commented Jul 28, 2026

Copy link
Copy Markdown

⚖️ Themis review: ✅ Ship it

TL;DR: This adds a narrowly scoped, validated resolution signal for replies in the bot’s own review threads, while retaining the existing output redaction boundary and best-effort delivery behavior. The currently queued CI run provides no completed result yet.

🎯 Correctness 4/5
🧪 Test coverage 4/5
📐 Code quality 4/5
🚀 Product impact 3/5
📝 Walkthrough
  • resolution.json - adds an optional, strictly boolean agent output for a verified fix.
  • Discussion delivery - posts the answer first, then resolves only a thread whose root comment is bot-authored.
  • Failure handling - malformed signals and GitHub resolution errors leave the reply delivered and the thread open.
🧪 How to verify
  1. Run uv run pytest -q tests/test_output.py tests/test_prompts.py tests/test_review_service.py.
  2. Reply to a bot-authored review thread with a verified fix and confirm the reply posts and the thread resolves.
  3. Repeat on a human-authored thread and confirm it remains open.
  4. Return malformed resolution JSON and a GraphQL resolution failure; confirm the reply still posts and the thread remains open.
  5. Confirm a conversation-level reply never attempts a thread resolution.
    Automate: keep these cases in the focused output, prompt, and discussion-service tests.

Product take: Solid workflow polish: maintainers no longer need to manually close bot findings that a follow-up has verified as fixed.

🧭 Assumptions & unverified claims

Focused tests and linting could not run locally because dependency installation could not reach PyPI; the CI run is still queued.

A small closure for threads that have finally earned it. · reviewed at e87aae6

The discuss path had no way to resolve anything: it parses reply.md only, so
resolve_thread was reachable from the review path alone. The agent, asked in
a thread whether its finding was fixed, would answer "confirmed fixed —
resolving" and nothing happened; every such thread stayed open. Add an
optional resolution.json the agent writes when it verified the fix, acted on
after the reply posts, and only for the bot's own threads.
@Zaimwa9
Zaimwa9 force-pushed the feat/discuss-resolve-thread branch from e87aae6 to e650ae5 Compare July 28, 2026 09:48
@Zaimwa9
Zaimwa9 changed the base branch from fix/discuss-prompt-doctrine to main July 28, 2026 09:48
@Zaimwa9
Zaimwa9 merged commit 4172550 into main Jul 28, 2026
2 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