Skip to content

feat(mcp): approval-queue control tools — list + decide pending agent actions (#784) - #934

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
oktofeesh1:feat/issue-784-mcp-approval-queue
Jun 20, 2026
Merged

feat(mcp): approval-queue control tools — list + decide pending agent actions (#784)#934
JSONbored merged 1 commit into
JSONbored:mainfrom
oktofeesh1:feat/issue-784-mcp-approval-queue

Conversation

@oktofeesh1

Copy link
Copy Markdown
Contributor

Part of #784 (Phase 3 — agent automation control surface). First of two focused PRs; the audit feed follows separately.

Why

Phase 3's MCP control surface could already read automation state (gittensory_get_automation_state) and stage an action (gittensory_propose_action) — but it could not surface or decide the approval queue it proposes into. That was only reachable through the CLI maintain commands and the HTTP routes, leaving an MCP-only client (or autonomous agent) unable to complete the loop it can already start.

What this adds

Two tools wrapping already-tested primitives (listPendingAgentActions, decidePendingAgentAction):

  • gittensory_list_pending_actions {owner, repo, status?} — surface the approval queue (default status=pending), each entry with id / actionClass / pullNumber / status / autonomyLevel / reason / decidedBy / decidedAt / createdAt.
  • gittensory_decide_pending_action {owner, repo, id, decision}accept (run through the live executor gates) or reject (cancel) a staged action.

Safety / parity with existing surfaces

  • Both are maintainer-manage scoped (requireRepoManageAccess) — the full queue with reasons is more sensitive than the bare count get_automation_state exposes.
  • decide is repo-scoped (a guessed id from another repo's queue → not_found, untouched) and idempotent (a second decision → already_decided), mirroring the HTTP decision route exactly.
  • accept honors current mode (dry-run / pause / autonomy) via the existing executor — no new execution path.

Tests

test/unit/mcp-automation-state.test.ts: list (default, status filter, empty), decide reject + idempotency, decide accept honoring dry-run, repo-scoped not_found, and the maintainer-access gate on both tools. Full npm run test:coverage green (branches 97.01%); new lines fully covered.

🤖 Generated with Claude Code

… actions (JSONbored#784)

Phase 3's MCP control surface could already read automation state
(gittensory_get_automation_state) and stage an action
(gittensory_propose_action), but could not surface or decide the approval
queue it proposes into — that was only reachable via the CLI `maintain`
commands and the HTTP routes. This closes the MCP parity gap with two tools:

- gittensory_list_pending_actions {owner, repo, status?} — surface the queue
  (default status=pending) with each action's id/class/PR/status/level/reason.
- gittensory_decide_pending_action {owner, repo, id, decision} — accept
  (execute via the live executor gates) or reject a staged action.

Both wrap already-tested primitives (listPendingAgentActions,
decidePendingAgentAction), are maintainer-manage scoped (the full queue with
reasons is more sensitive than the bare count), and decide is repo-scoped +
idempotent — mirroring the HTTP decision route so a guessed id from another
repo's queue cannot be decided.

Tests (mcp-automation-state.test.ts): list (default + status filter + empty),
decide reject (+ idempotent already_decided), decide accept honoring dry-run,
repo-scoped not_found, and the maintainer-access gate on both tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@oktofeesh1
oktofeesh1 requested a review from JSONbored as a code owner June 20, 2026 15:22
@dosubot dosubot Bot added the size:L label Jun 20, 2026
@ghost ghost added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jun 20, 2026
@ghost

ghost commented Jun 20, 2026

Copy link
Copy Markdown

🔍 Maintainer review

Reviewed 2 file(s) — ✅ all CI green.

Suggested action:Safe to merge — both reviewers found no blocking issues.

Reviewer A · gpt-oss-120b — recommends ✅ merge
The PR adds two new MCP tools for listing and deciding pending agent actions. It validates inputs with Zod, enforces maintainer access via requireRepoManageAccess, scopes decisions to the repository, and returns structured data without exposing forbidden public terms. Security checks (auth, scoping, no SSRF) are intact. Tests cover happy paths, filtering, permission checks, idempotency, dry‑run mode, and repo‑scoping, preserving test suite health. No CI failures reported. The change is a functional extension to core MCP logic, but implemented cleanly and safely.

Suggestions

  • Verify that decidePendingAgentAction correctly handles executionOutcome values to avoid leaking internal error details.
  • Add a unit test for the case where decidePendingAgentAction throws an unexpected error to ensure the tool returns a graceful error.

Worth double-checking

  • Introducing new public‑facing tool endpoints could increase surface area; ensure future changes keep the sanitizer constraints.
  • If the underlying decidePendingAgentAction service changes its contract, the tool may need updates.

Reviewer B · nemotron-3-120b-a12b — recommends ✅ merge
The PR adds two new MCP tools for managing the agent approval queue: list pending actions and decide pending action. The implementation correctly enforces maintainer access via requireRepoManageAccess, scopes decisions to the specific repo to prevent cross-repo tampering, and follows existing patterns for tool registration and schema definition. Tests cover core functionality, access control, edge cases (idempotency, dry-run, cross-repo), and validation. No public/private boundary violations are evident as the MCP is an authenticated interface. The changes are additive and do not modify existing logic.

No blocking issues spotted.

@ghost ghost added the reviewbot-review label Jun 20, 2026
@ghost

ghost commented Jun 20, 2026

Copy link
Copy Markdown

Note

Gittensory Gate skipped

PR closed before full evaluation. No late first comment was created.

Signal Result Evidence Action
Gate result ⚠️ Skipped #934 is no longer open. No action.

💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@ghost ghost added the gittensory:reviewed label Jun 20, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

⚠️ Contributor trust inconclusive. Click here for more info: Superagent Dashboard

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.61%. Comparing base (e0ac11f) to head (1c96192).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #934   +/-   ##
=======================================
  Coverage   96.61%   96.61%           
=======================================
  Files         110      110           
  Lines       14928    14954   +26     
  Branches     5399     5404    +5     
=======================================
+ Hits        14422    14448   +26     
  Misses        104      104           
  Partials      402      402           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants