feat(forgejo): let conversation sessions relabel their own issue #242

Merged
lucas merged 1 commit from agent/issue-241-conversation-labels into main 2026-11-09 15:04:15 +01:00
Collaborator

Gives every forgejo_conversation session (@mention turns and triage turns alike) forgejo_update_issue_labels, scoped to the issue or PR the session is about, with the repository's automation-steering labels off limits.

What changed

  • CONVERSATION_TOOL_NAMES gains forgejo_update_issue_labels; the no-checkout variant inherits it (labeling needs no checkout). The CI watchdog filter excludes it, so its "You cannot change code, branches, labels or issue state" prompt stays true.
  • forgejoConversationPolicy.decide is now async and uses the api/signal parameters it previously dropped. The tool is "allow"ed (not "default") so the mutating-tool default ask does not become an unattended denial; user deny rules still win, since PermissionFilter checks them first.
  • Denials: a number other than the session's, and any added/removed label matching (under sameLabel) Status/Blocked, issue_handler.label, the three implementation labels, review.label/exclude_labels or the CI-watchdog others-PRs label/excludes from .omp/forgejo.yaml. The config is read live per call (as everywhere else in the dispatcher) so edits apply without a restart. When it cannot be read or parsed, the fallback protects Status/Blocked and the agent/ namespace and allows everything else.
  • BLOCKED_LABEL moved from dispatcher.ts to repo-config.ts; session-policy.ts importing dispatcher.ts would be a cycle, repo-config.ts is cycle-free.
  • System prompt and docs/configuration.md describe the new, narrower capability.

The built-in triage task text in conversation-detect.ts is deliberately unchanged: the default steering stays passive, and a repository opts into labeling via issue_handler.prompt, which replaces that text.

Verification

  • bun test apps/server/src/bridge/session-policy.test.ts apps/server/src/forgejo/dispatcher.test.ts — 208 pass, 0 fail, including the new cases (own-number-only, configured automation labels incl. needs triage ↔ needs-triage normalization, Status/Blocked with a label-less config, unreadable-config fallback where agentic-ux is allowed but agent/anything is not, and agent/ not applying when the config was read).
  • bun run typecheck — clean.

Closes: #241

Gives every `forgejo_conversation` session (@mention turns and triage turns alike) `forgejo_update_issue_labels`, scoped to the issue or PR the session is about, with the repository's automation-steering labels off limits. ## What changed - `CONVERSATION_TOOL_NAMES` gains `forgejo_update_issue_labels`; the no-checkout variant inherits it (labeling needs no checkout). The CI watchdog filter excludes it, so its "You cannot change code, branches, labels or issue state" prompt stays true. - `forgejoConversationPolicy.decide` is now `async` and uses the `api`/`signal` parameters it previously dropped. The tool is `"allow"`ed (not `"default"`) so the mutating-tool default ask does not become an unattended denial; user *deny* rules still win, since `PermissionFilter` checks them first. - Denials: a `number` other than the session's, and any added/removed label matching (under `sameLabel`) `Status/Blocked`, `issue_handler.label`, the three `implementation` labels, `review.label`/`exclude_labels` or the CI-watchdog others-PRs label/excludes from `.omp/forgejo.yaml`. The config is read live per call (as everywhere else in the dispatcher) so edits apply without a restart. When it cannot be read or parsed, the fallback protects `Status/Blocked` and the `agent/` namespace and allows everything else. - `BLOCKED_LABEL` moved from `dispatcher.ts` to `repo-config.ts`; `session-policy.ts` importing `dispatcher.ts` would be a cycle, `repo-config.ts` is cycle-free. - System prompt and `docs/configuration.md` describe the new, narrower capability. The built-in triage task text in `conversation-detect.ts` is deliberately unchanged: the default steering stays passive, and a repository opts into labeling via `issue_handler.prompt`, which replaces that text. ## Verification - `bun test apps/server/src/bridge/session-policy.test.ts apps/server/src/forgejo/dispatcher.test.ts` — 208 pass, 0 fail, including the new cases (own-number-only, configured automation labels incl. `needs triage` ↔ `needs-triage` normalization, `Status/Blocked` with a label-less config, unreadable-config fallback where `agentic-ux` is allowed but `agent/anything` is not, and `agent/` *not* applying when the config was read). - `bun run typecheck` — clean. Closes: #241
Unattended Forgejo conversation sessions — including triage turns steered
by `issue_handler.prompt`, which the docs advertise as a labeling task —
had no label tool at all.

Add `forgejo_update_issue_labels` to the conversation tool surface (the
no-checkout variant picks it up, labeling needs no checkout) and keep it
off the CI watchdog, whose prompt still promises it cannot change labels.
The policy allows it only on the session's own issue or PR, and refuses
any label the repository's automation keys on: the issue-handler,
implementation, review and CI-watchdog labels from `.omp/forgejo.yaml`,
read live, plus `Status/Blocked`. When the config cannot be read, only
`Status/Blocked` and the `agent/` namespace stay protected.

`BLOCKED_LABEL` moves from `dispatcher.ts` to `repo-config.ts` so the
policy can share it without an import cycle.

Co-Authored-By: Claude Opus 5 via omp-deck
lucas merged commit fe00acefee into main 2026-11-09 15:04:15 +01:00
lucas deleted branch agent/issue-241-conversation-labels 2026-11-09 15:04:15 +01:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
lucas/omp-deck!242
No description provided.