Repository navigation
Conversation
The review comment footer now links "Kōan" to https://koan.anantys.com and shows the CLI provider and model used (e.g., "Claude · model claude-opus-4-6"), giving reviewers transparency on how the review was generated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move provider-specific behavior out of shared CLI code and into the provider objects so cli_exec no longer special-cases provider names: - Providers declare stdin prompt-passing support and own the argv->stdin rewrite (Claude "-p" placeholder, Codex "exec -"). - Providers can opt into serialized CLI invocations via a process-wide file lock. Codex uses it to avoid token-refresh races between preflight probes, message formatting, and long review sessions. - Providers own final-message-file arg placement (Codex inserts the flag before the prompt) and auth-failure detection. Codex recognizes 401 and refresh-token-reuse errors in both stderr and streamed JSONL events. Detect Codex auth failures from stdout-safe runtime lines so a bare 401 stream failure pauses for auth and requeues the active mission instead of marking it failed. Keep the trusted stdout surface narrow ([cli] summaries, CLI failure lines, and structured JSON error events) to avoid false positives from quoted CI logs or source text. Fix a missing contextlib import that crashed the JSON-event branch of the runtime auth scan with NameError, and add regression coverage for both the JSON-event auth case and a benign event that merely quotes a 401 string. Consolidate the triplicated provider error-event-type set into a single PROVIDER_ERROR_EVENT_TYPES constant in provider/base.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a post-mission test that feeds a Codex "event_msg" token_count JSONL event through run_post_mission and asserts both the budget state and the cost-tracker rows. It verifies that cached_input_tokens are treated as cache-read and subtracted from counted input, that the session and weekly token totals reflect billable input plus output, that the run counter increments, and that the emitted usage row carries the model, mode, and cache-read counts. Document the recognized Codex JSONL usage events in docs/providers/codex.md: "turn.completed" events with a "usage" object and "event_msg" rollout events whose "payload.type" is "token_count", along with the cache-read subtraction rule and the latest-snapshot-wins behavior when multiple usage-bearing events are present. This is test and documentation only; no production behavior changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consolidate all Kōan footer generation into a single pr_footer.py module with build_koan_footer() and strip_legacy_footers(). Every caller (pr_quality, review_runner, plan_runner, fix_runner, implement_runner, incident_runner, deepplan_runner, claudemd_refresh, tracker_comment_format) now uses the shared helper, producing a consistent branded link to koan.anantys.com. The quality pipeline also strips duplicate/legacy footers (including "🤖 Generated with Claude Code") from PR bodies before appending the quality report section.
Add thread-aware filtering to the review comment reply system. When the bot is the last poster in a thread and no human followed up, the thread is excluded from the repliable list on subsequent review runs. Also add a configurable max_thread_depth (default 5) to cap thread length. New config option: review_reply.max_thread_depth Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
increment_retry_count() and clear_retry_count() did unlocked load-increment-save, allowing concurrent parallel-session missions to read the same counter, both compute +1, and one overwrite the other — under-counting retries by one per race. Replaces the private _load/_save_retry_tracker helpers with locked_json_modify / locked_json_read from locked_file.py (the same pattern used by burn_rate, check_tracker, etc.). Reads in get_retry_count and get_retry_info now use a shared lock; writes hold an exclusive lock across the full mutate cycle. OSError tolerance on save is preserved. Adds a concurrent-increment test that reliably reproduced the race (30 threads all stagnating simultaneously → final count was 1 before fix, 30 after). Closes Anantys-oss#1701 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_read_session_pct_and_reset now returns a 3-tuple (session_pct, minutes_until_reset, state) so callers can reuse the already-parsed dict. _maybe_warn_burn_rate unpacks and uses that dict for the session_start comparison instead of issuing a second read_text() call. This removes the window where the run loop could flush a new session start between the two reads, causing an inconsistent comparison that silently suppressed the burn-rate alert for an entire new quota cycle. Also eliminates one redundant file read per iteration when last_warned is set. Closes Anantys-oss#1703 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracted a _read_tail(stdout_file, lines) helper that centralises the seek-to-end / read / size-guard logic. _tail_hash and classify_stagnation now delegate to it. _sample_once reads the larger classification window (100 lines) once per call; on the abort path it derives the hash from the last sample_lines of that same buffer and passes the buffer directly to _classify_from_bytes — eliminating the independent classify_stagnation file open that raced against the still-writing subprocess. Added _classify_from_bytes (extracted from classify_stagnation) and two new tests in TestSingleReadOnAbort that assert exactly one _read_tail call per _sample_once() invocation, including on the abort path. Closes Anantys-oss#1702 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…KILL.md The lite YAML parser doesn't interpret Python unicode escapes, so emoji fields like "\U0001F50E" were rendered as literal text in Telegram. Fix all 4 affected skills (check_need, spec_audit, doc, alias), strip unnecessary quotes from autoreview, and add quote-stripping to _parse_yaml_lite to prevent this bug class. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A complete, useful review that omits a sentinel-defaultable field (review_summary.checklist, file_comments[].code_snippet, finding_ref, or lgtm) was rejected wholesale by validate_review and replaced with the "⚠️ could not be formatted" placeholder — even though the content was perfectly usable. The retry didn't help because the model was consistently terse (observed on esphome/device-builder#1178: two opus passes, no reflection, fallback posted). _normalize_review_data() now fills these unambiguous sentinels in place before validation: checklist→[], code_snippet→"", finding_ref→"", and lgtm derived from finding severities. It deliberately does NOT fabricate semantically meaningful fields (summary, comment, title, severity, line numbers, checklist item/passed) — genuinely incomplete reviews still fail validation and fall back as before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New core skill that takes a PR URL and produces a pedagogical explanation: - What problem the PR solves (with concrete examples) - How the fix works, step by step - The data flow after the change - Whether a simpler approach could have worked Includes handler for Telegram bridge, runner with Claude CLI invocation, dispatch registration with /xp alias, mission dedup support, and 22 tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Headless agent commits (rebase, squash, claudemd refresh) ran target-repo pre-commit hooks. device-builder-frontend's .husky pre-commit runs 'npm run format:check && npm run lint && npm test', which exceeds the 60s git timeout (npm test can also hang on watch mode), raising an unhandled TimeoutExpired that crashes the whole rebase (PR 609). Add --no-verify to commit_if_changes, squash, and claudemd refresh. CI validates the PR; local hooks are not Kōan's gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two fixes for the regression where reviews post duplicate comments: 1. Issue comment self-reply detection: _fetch_issue_comments now collects bot replies and excludes human comments the bot already replied to. Bot replies use "> @user: text..." format — match that quote pattern against human comments to detect prior replies. This is the primary fix for the visible symptom (repeated identical replies). 2. In-progress dedup in _try_assignment_notification: the existing pending-mission check now also scans In Progress, preventing re-queuing while a review is still running. Also adds review cooldown infrastructure to the notification tracker (not yet wired — available for future use if needed). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When re-reviewing a PR after new commits are pushed, the review runner was PATCHing the existing summary comment in-place. GitHub does not send notifications for edited comments, so the reviewer never saw the updated review — it looked like the comment was never posted. Now detects new commits vs prior review SHAs and posts a fresh comment instead. The old review is collapsed to a short "superseded" notice so the PR timeline stays clean. Retries of the same commits (no new code) still skip as before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
|
Retargeted to upstream: Anantys-oss#1736 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
On re-review after new commits, post a new GitHub comment instead of silently PATCHing the existing one.
Why
GitHub does not send notifications when a comment is edited via the API. When the review runner PATCHed the existing summary comment on re-review, the reviewer never received a notification — making it look like the review was never posted. This is the "protection that is too strict" the user observed: the review runs fully but the result is invisible because the PATCH update is silent.
How
run_review(), after the SHA check passes (new commits detected), comparecurrent_shasagainstprior_shas. When they differ and an existing comment exists, force a fresh POST instead of PATCH.Previous review— superseded" notice via_collapse_old_review(), keeping the PR timeline clean.Testing
test_re_review_posts_new_comment_not_patch: verifies fresh POST + old comment collapsetest_same_shas_patches_existing_comment: verifies skip on identical SHAs still worksTestCollapseOldReview: unit tests for the collapse helper (success, failure isolation, missing id)🤖 Generated with Claude Code