Skip to content

fix(mcp): drop autonomy levels the server removed in #4620 from the CLI - #6378

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
luciferlive112116:fix/mcp-cli-autonomy-levels
Jul 16, 2026
Merged

fix(mcp): drop autonomy levels the server removed in #4620 from the CLI#6378
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
luciferlive112116:fix/mcp-cli-autonomy-levels

Conversation

@luciferlive112116

Copy link
Copy Markdown
Contributor

Summary

loopover-mcp maintain set-level client-side-validated against MAINTAIN_AUTONOMY_LEVELS, which still listed "suggest"/"propose". #4620 removed both server-side, and PUT /settings validates the body against the live enum (src/api/routes.ts -> z.enum(["observe","auto_with_approval","auto"])), so the CLI waved through two values the API rejects — turning what should be an immediate, clear client-side error into a confusing 400.

The same stale constant also fed maintain --help, so the help text advertised both dead levels as valid input. Both call sites read the constant, so narrowing it fixes them together.

The whole executable change is one line. Everything else is a test and comments.

Why a corrected literal, not an import

The issue asked me to consider importing the canonical list rather than keeping two hand-synced copies. I checked, and it isn't reachable from here:

  • bin/loopover-mcp.js resolves @loopover/engine through the published package ("@loopover/engine": "^3.0.0").
  • That package's exports map exposes only . plus a few ./scoring/* and ./signals/* subpaths — there is no ./settings/* entry, and the root entry doesn't export AUTONOMY_LEVELS (it exports TENANT_AUTONOMY_LEVELS, an unrelated dial).

So importing it would mean widening the engine's public API — larger than this issue's scope, which is exactly the case the issue scoped out. I took the blessed fallback: corrected literal + a comment naming the source of truth and why the import isn't available.

Since the copies stay hand-synced, I pinned the invariant instead of trusting the comment: the list parsed out of the committed CLI source must equal the live AUTONOMY_LEVELS. If either side moves again, the test fails immediately.

Validation

  • npx vitest run test/unit/mcp-cli-maintain.test.ts10/10 pass.
  • Both new tests fail against the old list, for the right reasons: the sync guard reports expected ['observe','suggest',...(3)] to deeply equal ['observe',...(2)], and the regression reports promise resolved "'Set review autonomy to suggest for owner/repo'" instead of rejecting — i.e. the old CLI reported success for a value the real API 400s.
  • Ran 7 related suites (maintain, basics, completion-spec, autonomy, autonomy-engine, automation-state, tool-categories) — 120/120 pass.
  • npm run typecheck — 0 errors. npm run build:mcp — passes (syntax-checks the changed file). npm run docs:drift-check — ok. git diff --check — clean.
  • Rebased on latest main — no base conflict.

The regression test proves the failure is client-side: the fixture's PUT /settings echoes any autonomy body back as a success, exactly like a server with no enum — so a rejection can only have come from the CLI's own check, before any round-trip.

Coverage

No patch surface: coverage is collected over src/**, packages/loopover-engine/src/**, and packages/loopover-miner/lib/**. The one-line change is in packages/loopover-mcp/** (not collected), the src/mcp/server.ts edit is comment-only, and test/** is ignored.

Scope note — what I deliberately did NOT change

MAINTAIN_ACTION_CLASSES (the line directly above) reads stale next to the engine's AGENT_ACTION_CLASSES, which now carries review_state_label/update_branch/assign. That divergence is intentional: it's the operator-settable subset the maintain surface exposes, and src/mcp/server.ts's MAINTAIN_AUTONOMY_ACTION_CLASSES mirrors those same six on purpose. I left it alone and said so inline, so the next reader doesn't "sync" it and widen the surface by accident.

I also refreshed the comment in src/mcp/server.ts that explained its choice of the live enum by citing this list as "still carries suggest/propose" — true before this PR, stale after it.

Scope

  • One coherent change; wanted paths (packages/, src/, test/).
  • No secrets/tokens/wallet/trust-score/reward terms.
  • No changelog, site/, CNAME, or lovable changes; no generated artifact invalidated (command-reference is generated from src/github/commands.ts, not this CLI).

Safety

  • Behaviour narrows client-side validation to match the server; no auth/CORS path touched. The dial still accepts every level the server does — a test asserts set-level review observe still succeeds, so the fix narrowed the list without breaking it.
  • No secrets committed.

Closes #6153

…rom the CLI

`loopover-mcp maintain set-level` client-side-validated against
MAINTAIN_AUTONOMY_LEVELS, which still listed "suggest"/"propose". JSONbored#4620
removed both server-side -- PUT /settings validates the body against the
live AUTONOMY_LEVELS enum -- so the CLI waved through two values the API
rejects, turning what should be an immediate, clear client-side error into
a confusing 400. The same stale list also fed `maintain --help`, so the
help text advertised both dead levels as valid input.

Narrow MAINTAIN_AUTONOMY_LEVELS to the live enum. Both call sites (help
text and validation) read the constant, so this fixes them together.

Kept as a literal rather than an import, per the issue's fallback: this
file resolves @loopover/engine through the published package (^3.0.0),
whose export map exposes only `.` plus a few ./scoring/* and ./signals/*
subpaths. Neither surfaces AUTONOMY_LEVELS, so importing the canonical
list would mean widening the engine's public API -- a larger refactor than
this fix. The comment now records that, and the source of truth.

Since the copies stay hand-synced, a test pins the invariant instead: the
list parsed from the committed CLI source must equal the live enum, so the
two cannot drift again silently. Both new tests fail against the old list.

Left MAINTAIN_ACTION_CLASSES alone: it reads stale next to the engine's
AGENT_ACTION_CLASSES, but it is a deliberate operator-settable subset that
src/mcp/server.ts's MAINTAIN_AUTONOMY_ACTION_CLASSES mirrors on purpose.
Noted inline so the next reader doesn't "fix" it.

Also refreshed server.ts's comment, which cited this list as the stale one.

Closes JSONbored#6153
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.60%. Comparing base (2e33517) to head (08d8f73).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #6378       +/-   ##
===========================================
+ Coverage   36.39%   95.60%   +59.20%     
===========================================
  Files         599      599               
  Lines       47235    47235               
  Branches    15031    15031               
===========================================
+ Hits        17192    45157    +27965     
+ Misses      27412     1291    -26121     
+ Partials     2631      787     -1844     
Flag Coverage Δ
shard-1 44.06% <ø> (?)
shard-2 36.60% <ø> (+0.20%) ⬆️
shard-3 32.58% <ø> (?)
shard-4 34.74% <ø> (?)
shard-5 31.59% <ø> (?)
shard-6 44.86% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/mcp/server.ts 96.33% <ø> (+55.19%) ⬆️

... and 481 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 16, 2026
@loopover-orb

loopover-orb Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-16 05:27:03 UTC

3 files · 1 AI reviewer · no blockers · readiness 83/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This one-line fix narrows the CLI's hand-synced MAINTAIN_AUTONOMY_LEVELS from five values to the three the live server enum actually accepts, closing the gap where the CLI would client-side-validate 'suggest'/'propose' only to have the API 400 on them. The accompanying test adds a genuine invariant check (parsing the committed CLI source and comparing against the live AUTONOMY_LEVELS import) plus a regression test that exercises the actual rejection path, both of which look like real, non-fabricated coverage of the fixed line. The extensive comments explain why an import isn't used instead of a shared constant (published package export map doesn't surface it), which is a reasonable, well-documented tradeoff rather than an oversight.

Nits — 5 non-blocking
  • The comment block in packages/loopover-mcp/bin/loopover-mcp.js is quite long (15+ lines) for a one-line fix; consider trimming to the essential rationale and issue reference.
  • test/unit/mcp-cli-maintain.test.ts uses a regex parse of the CLI source (declaredLevels()) rather than a more robust AST-based check, which is fragile if the array literal's formatting changes, though acceptable for a guard test.
  • The PR description states the whole executable change is one line, but src/mcp/server.ts also has a 5-line comment-only change — worth confirming that file's comment update doesn't need separate justification (it appears to be pure documentation, not behavior).
  • Consider extracting the comment's shared rationale (why no import) into a single reference comment rather than repeating similar explanations in both loopover-mcp.js and server.ts.
  • If the regex in declaredLevels() ever needs to handle multi-line array literals, note that assumption in a code comment near the regex.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #6153
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 141 registered-repo PR(s), 79 merged, 32 issue(s).
Contributor context ✅ Confirmed Gittensor contributor luciferlive112116; Gittensor profile; 141 PR(s), 32 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: minor
Linked issue satisfaction

Addressed
The PR narrows MAINTAIN_AUTONOMY_LEVELS to exactly ["observe","auto_with_approval","auto"] matching the live server enum, adds a comment citing src/settings/autonomy.ts as source of truth with justification for not importing, and adds tests both pinning list sync and confirming 'suggest'/'propose' now fail client-side with a clear error rather than a server round-trip.

Review context
  • Author: luciferlive112116
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 141 PR(s), 32 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Add a concise scope and risk note.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask 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.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

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.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 572a5a7 into JSONbored:main Jul 16, 2026
16 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 16, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(mcp): packages/loopover-mcp's MAINTAIN_AUTONOMY_LEVELS still accepts "suggest"/"propose", values the server rejected since #4620

1 participant