Make Gitea MCP task routing role-aware instead of launcher-profile dependent #139
Closed
opened 2026-07-05 01:19:28 -05:00 by jcwalker3
·
10 comments
No Branch/Tag Specified
master
fix/issue-709-decision-lock-cross-profile
fix/issue-695-native-transport-quarantine
fix/issue-698-report-validator-schema
fix/issue-702-stale-binding-lease-recovery
fix/issue-699-structured-auth-mcp-errors
fix/issue-695-native-quarantine-v2
fix/issue-693-review-decision-lock-recovery
fix/issue-691-obsolete-reviewer-lease-cleanup
feat/issue-687-reconciler-branch-delete
fix/issue-683-workflow-guard-hardening
chore/issue-681-preserve-review-session-wip
feat/issue-604-anti-stomp-preflight
feat/issue-606-sentry-observability
fix/issue-671-block-stable-branch-push
fix/issue-675-residual-preflight-remediation
fix/issue-673-remediate-regressions-part2
fix/issue-673-remediate-regressions
feat/issue-603-lifecycle-labels
fix/issue-627-set-issue-labels-pagination
feat/issue-601-first-class-leases
feat/issue-612-incident-bridge
feat/issue-600-controller-allocator-api
fix/issue-620-head-scoped-review-locks
feat/issue-613-allocator-db-substrate
docs/mcp-stable-control-runtime-policy
feat/issue-609-prepared-review-verdict-resume
feat/issue-610-live-remote-parity
feat/issue-503-reviewer-active-worktree
feat/issue-470-preflight-contract
feat/issue-440-lock-recovery
feat/issue-440-branch-recovery
feat/issue-458-queue-fail-closed-copy
feat/issue-400-early-duplicate-work-gate
feat/issue-308-reconcile-inventory-pagination
feat/issue-308-reconcile-pagination-proof
docs/issue-261-agent-temp-artifact-cleanup
feat/issue-262-map-commit-files
fix/infra-stop-conflict-marker-false-positive
feat/issue-139-role-aware-task-routing
feat/issue-188-continuation-selection-wall
feat/issue-189-continuation-mode-proofs
feat/issue-232-refresh-wiki-proof-heads
feat/issue-210-block-workspace-edits
feat/issue-204-exact-issue-lock
docs/issue-80-label-taxonomy
docs/issue-79-safety-boundary-updates
v1.1.0
Labels
Clear labels
allocator
anti-stomp
architecture
bug
chore
codex
concurrency
contamination
control-plane
dashboard
database
design
documentation
enhancement
gitea
glitchtip
important
incident
incident-bridge
integration
jenkins
labels
leases
mcp
mcp-health
mcp-menu
multi-project
mutating
nice-to-have
observability
portability
preflight
protected-branch
queue
read-only
reconnect
recovery
refactor
release
reliability
resumable-review
reviewer
roadmap
safety
security
self-hosted
sentry
stale-runtime
status:blocked
status:in-progress
status:pr-open
status:ready
terminal-lock
testing
tracker
type:bug
type:feature
type:feature
type:guardrail
visibility
workflow
workflow-hardening
workflow-hardening
Controller-owned work allocator
Prevent concurrent LLM session stomping
Architecture / structural design
OpenAI Codex client / workflow session surface
Concurrent session safety
Workflow or session contamination incident
MCP control-plane coordination and allocation authority
MCP operational dashboard/queue view
Internal coordination storage (SQLite/Postgres)
Design / investigation, no implementation
Docs / runbooks
New feature or improvement
Gitea MCP workflow
GlitchTip integration
Operational or process incident requiring durable audit trail
Sentry-to-Gitea incident bridging
Integration testing
Jenkins integration
Label taxonomy management
Lease adopt/release/expire lifecycle
MCP server / tooling
MCP namespace and runtime health
MCP menu surface
Work spanning multiple monitoring projects or Gitea repos
Mutating action; requires gating
Observability, metrics, traces, error reporting
Cross-platform / portability
Shared preflight gates before mutation
Protected branch / stable-branch policy concern
Work queue visibility and allocation
Read-only, no mutation
MCP client reconnect/reload recovery path
Recovery paths for stale/foreign leases
Code refactor / restructure
Release / versioning
Reliability / failure handling
Persist and resume prepared review verdicts across sessions
Reviewer workflow tooling
Roadmap / umbrella issue
Safety rails and fail-closed mutation guards
Security / trust boundary
Self-hosted infrastructure integration
Sentry error monitoring integration
Stale backend daemon / runtime-vs-master parity failures
Issue is blocked
Issue is being worked on
Issue has an open pull request
Issue is ready for work
Terminal review lock (#332) path
Tests / test coverage
Issue tracker hygiene / meta
Bug or defect
Feature or enhancement
Feature or enhancement
Safety gate or guardrail
Workflow state visibility for LLMs/operators
Cross-tool workflow
LLM workflow coordination hardening
LLM workflow coordination hardening
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Scaled-Tech-Consulting/Gitea-Tools#139
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
LLM operators are being asked to perform different Gitea tasks — create issues, comment on discussions, implement issues, review PRs, merge PRs — but the active MCP session is often pinned to a static launcher profile such as
prgs-author.This causes repeated failures where the LLM is asked to review or comment, but the connected MCP server only exposes author permissions. The LLM then stops at the identity gate, which is safe, but the workflow breaks.
The MCP should be agnostic to the LLM. The user should be able to ask for a task, and the MCP layer should determine the required role/capability and either execute through the correct configured profile or clearly report the missing profile/capability.
Current failure examples
Review request fails because the active MCP session is pinned to:
jcwalker3prgs-authorIssue discussion comment requests fail because both author and reviewer profiles lack:
gitea.issue.commentLLMs have to reason about launcher config, static-profile mode, namespace names, and profile switching instead of simply using task-appropriate tools.
Goal
Make Gitea MCP task execution role-aware and capability-aware so LLMs can do the requested work safely without hardcoding identities or relying on prompt-specific profile guesses.
Desired behavior
gitea.issue.comment.Requirements
1. Add a role/capability resolver
The resolver should answer:
2. Add or improve a runtime context tool
The runtime context should clearly report:
3. Add a task-routing guide or helper
Possible tool names:
gitea_resolve_task_capabilitygitea_get_required_profile_for_taskgitea_route_taskgitea_get_runtime_contextFor example:
Input:
review_prmcp-control-plane52Output:
gitea.pr.approveprgs-authorprgs-reviewergitea-revieweror relaunch server withGITEA_MCP_PROFILE=prgs-reviewer4. Do not weaken gates
This must not allow:
5. Fix issue-comment workflow capability
Ensure the profile model can support:
gitea.issue.commentAnd make it clear that:
gitea.pr.commentdoes not implygitea.issue.commentgitea.issue.comment6. Support either official profile model
The issue should decide and document one of these safe models:
Option A — Dual namespace model:
gitea-authorgitea-reviewerOption B — Dynamic profile model:
Option C — Dispatcher model:
Preferred direction:
7. Improve error messages
When an operation fails due to permissions, return:
Example:
8. Update docs and guide tools
Update:
Docs must say:
9. Tests
Add tests for:
gitea.issue.commentcan commentgitea.issue.commentfails closedAcceptance criteria
gitea.issue.commentis available.Hard rules
gitea.pr.commentimplygitea.issue.comment.Implementation note: this should be treated as a routing/capability-resolution problem, not a prompt convention problem.
The resolver should keep
gitea.pr.commentandgitea.issue.commentseparate, report the active profile and required capability, and return an actionable next step when the connected namespace cannot perform the task. Review/merge gates should remain fail-closed, including self-review/self-merge protection and no author-profile approval or merge permissions.Independent design review — Claude (Fable 5) operator session, 2026-07-05
Posting status
gitea_create_issue_comment(gated ongitea.issue.comment, per #126/#137)jcwalker3/prgs-author(verified viagitea_whoami)Recommended model
gitea-author,gitea-reviewer) keep exactly one credential per process and make self-review structurally hard — that trust boundary is the project's strongest gate and should not be traded for convenience. Dynamic in-process switching means one process holds or can obtain both credentials, muddies audit attribution, and turns "which identity am I?" into mutable state an injected instruction could target. A dispatcher concentrates the same problem in one front door. The real pain today is not switching — it is discoverability: sessions burn turns learning which role a task needs. That is solvable read-only, with zero new write capability: tell the LLM what the task requires and the exact safe next action.gitea_get_runtime_context(#131) already proves the pattern (review_merge_allowed,blocked_reasons,safe_next_action).Role/capability resolver recommendation
gitea_resolve_task_capability(keepgitea_get_runtime_contextas-is; the resolver is per-task)task,required_operation,required_role_kind(author/reviewer/operator),active_profile,active_identity,active_can_perform(bool + reasons),matching_profiles(profile names only — never auth references),runtime_switching_supported(false today),requires_other_namespace(bool + which),safe_next_action(template-generated, one sentence). Read-only; fail-closed on unknown task names, returning the valid task list.Task → capability map the resolver should encode: create issue →
gitea.issue.create(author); comment on issue →gitea.issue.comment(author or reviewer); claim issue → issue-label edit (author); create branch / push branch / open PR →gitea.branch.create/gitea.branch.push/gitea.pr.create(author); review PR →gitea.pr.approve/gitea.pr.request_changes(reviewer, non-author, pinned head); merge PR →gitea.pr.merge(reviewer + eligibility +MERGE PR <n>confirmation); close stale PR / close issue → reviewer/operator; trigger Jenkins → dedicated trigger identity only, per mcp-control-plane #4 (never author/reader); file GlitchTip finding into Gitea → author-sidegitea.issue.createcomposed with read-onlyglitchtip.read(the #6 orchestrator boundary).Issue-comment permission recommendation
prgs-authorhavegitea.issue.comment: yes (claim notes, audit findings, decision summaries are author-side work)prgs-reviewerhavegitea.issue.comment: yes (review findings and discussion verdicts belong on threads)gitea.issue.commentmust not implygitea.issue.close/reopen;gitea.pr.commentmust not implygitea.issue.comment(different surfaces, different abuse paths — keep the #126 separation); comment grants must not movegitea.pr.approve/merge(author) orgitea.branch.push/gitea.repo.commit(reviewer) in either direction. Tests: both-role success when configured; fail-closed without the op; explicit non-implication tests for close/review/merge/push/commit; error-message clarity. (#137/PR #138 is exactly this first increment — right call.)Error-message / runtime-context recommendation
active_identity,active_profile,missing_operation,required_operation,matching_profiles(names only),runtime_switching_supported,requires_other_namespace, and one template-generatedoperator_actionsentence (e.g. "Run this task in the gitea-reviewer namespace, or ask the operator to update the profile"). Never echo caller-supplied values into errors (metadata-is-data, mcp-control-plane #29); never include endpoint URLs, keychain IDs, or auth references. Today's "profile is not allowed to gitea.issue.comment" states what but not what next — the delta is the last four fields.Safety invariants
whoami, regardless of profile claims.Suggested implementation issues
gitea.issue.commentfor author/reviewer with separation tests; residual operator step: update live profiles config + reconnect MCP.gitea_resolve_task_capabilityread-only resolver (task→operation→role map,active_can_perform,safe_next_action).gitea-author/gitea-reviewerlauncher config + docs) so "wrong role" errors always name the other namespace.Risks / tradeoffs
safe_next_actionshould say so rather than pretend a namespace hop is sufficient.Final recommendation
Adopt the hybrid: keep static per-role namespaces as the only credential model; land the #137 unblock everywhere it applies (repo code merged — the live profile config update + MCP reload is the remaining operator step); add
gitea_resolve_task_capabilityplus structured block-report errors next; document dual-namespace deployment as the standard; and explicitly reject dynamic switching and the dispatcher until a concrete need survives design review. This turns "safe but mute" failures into safe, self-explaining ones without adding any new write capability to any runtime.Independent design review — Antigravity / 7fd11282
Posting status
gitea_create_issue_commentjcwalker3/prgs-authorRecommended model
Role/capability resolver recommendation
gitea_resolve_task_capabilityrequested_operation,required_permission,required_role_kind,active_profile,active_identity,allowed_in_current_session,available_matching_profiles,runtime_switching_supported,next_safe_actionIssue-comment permission recommendation
prgs-authorhavegitea.issue.comment: yesprgs-reviewerhavegitea.issue.comment: yesgitea.issue.commentmust not implygitea.pr.comment,gitea.issue.close, or any mutating review/merge permissions.Error-message / runtime-context recommendation
Safety invariants
Suggested implementation issues
gitea_resolve_task_capabilitytool to the MCP surface.Risks / tradeoffs
Final recommendation
gitea_resolve_task_capabilitytool first to enable self-discovery, standardizing the Dual Namespace model as the core safety architecture.Independent design review — Grok (xAI)
Session context (captured at time of review):
prgsprgs-author(role_kind: author)jcwalker3(verified)runtime_switching_supported: falsegitea.issue.comment,gitea.pr.comment,gitea.pr.create,gitea.branch.*,gitea.read,gitea.repo.commitgitea.pr.approve,gitea.pr.merge,gitea.pr.request_changesprgs-reviewerexists with complementary permissions (also hasgitea.issue.comment) and separate identity (sysadmin).gitea_get_runtime_contextandmcp_get_control_plane_guidealready provide strong signals.Posting status
gitea_create_issue_comment(via gitea-tools MCP)jcwalker3/prgs-author(prgs remote)Recommended model
prgs-author,prgs-reviewer) with distinct keychain identities enforce the author/reviewer boundary at the connection layer before any LLM reasoning.allow_runtime_switching: true+ fresh whoami after every switch + strong logging.Current state on
prgsalready approximates a healthy dual-namespace setup (different profiles, different identities, complementary permissions).Role/capability resolver recommendation
gitea_resolve_task_capability(new dedicated tool) or extendgitea_get_runtime_context+ a task-specific variant.gitea.issue.comment,gitea.pr.approve)Existing
gitea_get_runtime_contextalready returns excellent fields (allowed_operations,forbidden_operations,suggested_fix,safe_next_action,profile_mode). A dedicated resolver would make task-driven calls ("review this PR", "comment on issue #139") first-class.Issue-comment permission recommendation
prgs-authorhavegitea.issue.comment: yes (currently granted and correct).prgs-reviewerhavegitea.issue.comment: yes (currently granted and correct).gitea.pr.commentdoes not implygitea.issue.comment(and vice versa)gitea.issue.commentdoes not implygitea.close_issueor label changes that closegitea.pr.review/ approve / merge remain strictly reviewer-onlygitea.pr.approve/ mergegitea.branch.create|push|pr.create|repo.commitunless a separate "reviewer-with-author" hybrid is explicitly documented and configuredCurrent config on
prgscorrectly separates these. The fact that #137 was required to grantgitea.issue.commentshows the separation was being respected (good).Error-message / runtime-context recommendation
When blocked, every relevant tool and the resolver must surface (redacted but actionable):
gitea-reviewerMCP session for prgs" or "Set GITEA_MCP_PROFILE=prgs-reviewer and restart the MCP server")gitea_get_runtime_contextalready does a good job here. Make this the canonical pre-flight for any mutating or review task. Never allow silent fallbacks.Safety invariants
These must remain non-negotiable (fail closed, no exceptions):
gitea.issue.commentmust not imply issue close/reopen/set labels that change state in a closing waygitea.pr.commentmust not implygitea.issue.commentSuggested implementation issues
gitea_resolve_task_capability(or equivalent) + tests for the example tasks listed in #139Risks / tradeoffs
Final recommendation
prgs-author/prgs-reviewer(and equivalents).gitea_resolve_task_capabilitytool that returns the fields above; make it the first call for any task that may mutate or review.gitea.issue.commentis granted exactly where intended (it appears to be for both prgs profiles now).Do not weaken any gate to "make it easier." The safety model is working when it forces the correct profile/namespace to be used.
This review was performed read-only using inspection tools only. No code, branches, PRs, or config changes were made.
Independent design review — Codex GPT-5 session
Posting status
gitea_create_issue_commentviamcp__gitea_authorjcwalker3/prgs-authorRecommended model
Role/capability resolver recommendation
gitea_route_taskfor task-level workflows, backed by a lower-levelgitea_resolve_task_capabilityhelper if needed.The resolver should use an explicit task-to-permission table rather than infer from strings. Suggested mappings:
gitea.issue.create, author-capable profile.gitea.issue.comment, author or reviewer if explicitly granted.gitea.issue.claimor the existing mark/label permission, author-capable unless separately delegated.gitea.branch.create, author.gitea.branch.push, author.gitea.pr.create, author.gitea.pr.reviewplus verdict-specificgitea.pr.approveorgitea.pr.request_changes, reviewer.gitea.pr.merge, merger/reviewer only if explicitly configured, with existing merge confirmation gates.gitea.pr.close, not implied by review or merge.gitea.issue.close, not implied by issue-comment.jenkins.build.trigger, never implied by Gitea permissions.gitea.issue.createon the target repo.Issue-comment permission recommendation
prgs-authorhavegitea.issue.comment: yes, because authors need to update implementation notes, ask clarifying questions, and report completion/blockers in issue discussions.prgs-reviewerhavegitea.issue.comment: yes, because reviewers need to leave non-review discussion notes without submitting formal PR review state.gitea.pr.comment,gitea.pr.review,gitea.pr.approve,gitea.pr.request_changes,gitea.pr.merge,gitea.issue.comment,gitea.issue.close, branch push, repo commit, Jenkins trigger, and any deployment/production operation.Tests should prove that
gitea.pr.commentdoes not satisfygitea.issue.comment,gitea.issue.commentdoes not satisfygitea.issue.close, reviewer profiles still cannot push or commit unless explicitly configured, and author profiles still cannot approve or merge.Error-message / runtime-context recommendation
Blocked operations should return: requested task, normalized required permission, active identity, active profile, forbidden and allowed operation summaries, missing permission, matching configured profile if known, whether runtime switching is enabled, whether a different namespace is required, and one exact operator action.
The message should be deterministic and action-oriented. Example:
Cannot review PR from active profile prgs-author as jcwalker3. Required permission: gitea.pr.approve. Matching configured profile: prgs-reviewer. Runtime switching: disabled. Safe next action: use the gitea-reviewer MCP namespace or relaunch with GITEA_MCP_PROFILE=prgs-reviewer.Runtime context should also expose a capability matrix such as
can_create_issue,can_comment_issue,can_open_pr,can_review_pr,can_merge_pr,can_close_issue,can_read_jenkins, andcan_trigger_jenkins, without exposing tokens, keychain IDs, raw service URLs, or private config values.Safety invariants
Suggested implementation issues
gitea_route_taskor equivalent resolver output with safe next-action guidance.gitea.issue.commentcan post issue comments while profiles without it fail closed.Risks / tradeoffs
Dual namespace is safer and easier to audit immediately, but it still requires the operator or LLM to choose the right namespace. Dynamic switching can reduce friction but creates a sharp edge unless every switch is explicit, audited, config-gated, and followed by identity verification. Dispatcher routing gives the best user experience, but it increases control-plane complexity and must be built so it never bypasses the existing per-action gates.
Granting
gitea.issue.commentto both author and reviewer profiles is a small and useful permission broadening, but only if tests keep it separate from PR review, issue close, and merge permissions.Final recommendation
Standardize the dual-namespace model immediately, grant
gitea.issue.commentexplicitly to both PRGS author and reviewer profiles, and add agitea_route_taskresolver before attempting dynamic profile switching. Treat dispatcher routing as the target architecture once the resolver and capability matrix are well tested. Do not make permission implications implicit; every task should map to a named capability and every mutating action should continue to run through its own gate.MCP issue-comment path verified ✔
Posted via
gitea_create_issue_commentfrom the reconnected MCP session —jcwalker3/prgs-author, whose allowed operations now includegitea.issue.commentafter the #137/#138 migration (alias fix merged at995bd16, live profile config updated, session reconnected).This closes the loop on failure example 2 in this issue's body: the exact workflow that previously failed closed (
profile is not allowed to gitea.issue.comment, blocking the mcp-control-plane #51 audit comment) now succeeds through the gated MCP tool. PR #140 adds the forward-direction permission-separation tests pinning this behavior.Gitea-Tools #139 Child Issues Created
Based on the design consensus reached in this thread, five child issues have been created to implement the resolved static dual-namespace task routing capability:
These issues will track the incremental delivery of the resolver, structured reporting, updated guide/docs, and synthetic regression tests. Issue #139 will remain open until these sub-tasks are resolved.
Jenkins & GlitchTip MCP Integration Child Issues Created
Following the operator decision on the Jenkins and GlitchTip MCP status audit, five child implementation issues have been created to track the remaining gaps:
These issues will track the necessary work to align the safety boundaries, audits, naming conventions, and docs for the Jenkins and GlitchTip integrations. Issue #139 remains open.
Starting work on role-aware runtime context.
Branch:
feat/issue-139-role-aware-runtime-contextFirst slice: extend
gitea_get_runtime_contextwith per-task session capability flags (author / issue-comment / review / merge / close) and redacted matching-profile hints so LLMs can ask "can I review?" or "can I comment on issues?" without guessing launcher config.Refs #139
jcwalker3 referenced this issue2026-07-06 11:48:18 -05:00
Opened PR #385 — registers
work_issue/work-issuein the role-aware resolver and session router, documents pre-task routing in the canonical work-issue workflow, and adds workflow-source verification tests.Most other #139 acceptance criteria were already on master (resolver, runtime context, dual-namespace docs). This closes the remaining gap for the default author prompt path.