Skip to content

feat: maintainer command protocol and marker-backed status comments (#13) - #39

Merged
BunsDev merged 6 commits into
mainfrom
feat/issue-13-commands
Jul 7, 2026
Merged

feat: maintainer command protocol and marker-backed status comments (#13)#39
BunsDev merged 6 commits into
mainfrom
feat/issue-13-commands

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 6, 2026

Copy link
Copy Markdown
Member

Closes #13.

What ships

  • Typed command parser (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).
  • Command routing: fix → FixIssue (issue) / AddressReviewComment (PR); review/deepen/retry → ReviewPullRequest with command:<verb> reasons (deepen widens the review audit instruction); cancel tombstones queued PR reviews via the supersession registry and acknowledges (in-flight work is a documented limitation); status answers from the task store; remember/forget are parsed as typed intents and acknowledged as pending memory governance (Define hosted memory governance contract between coven-github and coven-code #6).
  • Permission gate: command-initiated tasks carry commander; the worker checks GET /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. status is open.
  • Marker-backed status comments: every worker comment funnels through 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).
  • Adapter-only TaskKind::CommandReply executed without spawning coven-code; Task.commander: Option<String> (serde-default); ReviewPullRequest drops 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

BunsDev added 6 commits July 6, 2026 17:32
…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>
Copilot AI review requested due to automatic review settings July 6, 2026 22:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 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 thread README.md
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.
@BunsDev
BunsDev merged commit 2de2411 into main Jul 7, 2026
2 checks passed
@BunsDev
BunsDev deleted the feat/issue-13-commands branch July 7, 2026 00:54
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.

Add marker-backed comments and maintainer command protocol

2 participants