feat: maintainer command protocol and marker-backed status comments (#13) - #39
Merged
Conversation
…okup (#13) Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Task gains an optional commander login for permission gating; CommandReply is a new adapter-only kind executed without spawning coven-code; ReviewPullRequest drops its write-only event-time ref fields — supersession plus live ref resolution already own correctness, and command-created reviews have no refs at parse time. Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Comment surfaces now speak the command protocol: only command-position mentions act, casual mentions are ignored, and unknown verbs earn a clarification reply. cancel tombstones queued PR reviews via the supersession registry; status answers from the task store; remember/forget acknowledge and defer to the memory governance contract (#6). Signed-off-by: Val Alexander <bunsthedev@gmail.com>
All worker comments funnel through a single marker-backed status surface per target, edited in place through the lifecycle (working / done+links / needs input / failed / declined). CommandReply tasks execute adapter-side with no coven-code session or Check Run. Command-initiated work is permission-gated: commanders below write access are declined on the status surface before any work is spent. A deepen command widens the review audit instruction. Signed-off-by: Val Alexander <bunsthedev@gmail.com>
…13) Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds an explicit maintainer command grammar to the webhook routing layer and introduces marker-backed, edited-in-place status comments in the worker, aligning the adapter with issue #13’s goal of durable, low-noise GitHub surfaces.
Changes:
- Implemented a typed maintainer command parser (
@familiar <verb>) and routed commands into work tasks vs. adapter-only replies. - Added marker-backed status comment upsert logic so task lifecycle updates edit a single comment per issue/PR instead of posting duplicates.
- Added a worker-side collaborator permission gate for command-initiated work tasks (via the collaborators permission endpoint).
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents the maintainer command grammar and marker-backed status comment behavior. |
| crates/worker/src/status_comment.rs | Introduces marker generation + upsert logic for marker-backed status comments. |
| crates/worker/src/lib.rs | Integrates status comment upserts, adds permission-gated preflight, and adds adapter-only CommandReply handling. |
| crates/worker/src/brief.rs | Adds a safe fallback brief mapping for TaskKind::CommandReply. |
| crates/webhook/src/routes.rs | Replaces substring mention triggers with typed command parsing and command→task routing (incl. status/cancel/retry/etc.). |
| crates/webhook/src/lib.rs | Exposes the new commands module. |
| crates/webhook/src/events.rs | Enriches parsed events with issue/PR titles/bodies needed for command-driven task creation. |
| crates/webhook/src/commands.rs | Implements the transport-independent command parser and mention classification. |
| crates/github/src/tasks.rs | Extends task listing to represent CommandReply items. |
| crates/github/src/repo.rs | Adds collaborator permission lookup used by the worker’s permission gate. |
| crates/github/src/pr.rs | Adds list/update comment APIs used for marker-backed comment upserts. |
| crates/github/src/lib.rs | Extends event/task structs with commander metadata and adds TaskKind::CommandReply. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+382
to
+395
| Command::Cancel if s.on_pull_request => { | ||
| // Tombstone queued reviews for this PR. In-flight work is not | ||
| // interrupted (documented limitation); the next review command or | ||
| // PR event re-arms the lane. | ||
| state | ||
| .task_store | ||
| .register_pr_review(&repo, s.number, &format!("cancelled:{}", uuid::Uuid::new_v4())) | ||
| .await; | ||
| reply(format!( | ||
| "Cancelled queued reviews for PR #{}. Work already running will finish; `@{} review` re-arms the lane.", | ||
| s.number, | ||
| familiar.bot_username.trim_end_matches("[bot]") | ||
| )) | ||
| } |
Comment on lines
+29
to
+46
| let full = format!("{marker}\n{body}"); | ||
| let comments = | ||
| pr::list_comments_with_base_url(api_base_url, token, repo_owner, repo_name, number) | ||
| .await?; | ||
| if let Some(existing) = comments.iter().find(|c| c.body.contains(marker)) { | ||
| pr::update_comment_with_base_url( | ||
| api_base_url, | ||
| token, | ||
| repo_owner, | ||
| repo_name, | ||
| existing.id, | ||
| &full, | ||
| ) | ||
| .await | ||
| } else { | ||
| pr::post_comment_with_base_url(api_base_url, token, repo_owner, repo_name, number, &full) | ||
| .await | ||
| } |
Comment on lines
+114
to
+119
| A mention only acts when it is the **first token of the comment**, followed by a | ||
| command verb — `@cody review`, `@cody fix: the lint is failing`. Casual | ||
| mentions mid-sentence trigger nothing, and an unknown verb in command position | ||
| gets a clarification reply instead of launching work. Every command except | ||
| `status` requires **write access** to the repository; the familiar's own | ||
| comments never re-trigger it. |
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.
Closes #13.
What ships
crates/webhook/src/commands.rs, transport-independent): a mention acts only as the comment's first token followed by a verb —review,fix/fix:,deepen,retry,cancel,remember,forget,status. Unknown verbs in command position get a clarification reply listing commands; casual mid-sentence mentions trigger nothing. Self-comments never re-trigger (kept).fix→ FixIssue (issue) / AddressReviewComment (PR);review/deepen/retry→ ReviewPullRequest withcommand:<verb>reasons (deepenwidens the review audit instruction);canceltombstones queued PR reviews via the supersession registry and acknowledges (in-flight work is a documented limitation);statusanswers from the task store;remember/forgetare parsed as typed intents and acknowledged as pending memory governance (Define hosted memory governance contract between coven-github and coven-code #6).commander; the worker checksGET /collaborators/{u}/permission(metadata scope) pre-flight and declines below write access on the status surface — no Check Run, no session, no task-store entry.statusis open.status_comment::upsert— one<!-- coven:{familiar}:{owner}/{repo}#{n} -->surface per target, edited in place through the lifecycle (working → done with PR/Check/Cave links / needs input / failed / declined). PR-scoped tasks get the surface too (they previously got no comments). Threads past 100 comments fall back to posting fresh (documented).TaskKind::CommandReplyexecuted without spawning coven-code;Task.commander: Option<String>(serde-default);ReviewPullRequestdrops its write-only event-time ref fields.Deliberate behavior change
Plain conversational mentions (
@cody can you take a look?) no longer create tasks — this is the issue's stated intent ("bot behavior can be triggered by ambiguous or accidental mentions").@cody <anything-unrecognized>at the start of a comment gets a safe clarification; a mention mid-text is ignored. README documents the grammar.Out of scope
Memory command execution (#6) · advisory/blocking publication gates (#11) · in-flight task cancellation (needs a process-handle registry — follow-up).
Plan and grooming trail: #13 (comment)
Local gates:
cargo check --all-targets+cargo clippy --all-targets -- -D warnings+cargo test --all(134 passed, 0 failed).🤖 Generated with Claude Code