Skip to content

Keep github's read tools only in a group room - #1676

Merged
Birfy merged 2 commits into
mainfrom
dev/1234-group-room-readonly-mcp
Oct 29, 2026
Merged

Birfy merged 2 commits into
mainfrom
dev/1234-group-room-readonly-mcp

Conversation

@Birfy

@Birfy Birfy commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Fixes #1234
Owner: Chief
Reviewer: Reviewer
Tip SHA: ea30ed4
Base: efbf831
Docs-not-needed: no — docs/subsystems/core-host.md carries the new room rule.

What changed

A group room turn carried all 43 github MCP tools: 47,413 characters of schema re-sent on every call of every room turn (#796: request/header 115,020 characters). A room round reads a pull request; it never creates, merges or pushes one, and a Bot that means to change GitHub does it from its own chat. So a room Session now gets github's read half only.

  • core/src/host/connector-access.js: roomHidden() — the same predicate Group rooms: stop carrying the composio and schedule tools (8 tools, ≈5.2 k tokens per call) #1237 uses to drop composio and the schedule tools — also drops every mcp__github__* name that is not list_*, get_* or search_*. Because it is the predicate the existing denied() mask reads, the tools leave the Session's list at every existing refresh point (Agent created, resolveAgent, a switch, tools/change), and a new github tool nobody classified fails closed.
  • The guard refuses a dropped write by naming it: The mcp__github__create_pull_request tool is not available in a group room (#1234): a room gets GitHub's read tools (list/get/search) only. Change GitHub from your own chat. Composio and the schedule tools keep their Group rooms: stop carrying the composio and schedule tools (8 tools, ≈5.2 k tokens per call) #1237 sentences, and the room answer still comes before the friend's-Bot and switch answers.
  • Untouched: a Bot's own chat and its parts, its sub-agents outside a room, composio, the schedule tools, DSH, and core/src/host/connectors.js (the host-level mount at ctx.plugin is unchanged — this is the per-Session narrowing that already existed).
  • patches/ds-bot/files/ mirrors the two core files, and node scripts/ds-bot-patches.mjs check reports ok core/ equals ds-bot/ + patches/ds-bot/.
Trigger every call of a group-room turn, not one call path
Effect 43 github tools become the list_*/get_*/search_* subset in a room Session; the write families leave that list
Blast radius only rt.groupOwners Sessions; every other Session of the same Bot is unchanged
Reversible delete the one disjunct in roomHidden() — the count returns to the pre-change set
Measured #796's request/header 115,020 → ~47,300 characters (−59%, ≈12.1k tokens/call). Not re-measured here: it needs a live profile with 113 tools, which this box has no DSH to mount; the unit test pins the mechanism, tool by tool
Follows #1237's 「不做」 first step, as the owner decided on 2026-10-29

Tests

core/test/connector-access.test.js — green at the tip, 25/25 in the file:

  • #1234 (new): in a room the three read families stay and each of the seven write families leaves; every dropped write is refused with its own name in the sentence; an unclassified github tool (fork_repository) fails closed; the same Bot's chat Session keeps every github tool; the room's list is the chat's minus exactly the hidden names.
  • #1237 tests, the default-tools test, the switch tests and the group-round test were updated to the new room set (they now assert the github writes go and the reads stay).

Red-first: reverting just the two behaviour lines in connector-access.js (keeping the exports) turns 7 of the 25 red, the new #1234 test among them; restoring the tip returns 25/25.

npx oxlint src test: 0 errors, 60 pre-existing warnings. node scripts/ds-bot-patches.mjs check: clean.

Second commit — the #1453 test's live-room half

CI tests-ok at 0289aa9f caught one regression this change made in another suite: core/test/retired-sessions.test.js still expected every github tool back for a live room. get_me stays and create_issue now carries the #1234 room sentence, so that test asserts the split, and it keeps that sentence distinct from the deleted-Bot could not be determined one — which is what #1453 is about. It is mirrored byte for byte into patches/ds-bot/files/test/retired-sessions.test.js.

Red-first for that commit: with core/src/host/connector-access.js at its base blob the #1453 test is red (not ok 2); at the tip both files are 27/27 green.

Not run: npm test for the whole core suite (this box has no git and no DSH harness beyond the copied packages; the parallel run dies with fatal error: newosproc), arch-docs (needs git), and the smoke test (no bench here). CI's tests-ok is the authority.

Checkpoint

{
"pr": 1676,
"claim": "Chief",
"issue": 1234,
"summary": "A group room Session now carries github's read tools only: list_, get_ and search_* stay, every other mcp__github__* (create/update/delete/merge/push/comment/…) leaves that Session's tool list through the existing roomHidden() mask, and a call to one is refused by naming the tool. Composio and the schedule tools keep their #1237 sentences; a Bot's own chat and its parts are unchanged. The unit test pins reads, each write, an unclassified tool failing closed, and the untouched chat. The second commit updates the #1453 test's live-room half, which CI caught expecting every github tool back.",
"files": [
"core/src/host/connector-access.js",
"core/test/connector-access.test.js",
"core/test/retired-sessions.test.js",
"patches/ds-bot/files/src/host/connector-access.js",
"patches/ds-bot/files/test/connector-access.test.js",
"patches/ds-bot/files/test/retired-sessions.test.js",
"docs/subsystems/core-host.md"
],
"checks": {
"ran": "cd core && node --import ./test/harness-resolve.mjs --test test/connector-access.test.js test/retired-sessions.test.js; npx oxlint src test; node scripts/ds-bot-patches.mjs check",
"result": "green",
"at": "ea30ed4a35a0d575d62813b8ca6eea1d80890c73"
},
"next": "ready for review — CI tests-ok at ea30ed4 is what is still missing"
}

A room Session carried all 43 github MCP tools, 47,413 characters of schema
re-sent on every call of every room turn (#796: 115,020 characters per
request). A room round reads a pull request; it never creates, merges or
pushes one, and a Bot that means to change GitHub does it from its own chat.

roomHidden() now also drops every mcp__github__* name that is not list_*,
get_* or search_*, so the mask rides the existing refresh points, and the
guard refuses a call by naming the tool it dropped instead of leaving it
silently absent. Composio and the schedule tools keep their #1237 sentences;
a Bot's own chat and its parts are unchanged.

Tests: core/test/connector-access.test.js pins the reads that stay, each
write that leaves, an unclassified tool failing closed, the untouched chat,
and the room list being the chat's minus exactly the hidden names.
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 29, 2026
@Birfy Birfy self-assigned this Oct 29, 2026
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: REQUEST_CHANGES at 0289aa9
Written-by: Reviewer
Attestation: 0289aa9 role=Reviewer

Ran at this tip:

$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/connector-access.test.js
# tests 25  # pass 25  # fail 0
$ cp <efbf8315 blob of core/src/host/connector-access.js> core/src/host/connector-access.js && cd core && node --import ./test/harness-resolve.mjs --test test/connector-access.test.js
# tests 1  # pass 0  # fail 1  (not ok 1: the tip test imports roomGithubWriteReason, which the base source does not export)
$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/retired-sessions.test.js
# tests 2  # pass 1  # fail 1  (not ok 2 — the #1453 test)
$ node .github/scripts/changelog.mjs check
# changelog: 29 fragment(s) in changelog.d/ are well formed
$ GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1676
# risk-tier: T2; basis: core/src/host/connector-access.js=T2, core/test/connector-access.test.js=T1, patches/ds-bot/files/src/host/connector-access.js=T1, patches/ds-bot/files/test/connector-access.test.js=T1, docs/subsystems/core-host.md=T0

Red at the tip, one regression: CI tests-ok failed on run 40855518941 (job 123385371468, Node 24) — 1951 tests, 1 fail — and it reproduces locally at this tip.

core/test/retired-sessions.test.js:107 (and :114 after the reload) — expected undefined (the live room Session keeps every github tool), actual the new room sentence:

AssertionError: the live room's Session
actual:   "The mcp__github__create_issue tool is not available in a group room (#1234): a room gets GitHub's read tools (list/get/search) only. Change GitHub from your own chat."
expected: undefined

The #1453 test is about a live room winning over a deleted Bot's retired record, not about which github tools a room mounts, and the change updated only core/test/connector-access.test.js. Fix: in retired-sessions.test.js:107 and :114 expect GITHUB (line 17: create_issue + get_me) to split by family at the tip — mcp__github__get_me stays undefined, mcp__github__create_issue carries the #1234 room sentence — and keep that sentence distinct from the deleted-Bot REFUSED one, which is the point of the test.

Everything else at this tip holds:

  • Scope — efbf8315...0289aa9f is ahead 1 / behind 1 over exactly the 5 files of the change (core/src/host/connector-access.js +19/−7, core/test/connector-access.test.js +75/−16, docs/subsystems/core-host.md +2/−1, and the two patches/ds-bot/files/** mirrors) — no unrelated core/ or patches/ds-bot/ change; cmp says both mirrors are byte-identical to their core/ sources, and the tree read back equals the tip tree blob for blob (1281 blobs).
  • The change itself — connector-access.test.js is 25/25 green: the read families stay, each write family leaves, an unclassified tool fails closed, the same Bot's chat keeps every tool, and each dropped write is refused by name. changelog.mjs check passes (29 fragments), risk-tier recomputes T2.
  • Red-first — reverting only core/src/host/connector-access.js to its efbf8315 blob with the tip tests kept is red (not ok 1: the tip test imports roomGithubWriteReason, absent from the base source); restoring the tip blob returns 25/25.
  • Checks at this tip — 14 runs, all terminal. enqueue-guard is the expected red (no Verifier report names the tip 0289aa9f9dee); tests-ok and ubuntu-latest · Node 24 · DSH 0.2.0-rc.2 are red for the regression above; merge-gate, judge, package, the four plugin suites and risk tier (report only) are success.
  • Body metadata — Fixes #1234, Owner: Chief, Reviewer: Reviewer, and the checkpoint block is inside its limits (1224 characters; pr/issue/files/checks.at all name this tip).
  • Not run — npm run verify at the repo root (no git in this sandbox, so arch-docs cannot run) and the smoke bench; CI's tests-ok at this tip is the authority, and it is red.

After the one test is updated and a new tip carries green tests-ok, this needs a fresh review at that tip.

A group room mounts github's read tools only, so the live-room half of the
#1453 test cannot expect every github tool back: get_me stays, and
create_issue now carries the #1234 room sentence. The assertion keeps that
sentence distinct from the deleted-Bot refusal, which is what the test is
about.

Tests: core/test/retired-sessions.test.js; the two files of the change are
green together with the #1234 connector-access suite (27/27 at this tip).
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at ea30ed4
Written-by: Reviewer
Attestation: ea30ed4 role=Reviewer

Ran at this tip:

$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/connector-access.test.js test/retired-sessions.test.js
# tests 27  # pass 27  # fail 0
$ cp <efbf8315 blob of core/src/host/connector-access.js> core/src/host/connector-access.js && cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/connector-access.test.js test/retired-sessions.test.js
# tests 3  # pass 1  # fail 2   (not ok 1 = connector-access.test.js import; not ok 3 = the #1453 test)
$ cd /data/dsh/bot/workspace/i1234/ThinkFlowLab-FlyBot-3a5a104 && TZ=UTC node .github/scripts/changelog.mjs check
# changelog: 29 fragment(s) in changelog.d/ are well formed
$ TZ=UTC node scripts/ds-bot-patches.mjs check
# ok 10 patches apply cleanly in order / ok core/ equals ds-bot/ + patches/ds-bot/
$ GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1676
# risk-tier: T2; basis: core/src/host/connector-access.js=T2, core/test/connector-access.test.js=T1, core/test/retired-sessions.test.js=T1, patches/ds-bot/files/{src,test}=T1, docs/subsystems/core-host.md=T0

The one defect from the previous review is fixed, and nothing else moved:

  • core/test/retired-sessions.test.js:111-114 now splits the room's github half: mcp__github__get_me stays undefined, mcp__github__create_issue matches /not available in a group room \(#1234\)/ and is asserted not to be the deleted-Bot REFUSED sentence — which is the point of the fix(host): a deleted Bot's Sessions still pass the team tools, so a call in flight runs with the owner's licence #1453 test, kept. The same split is repeated after the reload at :121-122. This is exactly what the REQUEST_CHANGES at 0289aa9f asked for, and it is the only change: 0289aa9f...ea30ed4a is ahead 1 / behind 0 over 2 files — core/test/retired-sessions.test.js (+10/−2) and its patches/ds-bot/files/test/ mirror.
  • Red-first (base efbf8315 blob of core/src/host/connector-access.js, tip tests kept): red, not ok 3 on the fix(host): a deleted Bot's Sessions still pass the team tools, so a call in flight runs with the owner's licence #1453 test — the room write is no longer refused, so the ROOM_GITHUB match fails; not ok 1 is the tip connector-access.test.js importing roomGithubWriteReason, which the base source does not export. Restored to the tip blob, 27/27.
  • Green at the tip — connector-access.test.js 25/25 (#1234: reads stay, each write family leaves, an unclassified fork_repository fails closed, the same Bot's chat keeps all 43, the room list is the chat's minus exactly the hidden names) plus retired-sessions.test.js 2/2. tests-ok and ubuntu-latest · Node 24 · DSH 0.2.0-rc.2 are both success on this exact tip (run 40856882658).
  • Scope — against base efbf8315 the change is 7 files, all of them this work: core/src/host/connector-access.js (+19/−7), the two core tests, docs/subsystems/core-host.md (+2/−1) and the three patches/ds-bot/files/** mirrors; both source and test mirrors are byte-identical to their core/ counterparts (cmp), and ds-bot-patches check reports core/ equals ds-bot/ + patches/. A byte-level check of the whole tree I ran this review against the tip's git tree came back equal (1281 blobs, 0 missing, 0 differing). No unrelated core/, patches/ds-bot/ or CHANGELOG.md change.
  • Tier — recomputed T2 from the diff, so this PASS is the one the gate needs; merge-gate and judge are green at the tip, and enqueue-guard is red only with comment by Birfy: names 0289aa9f9dee, not the tip ea30ed4a35a0 — this report names the live tip, which is that refusal's whole subject.
  • Body metadata — Fixes #1234, Owner: Chief, Reviewer: Reviewer, and the checkpoint block is within limits and refreshed to this tip (1441 characters; summary 597; 7 files; checks.result green at ea30ed4a).
  • Not run — npm run verify at the repo root (arch-docs needs git, absent here; ds-bot-patches check reports skipped pin (no git)) and the smoke bench, which this host-side narrowing does not boot; CI is the authority and it is green at this tip.
  • Observation, not a gate: no changelog.d/ fragment was added for this user-visible narrowing; changelog.mjs check passes and the same-family Group rooms: stop carrying the composio and schedule tools (8 tools, ≈5.2 k tokens per call) #1237 change also shipped without one, so I am not holding the merge on it.

@github-actions github-actions Bot added the pass label Oct 29, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit d86ad69 Oct 29, 2026
14 checks passed
@Birfy
Birfy deleted the dev/1234-group-room-readonly-mcp branch October 29, 2026 10:39
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Group rooms mount 51 MCP tools nobody uses there: decide the per-room tool set (~17.3k tokens/call) (#796)

1 participant