feat(api): add GET /v1/repos/:owner/:repo/automation-state + CLI mirror - #6964
Conversation
…or (JSONbored#6742) The derived automation view (mode / permissionReadiness / actingActionClasses / pendingActionCount) that loopover_get_automation_state computes was reachable only over MCP -- GET /settings returns just the raw resolved row. This adds the read-side REST route and a `maintain automation-state` CLI subcommand, symmetric with the existing write-side PUT /settings and maintain pause/resume/set-level. The computation is extracted into src/services/automation-state.ts (buildAutomationState) and the MCP tool refactored to call it, so the three surfaces share one implementation and cannot drift. Route is maintainer-gated like /settings; OpenAPI spec regenerated with an AutomationState schema. Closes JSONbored#6742
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6964 +/- ##
=======================================
Coverage 93.71% 93.71%
=======================================
Files 685 686 +1
Lines 68379 68392 +13
Branches 18730 18730
=======================================
+ Hits 64080 64093 +13
Misses 3302 3302
Partials 997 997
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 16:13:02 UTC
Review summary Nits — 5 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. Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. 🟩 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 MCP tool
loopover_get_automation_statecomputes a derived view —mode/permissionReadiness/actingActionClasses/pendingActionCount— thatGET /v1/repos/:owner/:repo/settingsdoes not return (settings returns only the raw resolved row). It was reachable only over MCP; the CLI had write-side mirrors (maintain pause/resume/set-level) but no read-side counterpart.This adds both halves the issue asks for:
GET /v1/repos/:owner/:repo/automation-stateinsrc/api/routes.ts, maintainer-gated exactly like/settings.maintain automation-stateCLI subcommand proxying it.AutomationStateschema).Single source of truth — the part worth reviewing
Rather than duplicate the computation into the route (which would drift from the MCP tool the moment either changed), I extracted it into
src/services/automation-state.ts(buildAutomationState) and refactored the MCP tool to call it. So all three surfaces — REST, MCP, CLI — compute the derived view one way. The MCP tool's own test suite (mcp-automation-state.test.ts, 37 tests) passes unchanged against the refactor, which is the evidence the extraction preserved behavior exactly.The service performs no authorization itself — every caller gates first (the route via
requireRepoMaintainer, the MCP tool via its ownrequireRepoAccess), preserving the pre-refactor gating.Tests
api.test.ts) — asserts 401 unauthenticated, 200 for a maintainer, and every derived field with its exact enum shape (mode,permissionReadiness). This issrc/**, so it's under the 99% patch gate.mcp-cli-maintain.test.ts) — drives the real CLI against a fixture, asserting the rendered summary + output parity (--jsonreturns the same derived fields).Validation
src/**file:automation-state.ts(9/9 stmts, 6/6 branches, 3/3 funcs), plus the route/refactor/openapi lines inroutes.ts,server.ts,spec.ts,schemas.ts— zero uncovered, zero partial. The one structurally-unreachable line (if (gate instanceof Response)— the auth middleware rejects before the handler) carries the same/* v8 ignore next */pragma its sibling routes use.npm run typecheck— 0 ·npm run ui:openapi:check(drift) — clean ·ui:openapi:settings-parity— clean ·eslint— 0/0 ·node --check— ok ·git diff --check— clean · rebased on latestmain.Deliberately does not touch
mcp-tool-rename-aliases.test.ts: amaintainsubcommand is not aregisterStdioTool, so it doesn't change the pinned stdio tool count — avoiding the count-pin that has been a recurring base-conflict hotspot.Scope & safety
GET+ a shared read-only service. No write path, no new capability; the route exposes only what the MCP tool already did, under the same maintainer gate.openapi.jsonis committed (CI fails on drift); the spec adds one path + one named schema.site//CNAME/lovablechanges.Closes #6742