feat(crew): detect human comments on vault issues via agent comment signing - #625
Merged
Merged
Conversation
…igning Crew agents post through `gh` with David's credentials, so agent comments and David's replies share an author. Ralph's scan covers issues, PRs, labels and checks but not comments, so a reply from David was invisible — on #84 six answers, two overturning crew recommendations, went unnoticed until he asked. Establishes the marker convention (`<!-- crew:agent={member} -->` on every agent-posted comment, making anything unmarked human by definition), the `seen=` acknowledgement as the durable per-issue high-water mark, a single GraphQL scan replacing the O(open issues) loop, and a `commentWatch.since` adoption cutoff so the 13 unmarked pre-convention comments are not reported as human on first run. Closes #105 (david-driscoll/vault) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Comprehensibility | 1 minor |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
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.
Implements david-driscoll/vault#105 — Ralph should detect new human comments on vault issues.
The problem
Crew agents post through
ghwith David's credentials, so every comment indavid-driscoll/vaultis authored bydavid-driscoll— agent reports and David's own replies alike. Author is not a discriminator, and style heuristics ("agents open with##and run long") break the first time either party writes atypically.Ralph's scan covers issues, PRs, labels, checks and alerts — not comments. So a reply from David is the one work signal that goes undetected. On #84 he answered six questions, two of which overturned crew recommendations, and it was only picked up because he asked for it explicitly.
Did crew already have a convention?
No. Checked
.crew/, the coordinator protocol, and a fresh clone ofBlacklite/crew. The onlycrew:-namespaced HTML comments are<!-- crew:begin -->/<!-- crew:end -->(the CLAUDE.md managed block) and<!-- version: X -->(stamped at install). Nothing marks agent-authored comments. The new marker slots into that existing namespace rather than opening a second one.Where the rule went — upstream, not here
.crew/templates/ralph-reference.mdis byte-identical toBlacklite/crew's shippedtemplates/ralph-reference.md, andcrew upgradecallsrefreshCrewTemplatesDir(), which overwrites all of.crew/templates/and regenerates.github/agents/crew.agent.mdfromcrew.agent.md.template. Editing either locally gets silently reverted — worse than not doing it, because it would look done.So the convention is proposed upstream in Blacklite/crew#3 (canonical
.crew-templates/, mirrors synced, changeset included), which is where every agent in every crew actually picks it up.This PR is the repo-local operative copy — it keeps the behaviour live in the window before that lands, and afterwards shrinks to the estate-specific parts that never belonged upstream: the tracker, the adoption cutoff, the scope decisions.
What lands here
.crew/comment-watch.md.crew/config.jsoncommentWatchblock — tracker,sincecutoff, scope. Operator config;crew upgradereads it and never rewrites it.crew/routing.mdCLAUDE.mdcrew:begin/endblock, so it survivescrew initThe mechanism
<!-- crew:agent={member} -->on the last line of every agent-posted comment. Anything unmarked is a human comment by definition — agents never have to recognise a human, only themselves, which they can do exactly.High-water mark
{issue, createdAt}setseen=on agent comments, in the threadcommentWatch.sinceThe durable mark is deliberately not a file under
.crew/. This estate runs agents in worktrees, in Actions, and on more than one machine — a local state file is wrong in all three the moment two run, and it would be a mutable, merge-conflicting copy of something GitHub already stores. In the thread, the thread is self-describing.A marked comment without
seen=does not advance the mark: a status update posted while a question is outstanding must not silence it. Unanswered human comments keep surfacing until someone answers. The nagging is the point.Retroactive marking — the issue doesn't cover this, and it decides the first run
Every pre-convention comment is unmarked. Measured, not assumed: the live tracker had 13 comments across 7 open issues, 0 marked. Without a floor, run one reports all 13 as new human comments.
commentWatch.sinceis the floor. A back-fill — editing 13 historical comments in David's own threads — mutates the record to fix a tooling problem, so it was rejected.The floor loses nothing here, because a one-time sweep was done as part of this change. Three of the 13 are genuine David replies, and all three were already answered:
2026-07-29T02:37:39Z"A lot of rework is in order…"2026-07-29T03:06:23ZQ-A…Q-F answers2026-07-29T02:47:41Z"Lets fix the upstream bugs…"If this sits before merging, re-set
sinceto the merge time — agent comments posted in the gap would be unmarked and past the floor, the one window a false alert is possible.Scan shape
One GraphQL request for the whole tracker. The per-issue shape sketched in #105 works, but it is O(open issues) requests per cycle and Ralph cycles continuously — ~11 calls a cycle for data that fits in one.
first: 50issues ×last: 30comments covers this tracker; page viapageInforather than raising the bounds, since the node budget is their product.Verification — against #105's own regression case
The issue supplies five interleaved comments across #84, #81, #94, #95 where agent and human alternate under one author. Built as a fixture from the real bodies (nothing posted to real issues):
seen=acksCaveat, stated plainly: the historical comments cannot be discriminated, because they predate the marker — all 13 live comments come back unmarked. That is the retroactive problem above, handled by the cutoff, not a failure of the mechanism. Discrimination is verified on the same comments with markers applied as the convention prescribes.
Scope beyond vault — recommendation, not assumption
#105 asks whether PR review comments in the four code repos deserve the same treatment. Yes, but not with this mechanism, and as a separate issue.
Ralph already sees
CHANGES_REQUESTEDandAPPROVEDviareviewDecision. What it misses is aCOMMENTEDreview and unresolved inline threads — confirmed on live open PRs, which reportreviewDecision: nulldespite review activity.The marker machinery is the wrong tool there: GitHub already provides the high-water mark.
reviewThreads(first:N) { isResolved }— an unresolved thread is outstanding work, tracked natively, no cutoff, noseen=, no retroactive problem. The right shape is a Ralph category keyed onisResolved == falseplusreviews(states:[COMMENTED])across all four repos. Signing still applies to PR comments; PR-side detection should be built on resolution state.Acceptance (vault#105)
seen=across sessionscrew:{member}, with a mandatory supersession checkCloses david-driscoll/vault#105
🤖 Generated with Claude Code