Skip to content

fix: address Copilot review on PRs #3 + #4#5

Merged
jphein merged 1 commit intomainfrom
fix/copilot-review-batch-202605051
May 6, 2026
Merged

fix: address Copilot review on PRs #3 + #4#5
jphein merged 1 commit intomainfrom
fix/copilot-review-batch-202605051

Conversation

@jphein
Copy link
Copy Markdown
Owner

@jphein jphein commented May 6, 2026

Batches 7 Copilot findings across PR #3 (file-watcher) and PR #4 (mine-queue).

PR #3:

  • watcher.py: drop unused time import
  • watcher.py: type _log_future_exception correctly (concurrent.futures.Future, not asyncio.Future) + catch concurrent.futures.CancelledError
  • main.py: watcher mine failures surface stderr/stdout, not just rc
  • main.py: GET /watch double-checks is_running so a thread crash post-startup flips the response

PR #4:

  • drain replay re-applies optional extract / limit fields (was dropping them silently)
  • drain replay enforces the same safety guards as live /mine (isinstance str, absolute path, no traversal, valid mode/extract/limit)

+2 new tests (replay-extract-and-limit, skips-invalid-payload-fields). 35 daemon tests pass.

🤖 Generated with Claude Code

Seven findings, batched into one cleanup PR.

PR #3 (file-watcher) findings:

* watcher.py:30 — drop unused ``import time``.
* watcher.py:336 — type ``_log_future_exception`` parameter as
  ``concurrent.futures.Future`` (NOT ``asyncio.Future``); that's
  what ``asyncio.run_coroutine_threadsafe`` returns. Catch its
  cancellation/state errors plus the asyncio variants so the
  callback can't itself crash on a concurrent cancellation.
* main.py:560 — surface stderr/stdout when watcher mine returns
  non-zero. The rc alone hides 'No mempalace.yaml found' / python
  tracebacks operators need to diagnose.
* main.py:1202 — ``GET /watch`` now double-checks
  ``watcher.is_running`` so a thread crash that flips is_running
  to False between startup and now is reflected in the endpoint
  response. Lifespan still gates publication; this adds defense
  in depth.

PR #4 (mine-queue) findings:

* main.py drain replay — re-apply optional ``extract`` and
  ``limit`` fields. The prior drain dropped them silently, so a
  queue entry with those fields got replayed without. Live /mine
  accepts them; replay must too.
* main.py drain replay — enforce the same safety guards as the
  live /mine endpoint: ``isinstance(dir, str)``, absolute-path,
  no ``..`` traversal, ``mode in {convos, projects}``, ``extract
  in {exchange, general}`` if set, ``limit`` int-coercible if
  set. Without these a queue entry could smuggle through values
  the live endpoint would 400.

Tests: +2 — replay-extract-and-limit (asserts the new fields
make it onto the subprocess argv) and skips-invalid-payload-fields
(5 invalid-payload variants, each correctly skipped pre-spawn).
35 daemon tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings May 6, 2026 03:51
@jphein jphein merged commit 5fa0341 into main May 6, 2026
1 check passed
@jphein jphein deleted the fix/copilot-review-batch-202605051 branch May 6, 2026 03:52
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses previously identified review findings across the watcher service and the pending-mine queue drain path, focusing on correctness of cross-thread future handling, better operator diagnostics, and ensuring queued mine replays are validated consistently with live /mine requests.

Changes:

  • Fix watcher future callback typing/exception handling for asyncio.run_coroutine_threadsafe() (use concurrent.futures.Future) and remove an unused import.
  • Improve subprocess failure logging (surface stderr/stdout) and make GET /watch reflect watcher thread crashes by re-checking is_running.
  • Ensure pending-mine drain replay preserves extract/limit and enforces the same validation guards as the live /mine endpoint; add tests for these cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
watcher.py Corrects the future type/exception handling for cross-thread coroutine scheduling and removes an unused import.
main.py Hardens pending-mine drain replay validation, preserves optional replay fields, improves subprocess failure logs, and tightens /watch running-state reporting.
tests/test_mine_queue.py Adds coverage to ensure drain replay preserves extract/limit and skips invalid queued payloads without spawning subprocesses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread main.py
Comment on lines +388 to +393
# Same valid-mode/extract sets as the live /mine endpoint —
# apply them on replay too so a queue entry can't smuggle through
# a value the live endpoint would reject (Copilot finding on
# jphein/palace-daemon#4).
VALID_MODES = {"convos", "projects"}
VALID_EXTRACTS = {"exchange", "general"}
Comment thread main.py
"drain-mine: replay returned %s for %s\n stderr: %s",
proc.returncode,
directory,
(stderr or b"").decode(errors="replace")[:300],
Comment thread main.py
Comment on lines +716 to +717
(stderr or b"").decode(errors="replace")[:500],
(stdout or b"").decode(errors="replace")[-500:],
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.

2 participants