Skip to content

feat(agent): approval queue + notification + accept/reject (#779)#846

Merged
JSONbored merged 1 commit into
mainfrom
feat/agent-approval-queue-779
Jun 17, 2026
Merged

feat(agent): approval queue + notification + accept/reject (#779)#846
JSONbored merged 1 commit into
mainfrom
feat/agent-approval-queue-779

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #779

What & why

This completes Phase 1 (#769) — the auto_with_approval path. When an action's autonomy level is auto_with_approval, the write-actions layer (#778) now stages it for a one-tap maintainer decision instead of executing. Accept/reject feeds the trust loop.

How

  • Model — migration 0045_agent_pending_actions + agentPendingActions schema + AgentPendingActionRecord. At most one row per (repo, pull, action_class); a decided row is sticky (re-evaluation never re-stages it). Repo fns: createPendingAgentActionIfAbsent (idempotent), listPendingAgentActions, getPendingAgentAction, setPendingAgentActionStatus.
  • Executor (feat(agent): maintainer write-actions layer (request-changes/approve/merge/close/label) #778) integrationrequiresApprovalstageForApproval: persist the action's execute-time params + notify the maintainer once (reusing the feat(notifications): event-to-subscription-to-delivery service #535 notifications service, badge channel) → audit queued. Re-evaluation neither duplicates the row nor re-notifies.
  • Decision servicedecidePendingAgentAction:
    • accept → runs the staged action live (the accept is the approval, so the executor's approval gate is bypassed — but the kill-switch and write-permission gates still apply), marks accepted, audits.
    • reject → cancels, marks rejected, audits.
    • Both are sticky + idempotent; a second decision is a no-op. Each records an agent.pending_action.* audit event (the trust-loop signal).
  • API (maintainer-scoped, per-repo) — GET /v1/repos/:owner/:repo/agent/pending-actions, POST .../pending-actions/:id/accept, POST .../pending-actions/:id/reject. The id is scoped to the repo so no one can decide another repo's queue via a guessed id.

Safety

  • Accept honors the kill-switch + pull_requests: write readiness — an accept on a paused or under-permissioned repo records an error, it does not silently mutate.
  • Cross-repo decisions are rejected (404); a non-operator session is forbidden; a re-decide returns 409.

Tests

Staging (pending row + notification + idempotency), repository dedup, accept/reject/already-decided/not-found/denied-execution, the exported helpers (actionParams, pendingActionToPlanned), and the routes (list, accept, reject, invalid verb, 404 cross-repo, 409 re-decide, non-operator forbidden, operator-session identity). New code 100% covered; full suite green (2089 passed).

Phase 1 completes: the auto_with_approval path. When an action's autonomy level
is auto_with_approval, the write-actions layer (#778) now STAGES it for a one-tap
maintainer decision instead of just auditing 'queued'.

- migration 0045 + schema agent_pending_actions + AgentPendingActionRecord — at
  most one row per (repo, pull, action_class); a decided row is sticky.
- db: createPendingAgentActionIfAbsent (idempotent stage), listPendingAgentActions,
  getPendingAgentAction, setPendingAgentActionStatus.
- executor: requiresApproval → stageForApproval (persist the action's execute-time
  params + notify the maintainer ONCE via the #535 notifications service, badge
  channel) → audit queued. Re-evaluation never duplicates the row or re-notifies.
- services/agent-approval-queue: decidePendingAgentAction — accept runs the staged
  action LIVE (the accept IS the approval, so the executor's approval gate is
  bypassed; the kill-switch + write-permission gates still apply), reject cancels.
  Either decision is sticky + idempotent and records an agent.pending_action.*
  audit that feeds the trust loop.
- API (maintainer-scoped, per-repo): GET .../agent/pending-actions,
  POST .../pending-actions/:id/{accept,reject}. The id is scoped to the repo so
  no one can decide another repo's queue via a guessed id.

Tests: staging (pending row + notification + idempotency), repository dedup,
accept (executes + accepted + audit) / reject / already-decided / not-found /
denied-execution, the exported helpers, and the routes (list, accept, reject,
invalid verb, 404 cross-repo, 409 re-decide, non-operator forbidden, operator
session identity). New code 100% covered; full suite green (2089).
@dosubot dosubot Bot added the size:L label Jun 17, 2026
@ghost

ghost commented Jun 17, 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 #846 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 17, 2026
@ghost

ghost commented Jun 17, 2026

Copy link
Copy Markdown

gittensory · advisory review

Reviewed 9 changed file(s) — two independent AI reviewers.

Changed files (9)
  • migrations/0045_agent_pending_actions.sql
  • src/api/routes.ts
  • src/db/repositories.ts
  • src/db/schema.ts
  • src/services/agent-action-executor.ts
  • src/services/agent-approval-queue.ts
  • src/types.ts
  • test/unit/agent-approval-queue.test.ts
  • test/unit/routes-agent-approval.test.ts

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

Reviewer A · gpt-oss-120b — recommends ✅ merge
The PR adds a full approval‑queue feature for auto‑with‑approval agent actions, including a new DB table, repository helpers, service logic, API routes, types, migration, and comprehensive tests. The implementation follows existing patterns and appears functionally correct.

Suggestions

  • Consider adding pagination or a max‑limit parameter to the pending‑actions list endpoint for scalability.
  • Document the new routes in the API reference (e.g., OpenAPI spec) to keep documentation up‑to‑date.
  • Verify that the migration is included in the CI deployment pipeline so the new table is created in production.

Worth double-checking

  • Ensure the migration runs on all environments; missing the table would cause runtime errors.
  • Confirm that the new routes are protected by the existing authentication/authorization middleware in all deployment configurations.

Reviewer B · nemotron-3-120b-a12b — recommends ✅ merge
The PR adds an approval queue feature for agent actions requiring maintainer approval (auto_with_approval). It introduces a new database table (agent_pending_actions), repository functions, service logic for staging/deciding actions, API routes for listing and deciding, and comprehensive unit tests. The implementation correctly stages actions instead of executing them, sends notifications to maintainers, and handles accept/reject decisions with audit logging. The changes respect the public/private boundary (no forbidden terms in public output) and include proper maintainer-scoped authentication.

Suggestions

  • Consider adding error logging for notification failures in stageForApproval (though non-blocking, it would improve observability).
  • The v8 ignore comments in createPendingAgentActionIfAbsent and decidePendingAgentAction are acceptable but could be supplemented with tests to verify the defensive logic (though currently hard to test due to uniqueness constraints).

Worth double-checking

  • If notification delivery fails silently, maintainers may not be alerted to pending actions (though they can still access via API).
  • The autonomy level auto_with_approval now stages actions instead of executing; ensure existing configurations using this level are intentional and maintainers are aware of the new workflow.

@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.66%. Comparing base (5b53281) to head (dcb9c71).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #846      +/-   ##
==========================================
+ Coverage   96.64%   96.66%   +0.01%     
==========================================
  Files         104      105       +1     
  Lines       14411    14476      +65     
  Branches     5243     5266      +23     
==========================================
+ Hits        13928    13993      +65     
  Misses        105      105              
  Partials      378      378              

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit 80a1f48 into main Jun 17, 2026
20 checks passed
@JSONbored
JSONbored deleted the feat/agent-approval-queue-779 branch June 17, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(agent): approval-queue UX + notification channel

1 participant