Forgejo: comments on agent-opened issues/PRs and replies to the opening post must trigger #82
Labels
No labels
Agent
Ignore
Agent
In Progress
Agent
Planned
Agent
Planning
Agent
Ready
Agent
Triage
Compat
Breaking
Kind
Bug
Kind
Documentation
Kind
Enhancement
Kind
Feature
Kind
Security
Kind
Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
lucas/omp-deck#82
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Trigger
dad12e80-198b-4faa-be10-daee1cf9659cwas dropped as "not addressed to the agent". It was lucas's first comment on PR #79 ("Give me an example for the repo config file"), and the agent (omp-deck) had opened that PR.detectAddressed(apps/server/src/forgejo/conversation-detect.ts) only has three rules: mention, quoted-reply and follows-agent. Thethreadit gets fromdispatcher.tsdetect()islistCommentsonly. As a result:Two rules are needed:
follows-agent,quoted-reply).The hard rules take precedence over the soft one. The "decide from context" steering is only added when no explicit rule matched.
Plan
Approach
Steps 1 and 2 must land together. The new parameter is required, so the dispatcher stops compiling after step 1 until step 2 is done. Step 3 is independent.
1. Detection rules (
apps/server/src/forgejo/conversation-detect.ts)TriggerReasonto"mention" | "edited-mention" | "quoted-reply" | "follows-agent" | "agent-artifact".opening: ThreadComment | nulltodetectAddressed. It is the issue/PR description as a synthetic thread entry; null when the author is unknown.detectAddressed, first match wins:action === "edited"→ unchanged:edited-mentionor null. Edits never use the new rules.mentions(body, agent)→"mention"(unchanged).thread === null→ return null (unchanged; the dispatcher then fetches the thread).const entries = opening ? [opening, ...thread] : thread;and run the existing quoted-reply and follows-agent logic overentriesinstead ofthread. The opening entry has id0, so it is "previous" exactly when no real comment with a lower id exists.if (opening && isAgent(opening)) return "agent-artifact";detectAddressed:openingis the description as entry 0, andagent-artifactis the soft last-resort rule for artifacts the agent authored.REASON_TEXT:"agent-artifact": "a comment on an issue or pull request you opened".buildConversationSeed, whent.reason === "agent-artifact", append these lines after the fenced comment body: For every other reason the seed is unchanged.2. Dispatcher wiring (
apps/server/src/forgejo/dispatcher.tsdetect(), around line 618)openingfrom the webhook payload'sissuefield. Comment payloads on PRs also carryissue;gate()already readspayload.issue?.user?.loginfor them at line 333. Changedetect's parameter type fromPayloadFieldstoPayload(both are defined in the same file) so it can readpayload.issue. The call site at line 309 already passes aPayload.openingininput, so bothdetectAddressedcalls (explicit withthread: null, and with the fetched thread) receive it. Leavejob.thread = thread.dataas is: the seed and other consumers keep the real comments only, without the synthetic entry.if (explicit !== null || action === "edited") return explicit;stays. Agent-artifact comments always fetch the thread, because the hard rules have to be checked first.runReady,buildConversationSeedalready receives everyTriggerReason, so it needs no change. Permission and workspace gates are unchanged.3. Implementer policy wording (
apps/server/src/bridge/session-policy.ts,forgejo_implementersystemContext,rulesarray around line 323)rules:"- Comments on the issue or pull request arrive as turns. If one is not addressed to you, end the turn without posting. If you cannot tell, ask in a reply."rulesarray is shared by both the PR-started and the issue-started branches, so both get the line. The conversation and pull-request policies already have the equivalent line and stay unchanged.Critical files & anchors
apps/server/src/forgejo/conversation-detect.ts:TriggerReason,detectAddressed,REASON_TEXT,buildConversationSeed.apps/server/src/forgejo/dispatcher.ts:detect()(around line 618) and thePayloadFields/Payloadtypes (lines 105–112).apps/server/src/bridge/session-policy.ts: implementersystemContextrules.apps/server/src/forgejo/conversation-detect.test.ts(baseat line 33 needsopening: null),apps/server/src/forgejo/dispatcher.test.ts(theenqueuehelper at line 325 already has anissueAuthoroption; add an optionalissueBody→issue.body).Verification
Run from
apps/server.Add to
conversation-detect.test.ts(detectAddressed). Addopening: nulltobaseso the existing cases still compile and pass unchanged:opening = comment(0, AGENT, "desc")with an empty thread and body "Give me an example" →"follows-agent". This is the PR #79 case: the description counts as the previous entry.openingauthored by the agent, thread[comment(5, "alice", "q")], body "@carol thoughts?" (comment id 10) →"agent-artifact".openingauthored by"carol", thread[comment(5, "alice", "q")]→null. A human-authored artifact without agent involvement still drops.opening = comment(0, AGENT, "The parser lives in repo.ts")with body "> the parser lives in repo.ts\n\nwhy?" and thread[comment(5, "alice", "x")]→"quoted-reply".null.buildConversationSeedwithreason: "agent-artifact"contains "Participants may be talking to each other"; withreason: "mention"it does not.Add to
dispatcher.test.ts:enqueue({ isPull: true, number: 9, issueAuthor: AGENT, body: "just chatting" }), withh.api.threads.set(9, [{ id: 1, author: "bob", body: "hi", createdAt: "" }])and the same agent-PR fixtures as the existing test at line 455 (h.api.pulletc.) → the trigger runs (not dropped) and the prompted seed contains "Participants may be talking to each other".issueAuthordefaults tocarol.Commands:
bun test src/forgejo src/bridge, thenbun run typecheckinapps/server. Theapps/webtypecheck is also needed if it importsTriggerReason; currently nothing outsideapps/server/src/forgejomatches the reason strings.