Skip to content

feat(mcp): let agents ask BOSS how it is doing - #1369

Merged
fluck-boss merged 1 commit into
risa-labs-inc:devfrom
Vidhaankhare16:feat/introspection-mcp-tools
Sep 23, 2026
Merged

fluck-boss merged 1 commit into
risa-labs-inc:devfrom
Vidhaankhare16:feat/introspection-mcp-tools

Conversation

@Vidhaankhare16

Copy link
Copy Markdown
Contributor

What this adds

A host MCP tool provider, boss-introspection, answering "what condition is BOSS in
right now?" with two read-only tools. Fixes #1364.

tool returns
get_workspace_health / workspace_health the WorkspaceHealthReport: degraded, findings[] with stable codes and remedies, unchecked[], partial[]
get_performance_metrics / performance_metrics heap and non-heap memory, CPU load, GC activity, and window / browser-tab / terminal / editor-tab counts

The gap

BOSS already computes both halves of its own condition and exposes neither to a tool
caller.

WorkspaceHealthReport is reachable only through SingleInstanceManager — over the
single-instance socket, from a CLI process outside the host. boss doctor (#418,
#579) was built for a human at a terminal. PerformanceMonitor publishes its snapshot
to a settings panel and nowhere else.

So the agent sitting inside the host, which is the party that actually has to decide
whether to open another browser tab or spawn another terminal, could not ask whether
the host was already degraded or near a ceiling. It found out by causing the failure.

Three decisions worth reviewing

One contract, two surfaces. get_workspace_health returns
WorkspaceHealthReport.toJson() — the same object boss status --json already emits —
rather than a second shape for one concept. A script written against
boss doctor --json and an agent calling this tool read the same codes, and they
cannot drift apart later.

Magnitudes, not contents. ResourceMetrics carries browserTabs, terminals and
editorTabs; CpuMetrics carries a thread list. Those hold URLs, file paths and
thread names. None of it is emitted. A caller deciding whether there is headroom needs
to know there are eleven browser tabs, not which pages they are on, and a tool that
answered the second question would be a far larger disclosure than the one it was
asked. There is a test asserting a tab's URL and title never reach the output while the
count still does.

Honest about not knowing. PerformanceMonitor.currentSnapshot is null until
start() has run and the first tick has landed. The tool reports sampling: false
with no memory object at all rather than zeros — for the same reason
WorkspaceHealthReport separates unchecked from "no findings". An agent that read
heapUsedBytes: 0 and concluded it had headroom would be worse off than one told the
monitor has not reported. Likewise a missing supplier answers available: false, never
an empty-but-successful report.

Platform seams

PerformanceMonitor and WorkspaceHealthCollector are desktopMain; this provider and
the registry are commonMain. Both sources are injected at startup from main.kt,
exactly as WorkspaceMcpToolProvider.windowCreator already is, so the provider carries
no platform assumption and the tests drive it entirely through fakes — no running
monitor, no window, no desktop.

Tests

IntrospectionMcpToolProviderTest, 10 cases, covering both tools' happy paths plus the
cases that make the output trustworthy: an unchecked area not reading as healthy, a
null snapshot not reading as zero, a throwing source being reported rather than
propagated, an unwired supplier saying so, the per-tab detail not escaping, and both
tools declaring readOnly.

Relationship to the other host providers

Those answer what the workspace contains; this answers what condition the host is
in
. Complementary surfaces, and a separate provider keeps the concerns apart. The only
line shared with #997 is the registerProvider(...) call in McpToolRegistryImpl.init,
which is a one-line merge in either order.

@kshivang

Copy link
Copy Markdown
Contributor

Review disposition: draft pending a clean rebase onto current dev.

Oldest-first history check: the branch contains 68 commits that are already patch-equivalent to dev; only 30c9191 (the five-file boss-introspection feature, authored by @Vidhaankhare16) is unique. The unique feature behavior is coherent:

  • Before: an in-host MCP agent could not read the existing workspace-health report or performance snapshot; health was available only through the external CLI/single-instance path and performance only in the settings panel.
  • After: boss-introspection registers four read-only aliases, reuses WorkspaceHealthReport.toJson(), exposes aggregate performance counts/metrics without URLs, paths, or thread names, and explicitly reports unavailable/not-yet-sampled states instead of fabricating zeros.

The merge blocker is branch ancestry, not that feature logic. A three-way merge against current dev would remove 28 current-dev paths, including:

  • .github/workflows/edge-functions.yml
  • infra/cloudflare/live-sessions-alias/*
  • supabase/functions/live-sessions/*
  • supabase/migrations/20260921120000_terminal_sessions.sql
  • supabase/migrations/20260921130000_terminal_sessions_scope_all.sql
  • supabase/migrations/20260921140000_terminal_sessions_sweep_tuning.sql
  • current release-note/config/redirect/email-template files

Please rebase/update this branch from current dev and retain your feature commit/credit, or create a clean branch from dev and replay only 30c9191. Before requesting review again, verify:

  1. git diff --name-status origin/dev...HEAD contains only the intended introspection provider, its two wiring changes, and its two focused test files; no current-dev files are deleted.
  2. git diff --check origin/dev...HEAD is clean.
  3. Rerun ./gradlew :composeApp:desktopTest --tests 'ai.rever.boss.mcp.IntrospectionMcpToolProviderTest' --tests 'ai.rever.boss.mcp.IntrospectionRegistrationDriftTest' --console=plain.
  4. Keep the existing CI coverage; the current PR-head CI is green, and the focused PR-head test run also passed (BUILD SUCCESSFUL).

Related-work check: #1364 is the matching open issue; #997 (workspace contents) and #1120 (panel layout) are adjacent MCP surfaces, not duplicates. No separate Claude review is present on this PR; the issue feedback from @surfthewave-commits is reflected in the unique tip's nested health payload, explicit not-sampling behavior, read-only declarations, and registration-wiring test.

No migrations were applied.

@kshivang
kshivang marked this pull request as draft September 22, 2026 04:15
@kshivang
kshivang force-pushed the dev branch 2 times, most recently from bdcf620 to bc9aa3b Compare September 22, 2026 04:42
BOSS computes both halves of its own condition and exposed neither to a tool
caller. WorkspaceHealthReport is reachable only through SingleInstanceManager -
over the single-instance socket, from a CLI process outside the host - because
`boss doctor` was built for a human at a terminal (risa-labs-inc#418, risa-labs-inc#579). The performance
monitor publishes its snapshot to a settings panel and nowhere else. So the
agent inside the host, the party that has to decide whether to open another
browser tab or spawn another terminal, had no way to ask whether the host was
already degraded or near a ceiling; it found out by causing the failure.

Adds a host provider, boss-introspection, with get_workspace_health and
get_performance_metrics, both read-only by declaration rather than by the
mutating gate's fail-closed default.

The health tool returns WorkspaceHealthReport.toJson() - the same object
`boss status --json` emits - so the CLI and the MCP surface cannot drift into
two shapes for one concept, and scripts and agents match the same codes.

Counts and aggregates only. ResourceMetrics carries per-tab, per-terminal and
per-editor lists and CpuMetrics carries thread names; none of it travels. A
caller deciding whether it has headroom needs to know there are eleven browser
tabs, not which pages they are on.

A snapshot that does not exist yet reports sampling=false with no memory object
at all, never zeros, for the reason the health report separates unchecked from
"no findings": a caller reading 0 bytes used and concluding it has headroom is
worse off than one told the monitor has not reported.

Both sources are desktopMain and the provider is commonMain, so they arrive
through suppliers wired in main.kt the way WorkspaceMcpToolProvider.windowCreator
already is - which is also what lets the tests drive it with fakes.

The health payload is nested under "health" rather than flattened beside an
"available" flag, so the value is byte-identical to what `boss status --json`
emits under its own "health" key and the two surfaces can be diffed on one
machine. A test pins it by equality against toJson() rather than by spotting
fields, and a future field on the report can no longer collide with "available".

A drift test pins the registration and both supplier wirings. The failure it
guards is silent: the provider can compile, expose its tools and pass every one
of its own unit tests while never being registered, or while registered with no
suppliers behind it - in which case every call answers available=false on a
healthy host and the tools read as broken rather than absent. Source-text rather
than booting the registry, which would construct the policy engine, approval bus
and ledger and reach ~/.boss on the machine running the suite.

Both raised by @surfthewave-commits in review on risa-labs-inc#1364.
@Vidhaankhare16

Copy link
Copy Markdown
Contributor Author

Rebuilt as you described: a clean branch from current dev, replaying only the introspection commit, with authorship kept. Head is now 132541f0 — one commit on dev.

Your four checks, run against that head:

1. git diff --name-status origin/dev...HEAD — only the intended files, no deletions:

A  composeApp/src/commonMain/kotlin/ai/rever/boss/mcp/IntrospectionMcpToolProvider.kt
M  composeApp/src/commonMain/kotlin/ai/rever/boss/mcp/McpToolRegistryImpl.kt
M  composeApp/src/desktopMain/kotlin/ai/rever/boss/main.kt
A  composeApp/src/desktopTest/kotlin/ai/rever/boss/mcp/IntrospectionMcpToolProviderTest.kt
A  composeApp/src/desktopTest/kotlin/ai/rever/boss/mcp/IntrospectionRegistrationDriftTest.kt

The provider, its two wiring changes, its two focused test files. The live-sessions paths you listed — infra/cloudflare/live-sessions-alias/*, supabase/functions/live-sessions/*, the three terminal_sessions migrations, edge-functions.yml — are all present on the branch, untouched.

2. git diff --check origin/dev...HEAD — clean.

3. ./gradlew :composeApp:desktopTest --tests 'ai.rever.boss.mcp.IntrospectionMcpToolProviderTest' --tests 'ai.rever.boss.mcp.IntrospectionRegistrationDriftTest' — BUILD SUCCESSFUL, 11/11 and 2/2, declared counts matching run counts. detekt and ktlint clean on the same run.

4. No workflow or CI configuration touched; existing coverage is unchanged.

Hosted CI on 132541f0, stated plainly: 8 of 9 checks green, none failed. The one not yet
finished is build-test (macos-latest), still queued rather than run - so this is not a
fully green head yet. I am marking it ready now because a draft cannot merge at all and you are
mid-sweep; if you would rather hold it until the macOS leg reports, re-drafting it is entirely
reasonable and I will flip it back once that check lands.

The same ancestry was on three more of mine. #1340, #1343 and #1347 were cut from the same pre-rewrite dev and carried the same stale history, so rather than wait for them to reach you in the same state, I rebuilt each the same way — one commit per branch on current dev, authorship kept — and re-ran each one's focused tests before pushing:

PR files tests
#1340 7 54/54
#1343 2 43/43
#1347 3 shell guard passes; still fails against current dev's boss.bat

#869 you had already rebuilt yourself - thank you. I have addressed the Claude review of
your rebuilt head there, as one fast-forward commit on top of it.

One thing I could not do, and want to be straightforward about: I tried to reproduce the 28-path deletion you found with git merge-tree --write-tree origin/dev <old head>, and it reported zero for the old #1369 head as well — so my check did not see what yours did. I rebuilt anyway because the stale ancestry was the problem you named, but I would rather tell you my verification had a blind spot than claim it confirmed your finding.

@Vidhaankhare16
Vidhaankhare16 marked this pull request as ready for review September 22, 2026 12:50
@fluck-boss fluck-boss closed this Sep 23, 2026
@fluck-boss fluck-boss reopened this Sep 23, 2026
@fluck-boss
fluck-boss merged commit a827cb0 into risa-labs-inc:dev Sep 23, 2026
20 checks passed
@fluck-boss

Copy link
Copy Markdown
Collaborator

Merged to dev (squash). Gate: diff verification + CI green on head. feat(mcp): let agents ask BOSS how it is doing.

fluck-boss added a commit that referenced this pull request Sep 23, 2026
…shots (#1595)

#1524 dropped ResourceMetrics.browserTabs (and BrowserTabInfo with it)
while #1369's introspection test still constructed one, so dev's
compileTestKotlinDesktop fails on the merged tree - both PRs were green
against their own bases. The privacy property the test pinned is now
structural (nothing per-tab is retained), so the test now pins the wire
shape instead: the count is reported and no per-tab key ever appears.

Co-authored-by: Instinct Agent <agent@instinct.com>
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.

3 participants