fix(platform): gate the task-comment automation trigger on the author - #3195
Merged
Merged
Conversation
Two 0.4 behaviours the 0.5 port dropped from the task-comment path. An agent- or workflow-authored comment could start the task's owning automation. 0.4 called the trigger from one place — `applyUserTaskComment`, the single write path for a USER comment — while the agent door hard-coded `actorType: 'agent'` and never reached it. 0.5 merged both lanes into one `addTaskComment`, and `maybeTriggerOwningAutomation` ran unconditionally with no author type to check. The result is a self-sustaining loop: the automation comments, the comment restarts the automation, and every iteration is a metered agent turn. `startWorkflowForTask`'s duplicate guard does not catch it — one live run per (automation, task) blocks a concurrent second start, not a sequential loop. The trigger now takes the author type and returns early unless it is `user`, mirroring the agent lane's `dispatchMentionedProjectAgent` gate right below it in the same file. Editing a comment never re-resolved its mentions: `editTaskComment` wrote only `edited_at_ms`, so editing a comment to add `@someone` notified nobody and the stored mention set went stale. It now re-resolves through `resolveSurfaceMentions` and diffs with `addedMentions` — which had survived the port with no production caller — patching the full set onto the meta row and fanning out the ADDED mentions only, as the bell plus `comment.mentioned` with no subscriber re-alert. Rewording prose around an existing `@handle` still notifies nobody. Editing starts no engine. Both are probed in the real-Postgres integration check, each seen red against deliberately broken code: dropping the author gate enqueues a `task.start_workflow` job for the agent-authored comment; reverting the edit path notifies nobody and leaves the stored set stale; fanning out the full set instead of the added ones gives the already-mentioned teammate a second bell. Task DESCRIPTION mentions (`updateTask`) stay PENDING — a separate decision.
Israeltheminer
force-pushed
the
fix/gate-comment-automation-trigger-v2
branch
from
September 4, 2026 09:01
e7072a4 to
dd9e744
Compare
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.
An agent- or workflow-authored comment naming the automation that owns its
task restarted the engine that wrote it. The automation writes a comment, the
comment starts the automation, and round it goes — a sequential loop of
metered agent turns against the organization's own provider keys.
The one-live-run guard does not stop this. It blocks a concurrent second
start, not a later one, and each turn here begins after the last has finished.
Rebase of #3146 onto current main, plus the coverage the original lacked.
Why 0.5 has the bug and 0.4 did not
0.4 reached the trigger from
applyUserTaskCommentalone, so a non-humanauthor could never get there. 0.5 merged the user and agent doors into one
addTaskComment, and the trigger was ported without the author check thatthe old entry point had provided implicitly.
The rule is now named —
commentCanStartAutomation— rather than left as abare
!== 'user'mid-function, because the reason it exists is not obviousfrom the line.
editTaskComment re-resolves mentions
Second dropped behaviour in the same file: editing a comment wrote only
edited_at_ms, so adding@someoneto an existing comment notified nobodyand the stored mention set went stale. The fan-out is
addedMentionsonly,never the full set, so an edit that touches nothing re-notifies nobody.
The coverage is new
I mutation-tested the original and dropping the gate broke nothing in CI —
its only proof was the
integration-check.tslane, which needs a live stack.gates the trigger on the rulesystemrefuses agent,refuses workflow,refuses apiauthorTypeto'user'threads the comment author into the trigger callThat third one matters: two call sites pass
authorType, so the assertion isscoped to the trigger's. Hard-coding it would leave the gate in place and
disable it.
The rule is asserted directly and the wiring by reading the source. Driving
this through
addTaskCommentwould need ten mocked collaborators, and thatscaffold would break on the next refactor without the rule ever changing —
the end-to-end lane stays in the harness.
MIGRATION.md
The
collabrow gains a note on both behaviours. Verified additive: the row'scontent is main's verbatim plus 729 characters (the raw line is shorter only
because the table's trailing space padding went with it).
Gate
typecheck0 errors,oxlint --type-awareclean,oxfmt --checkclean,tasks suites 111 passed (13 files).