feat(api): mirror loopover_propose_action to REST and the CLI - #7030
Conversation
…red#6744) Add POST /v1/repos/:owner/:repo/agent/pending-actions and a `maintain propose` CLI subcommand, completing the create/list/decide trio the approval queue only had list/decide for. The route is write-gated (requireRepoWriteAccess) like its sibling decision route and mirrors the loopover_propose_action MCP tool: same head-SHA pinning (JSONbored#2255) and the same { created, action } shape. It only STAGES an auto_with_approval action for a maintainer to accept/reject later; it never executes one. Like the sibling pending-actions routes it is not in the OpenAPI spec. The CLI subcommand posts to the bare create path and sanitizes every API-echoed field on the plain-text path.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7030 +/- ##
=======================================
Coverage 93.74% 93.74%
=======================================
Files 690 690
Lines 68643 68662 +19
Branches 18756 18764 +8
=======================================
+ Hits 64346 64365 +19
Misses 3302 3302
Partials 995 995
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-17 18:55:46 UTC
Review summary Nits — 4 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
Summary
The
loopover_propose_actionMCP tool stages a new pending agent action for later maintainer approval(it never auto-executes). REST already had the list side (
GET .../agent/pending-actions) and thedecision side (
POST .../agent/pending-actions/:id/:decision), both CLI-mirrored — but no way tocreate a staged action over REST/CLI. This completes the create/list/decide trio.
POST /v1/repos/:owner/:repo/agent/pending-actions— a plain create route,requireRepoWriteAccess-gatedexactly like its sibling decision route. It mirrors the
proposeActionMCP handler verbatim: resolve therepo's installation (409
app_not_installedif the App isn't installed), pin the staged action to the PR'scurrent head SHA (the same force-push freshness guard
proposeActionsets, fix(mcp): gittensory_propose_action stages actions with no expectedHeadSha, disabling the force-push guard #2255), thencreatePendingAgentActionIfAbsentatauto_with_approval. It returns the identical{ created, action: { id, actionClass, pullNumber, status, reason } }shape the tool returns, and onlystages an action — it never executes one. A zod schema mirroring
proposeActionShape(minus thepath-param owner/repo) rejects a malformed body with
400 invalid_propose_action_request.loopover-mcp maintain propose <action-class> <pull-number>— the CLI subcommand, alongside theexisting
status/queue/approve/reject. Posts to the bare create path, supports--reason/--label/--review-body/--merge-method/--close-comment+--json, validates the action class(the 7-value propose set, incl.
review_state_label) and pull number before any request, and sanitizesevery API-echoed field on the plain-text path.
Like every sibling
agent/pending-actionsroute, it is deliberately omitted from the OpenAPI spec.Closes #6744
Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #6744).Validation
npm run typechecknpm run build:mcp(node --check)npm run command-reference:check/npm run ui:openapi— no diff (localmaintainsubcommands aren't in the generated command catalog; mirror routes aren't in the OpenAPI spec)git diff --checknpx vitest run test/unit/routes-agent-approval.test.ts test/unit/mcp-cli-maintain.test.ts(66 passing)src/api/routes.ts(the only Codecov-measured file in this diff) viacoverage-final.json— every optional-param branch (present/absent), the head-SHA pin (present/absent), the schema-reject, and the not-installed arm.Safety
sanitizePlainTextTerminalOutput;--jsonstays raw (JSON.stringify escapes control chars).requireRepoWriteAccess-gated like the decision route; a non-maintainer session gets 401/403 (tested), and the coarse-allowlist comment is updated to reflect the new write-gated POST on the shared path.UI Evidencesection is required.--helpdocuments the new subcommand; no changelog edited.Notes
createPendingAgentActionIfAbsentpath the MCP tool calls, with the same write gate and head-SHA pinning. It stages for approval only —
execution stays exclusively on the existing accept path.
PROPOSE_ACTION_CLASSESin the CLI (a superset of theautonomy-configurable
set-levellist, addingreview_state_label) soproposeaccepts exactly what theroute + MCP tool accept.