Repository navigation
feat: add io.github.kennymcsimpson.governed-roundtable — governed roundtable for coding agents - #65
KennyMcSimpson wants to merge 2 commits into
Conversation
…ndtable for coding agents Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@KennyMcSimpson is attempting to deploy a commit to the vastsa's projects Team on Vercel. A member of the Team first needs to authorize it. |
…l-app test in 0.16.1 Rebuilt from room-dev 57f17e5 (public export to follow): - turn toasts follow the host language (read per toast, follow appearance:changed); a plugin restored at boot no longer shows English under a zh-CN UI - packets for PI seats name only Room tool calls and packets for hosted seats name only ASCII markers; no room-dev command lines reach either - the panel keeps polling while you type without losing input; a closed room is read-only with no serve / stop / room-UI button, and Release on a closed room asks twice - the stale-lock probe no longer calls Get-Process (room-dev ebc26a1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Closing this as part of the migration that removed plugin sources from this repository. Since commit 38284f1 the Your work is not lost — your branch and fork stay exactly as they are. To ship
One detail worth keeping: the center rebuilds the published manifest from what you submit, so send This repository still welcomes distribution-side contributions (a broken |
feat: add io.github.kennymcsimpson.governed-roundtable — governed roundtable for coding agents
Summary
Adds
plugins/io.github.kennymcsimpson.governed-roundtable0.1.0, its packedpackages/io.github.kennymcsimpson.governed-roundtable-0.1.0.piplug, the regeneratedcatalog.json,and
tests/governed-roundtable.test.mjs(manifest contract and negative-path tests). The only otherchange is the panel count in
tests/panel-chrome.test.mjs(19 → 20), because this plugin declaresa v3 panel.
The plugin runs room-dev's governed room inside PI-Desktop
using only public plugin APIs:
room-host): serves rooms in the plugin process, with a loopbackroom UI on
127.0.0.1and aservice.lockheartbeat.Roomagent tool (risk high): a PI conversation lists, creates and joins rooms and acts onlyfor the one seat bound to its host-supplied
ctx.sessionId.verdicts, closes rooms, serves / stops rooms and releases seat bindings.
pi-complete): text-only discussion seats that speak throughpi.agent.complete, one completion per turn, no tools.JOIN.mdand the vendoredroom-dev/room.mjs; the plugin does not touch them.No change to PI-Desktop or its core is needed.
Changes since the first commit
The second commit rebuilds the plugin from room-dev
57f17e5. It fixes what the first real-hostrun in PI-Desktop 0.16.1 found:
once in
onLoad, and the host reportsenwhile it restores plugins at boot, so a zh-CN UI gotEnglish toasts. It now reads the locale at each toast and follows
appearance:changed.Roomtool calls, andpackets for hosted seats name only the ASCII markers they write in their reply. Neither gets
room-dev command lines any more (
node …/room.mjs … --seat …). The PI seat declares this atcreation: room-dev's new seat "surface"
tool:<the name the model sees>. Packets forcommand-line seats are byte-identical to before; 26 golden hashes pin this.
caret and IME composition. Polls never stack, and a late answer is dropped.
button, and Release asks twice.
Get-Process(room-devebc26a1).All five were checked again in the real host. For this pull request the packed package grew from
958077 to 1005015 bytes. The manual-review signal count is unchanged at 58; 15 of them moved to new
line numbers, and the table below is regenerated.
Why
room-dev is a local, Windows-first room in which coding agents you already run (Codex, Claude Code,
or any agent that can run one local command) take turns in one conversation; the room never
launches, configures or attaches to them. Because it owns none of the agents, its governance detects
and records instead of enforcing: relayed text carries source labels, a reviewer's verdict is checked
against hashes of the frozen artifacts and marked stale if they changed, and an agent's own native
log can be read to confirm that a packet arrived. So far this is verified end to end with scripted
seats and with one real seat kind, a Codex thread started with
codex execin the same packagecontext as the room; Claude Code as an independent seat, and the governance layer on any real agent,
are not verified yet. The PI-Desktop side is this plugin, built only on the public plugin APIs.
It is tested against a fake host. It was also run through its GUI and one full round in the real
0.16.1 host, with a stub model. It asks for no core change.
It is a plugin rather than a core proposal because ADR 0165 withdrew the core agent-to-agent stack
and cross-session coordination now lives in plugins (
pi.session-orchestrator). Whether thegovernance layer catches failures that manual forwarding misses has not been evaluated; this PR
makes no claim that it does.
Risk tier and permissions
Tier: High (background service, file writes, child processes, an agent tool).
ui.panelopenPanelfails withPERMISSION_DENIED.agent.tool.registerRoomtool.registerToolfails withPERMISSION_DENIED,onLoadfails, nothing half-loads.background.servicecreateanswersSERVICE_NOT_RUNNINGand writes nothing; panel serve refuses the same way.agent.completeseat_failed {class: denied}; no completion is made; the plugin keeps working.shell.openExternalhttp://127.0.0.1:<port>/#<admin token>).PERMISSION_DENIED.Not requested:
desktop.control,net.fetch,fs.*,clipboard.*,agent.prompt.inject,session.read. The tests assert that nopi.desktop.*orpi.net.*call is ever made.Capability and data-flow matrix
Roomcreateroom.json%USERPROFILE%\room-dev\rooms\<room>(room, seats, tokens,JOIN.md,admin.token, events)agent.tool.register+ servicerisk: hightool[A-Za-z0-9_-]{1,64}; 1–8 seats; existing absolute seat folders;session*/token*/admin*fields refusedRoomseat actionsctx.sessionId<seat folder>\.room-outbox\<seat>, room event logagent.tool.registerRoomwaitagent.tool.registerauthority=none; forged[ROOM:escapedRoomartifactsgit init -qin the snapshot copyagent.tool.register.git, no symlinks); size capRoomdiscloseagent.tool.registerroom-host127.0.0.1HTTP (random port),service.lock, eventsbackground.servicepi.agent.completeper turn → user's configured model (quota)agent.completetools: [], no session contextroundtable/*task, start, say, close, skip, retry, approve-disclose, deny-disclose, accept-stale)ui.panelUNKNOWN_CMDpi.shell.openExternalshell.openExternalpi.ui.showToastroundtable.jsoninpi.plugin.getDataPath()(bindings incl. session ids)%USERPROFILE%\room-dev\adjudications.jsonlcodex queuechild process%USERPROFILE%\.codex,%USERPROFILE%\.claude\projects)Credentials: none read. The plugin opens rooms with
savedPiKey: false, so room-dev's DPAPI-savedPi key is never decrypted (a test runs room-dev's default as a control and shows the difference).
No outbound network; the only socket is the loopback room UI.
Known gap, documented in the README and safety notes: "administration is the user's" holds for
the
Roomtool only. Each room's admin token is a file under the rooms folder, so a PI conversationwhose own file or shell tools can read that path can administer the room without the panel. Users
who want administration to stay with them must deny those tools the rooms folder.
Dependency and provenance
room-dev/is room-dev itself, vendored unchanged by room-dev'sbuild.mjs --source headfromcommit
57f17e5553849b0da2b1a5b3b8440026621dc3af;room-dev/VENDORED.jsonlists every vendoredfile with its byte count and sha256 (
dirtyAtBuild: []). MIT (room-dev/LICENSE).57f17e5is a commit in theauthor's working repository, and public commit
4216222is its export. Each public commit messagenames the working commit it was exported from. All 46 files in
VENDORED.jsonmatch4216222byte for byte (sha256 checked).
node_modules, no minified or generated files, no native binaries.room-dev/lib/hosted/pi.mjsandlib/hosted/dpapi.mjs(room-dev's built-in Pi seat and itsDPAPI key store) are vendored but inert here: the Pi SDK is not bundled (its literal
import('@earendil-works/pi-coding-agent')fails withPI_NOT_INSTALLED), the plugin passessavedPiKey: false, and no panel or tool path reaches the key store. The plugin uses onlybuildSystemPromptfrompi.mjs.room-dev/lib/lobby.mjsandroom-dev/ui/lobby.*belong to room-dev's desktop app and are notused by the plugin (it opens the room UI through
pi.shell.openExternal).Audit result
Commands run in this clone with
C:\ProgramData\anaconda3\python.exe(CPython, stdlib only):The catalog
shasumequals the package's sha256, and--check-packagesconfirmed the packed bytesmatch the plugin source. (On Windows,
rebuild_catalog.pywrites CRLF; the file was normalized backto LF so the diff is only the new entry and
updatedAt.)Manual-review signals (58), one line each
The script reports the first match per file and kind. "room-dev" files are the vendored engine.
core.mjs:311savedPiKey: false: the plugin never reads room-dev's saved key; hosted seats use host-resolved credentials.core.mjs:283background.servicein theSERVICE_NOT_RUNNINGmessage; the service is declared in the manifest and stops on stop / unload.core.mjs:386shutDown()of the service: closes the rooms this plugin serves and removes theirservice.lock. No system action.renderer/panel.js:21background.servicein panel status text; the panel polls every 4 s withsetTimeoutonly while open.room-dev/lib/admin.mjs:551admin pi-key --port: POST to127.0.0.1only. The plugin importsadmin.mjsonly for its command list.room-dev/lib/admin.mjs:36process.env; no secret is read on the plugin's path.room-dev/lib/api.mjs:46process.env(the host's minimal env).room-dev/lib/api.mjs:168service.lockheartbeat while a room is served; cleared on close.room-dev/lib/audit.mjs:391cmd.exe&in the read-only native-log auditor's command classifier.room-dev/lib/audit.mjs:24CLAUDE_CONFIG_DIRlookup to locate Claude Code logs for read-only audit (seats registered outside the plugin only).room-dev/lib/audit.mjs:350room-dev/lib/codex.mjs:1codex.exefor the wake push (rooms with registered wakes only).room-dev/lib/codex.mjs:48findCodexreads PATH-style variables from env.room-dev/lib/common.mjs:88ROOM_DEV_HOMEfor the rooms root (not passed by the host; default%USERPROFILE%\room-dev).room-dev/lib/common.mjs:135process.kill(pid, 0): liveness probe of a lock holder; signal 0 kills nothing.room-dev/lib/export.mjs:9room-dev/lib/guard.mjs:84rm, restricted to the guard's allowed roots and logged.room-dev/lib/hosted/dpapi.mjs:109savedPiKey: false, no key command exposed).room-dev/lib/hosted/dpapi.mjs:60powershell.exefor the same; unreachable.room-dev/lib/hosted/dpapi.mjs:1room-dev/lib/hosted/dpapi.mjs:205forgetPiKeyremoves the saved key file (room-dev CLI only); unreachable.room-dev/lib/hosted/pi.mjs:19room-dev/lib/hosted/pi.mjs:8git pushbefore execution; inert here.room-dev/lib/http.mjs:45room-dev/lib/join.mjs:5node.exeon PATH for theJOIN.mdcommand.room-dev/lib/join.mjs:111nodeOnPathreads PATH from env.room-dev/lib/lobby.mjs:161rundll32 url.dllbrowser open for room-dev's desktop lobby; not used by the plugin.room-dev/lib/lobby.mjs:156room-dev/lib/lobby.mjs:20room-dev/lib/seat.mjs:475cmd.exequoting in seat command help.room-dev/lib/seat.mjs:28room-dev/lib/seat.mjs:200room-dev/lib/service.mjs:620codex queuewake push for seats with a registered wake (30 s timeout, 64 KiB cap).room-dev/lib/service.mjs:152service.lockto identify the holder.room-dev/lib/service.mjs:12savedPiKey: false.room-dev/lib/service.mjs:1748servepath (the plugin usesapi.mjs's).room-dev/lib/service.mjs:168private/folder.room-dev/lib/spawn.mjs:14room-dev/lib/spawn.mjs:89.exe,.com);.cmd/.batshims are refused.room-dev/lib/spawn.mjs:53buildCleanEnv: whitelist env so children do not inherit secrets.room-dev/lib/spawn.mjs:120killTree:taskkill /T /Fof the child's own process tree on timeout.room-dev/lib/supervision.mjs:477gitasargv[0]for disclosure rules.room-dev/lib/workspace.mjs:517git init -qinside an artifact snapshot copy in the room folder.room-dev/lib/workspace.mjs:418.cmd/.batshims as acceptance commands.room-dev/lib/workspace.mjs:219room-dev/lib/workspace.mjs:493room-dev/lib/zip.mjs:44SOURCE_DATE_EPOCHfor reproducible export archives.room-dev/room.mjs:60room-dev/room.mjs:5room-dev/ui/app.js:621fetchto its own loopback server (same origin).room-dev/ui/app.js:619credentials: 'same-origin'fetch option.room-dev/ui/app.js:1147room-dev/ui/index.html:29room-dev/ui/lobby.html:25room-dev/ui/lobby.js:67fetch; not used by the plugin.room-dev/ui/lobby.js:67credentials: 'same-origin').room-dev/ui/lobby.js:125navigator.clipboard.writeText); not used by the plugin.room-dev/ui/lobby.js:570Validation actually run
This repository's own
tests.ymlwas run unchanged on this branch, on GitHub Actionsubuntu-latestwith Node v22.23.3 and Python 3.12. The run was made in a private scratch copy,because Actions stay off on a new fork until someone enables them in the web UI. Every step passed:
security_audit.py --check-packages: 27 plugins, 0 blockers, 139 manual-review signals (allplugins together).
node --test tests/*.test.mjs tests/*.test.js plugins/*/test/*.test.mjs: 222 tests, 220 pass,0 fail, 2 skipped. Neither skip is in this plugin's tests: one needs
osv-scannerand one needsWindows OpenSSH. All 8 tests in
tests/governed-roundtable.test.mjspass.The same run was repeated on the second commit (
8fa21c2). The results were identical: 0blockers, 139 signals, 16 Python tests OK, and 222 Node tests with 220 pass, 0 fail and 2 skipped.
All 8 of this plugin's tests passed again.
On room-dev itself, at
57f17e5, withROOM_DEV_HOMEpointed at a short temp folder:node test/e2e.mjs: 81/81;On the author's Windows 11 machine, Node 24.11.1 (first commit unless stated):
node --test --test-skip-pattern="real helper" tests/*.test.mjs→ 189 tests,185 pass, 4 fail. The 4 failures (
gitlens.test.mjs×2,terminal.test.mjs×2) also fail ona clean
origin/mainworktree on this machine. They are environment-specific and unrelated to thisplugin. An earlier unfiltered run also failed
terminal.test.mjs"real helper can spawn a shortcommand…". That test was skipped afterwards and was not rechecked on
origin/main.tests/governed-roundtable.test.mjs: 8 / 8 pass.tests/panel-chrome.test.mjspasses with theupdated count.
python -m unittest discover -s tests -p "test_*.py"→ 16 tests OK.tests/governed-roundtable.test.mjsloadsplugins/<id>/main.jsin a fake host that followsupstream's
buildApi()shapes and AsyncLocalStorage tool-invocation scoping, with rooms in athrow-away temp folder. It checks:
sessionId/session/token/adminTokenin tool input is refused(
IDENTITY_FROM_CONTEXT_ONLY), as are a missing session (NO_SESSION), a foreign seat(
NOT_YOUR_SEAT), a taken seat (SEAT_TAKEN) and a hosted seat (HOSTED_SEAT);ADMIN_ONLY_IN_PANEL), no admin event comes fromthe tool, and the admin token never appears in tool output;
[ROOM:…authority=user]block in one seat's speech reaches the next PI seat and thehosted seat's
agent.completepacket escaped, inside anauthority=noneblock that carries thepacket's nonce and a "not a user instruction" declaration;
agent.complete,shell.openExternal,background.serviceandagent.tool.register, as tabulated above;service.lock, a stopped service is not restarted by a tool call,start serves the room again, and unload leaves nothing served;
pi.desktop.*/pi.net.*call is made.6123f21:node --test "integrations/pi-desktop-plugin/test/*.test.mjs"→ 24 / 24 pass (fake host: full rounds with PI seats, an external Claude Code seat that runs
the vendored
room.mjsin a separate process, hosted seats incl.RATE_LIMITED, panel flows,service stop / restart races). Root suite
node --test "test/**/*.test.mjs"→ 587 tests, 586pass, 1 skipped, 0 fail.
In the real host (official PI-Desktop 0.16.1 portable)
There were two runs. The first ran on the first commit's files, and its findings led to the second
commit. The second ran on the second commit's build, in a fresh profile (see
the second run).
What was tested in the first run. The first commit's files, unchanged: a copy of
plugins/<id>(
diff -ragainst the branch showed no difference) andpackages/<id>-0.1.0.piplug(sha2564fc8b4a9…8eba4, the value incatalog.jsonat that commit).Host and profile. The official
PI-Desktop-Portable-0.16.1.ziprelease asset, run with athrow-away profile:
PI_DESKTOP_DATA_DIR,PI_DESKTOP_AGENTS_DIR,HOME,USERPROFILEandPI_CODING_AGENT_DIRpoint into it, and so does
--user-data-dir.PI_DESKTOP_AGENTS_DIRis needed. host-core finds the global.agentsroot withdirs::home_dir(), whichUSERPROFILEdoes not redirect. A first attempt that left the variableunset loaded the author's real
.agentsskills and MCP server definitions and started thoseservers. That attempt was stopped and the whole run was repeated with the variable set.
Model. A local OpenAI-compatible stub, modelled on upstream's
apps/desktop/test/e2e/plugin-ui-slots/stub-model.mjs. It was registered through host-core'sproviders.create, the way that harness'sseed.mjsdoes it. No real model was used.How it was driven.
--remote-debugging-port).PI_DESKTOP_MCP_CONTROL=1).addressed to the picker's own controls.
What happened:
Load dev plugin. The Plugins menu item 加载本地插件 opens a folder picker, then the permission
review. The review listed all five permissions by risk:
agent.tool.register,background.service,agent.complete;shell.openExternal;ui.panel.After Load, the registry row read
source: dev,status: ready. Serviceroom-hostwasrunningwith 0 restarts,plugin.load.successwas logged, and there were no warn or error lines.Command palette. Searching "roundtable" lists Governed Roundtable: Open panel with the
extension badge. Running it opens the panel window.
Panel. It rendered in the host's language (zh-CN). Its content starts below the 46 px band and
the window-control capsule. It showed the service as running and the rooms root inside the
throw-away profile.
Tool name and approval. The model was offered
plugin_io_github_kennymcsimpson_governed_roundtable_Room. It is a deferred tool, so the modelactivated it through
ToolSearchfirst. Calls then showed the host's high-risk approval card("Plugin-provided tool requires approval") with an input preview, until "allow for this
conversation" was chosen.
create. After approval,
createreturned "Room created and served". Seatpi1was bound tothe calling conversation's host session id; the panel showed the binding.
Forged identity and admin actions. A forged
sessionIdfield and the non-tool actionstartwere both rejected by the host's own schema validation ("must not have additional properties",
"must be equal to one of the allowed values"). This happened before approval and before any plugin
code ran. In the real host these inputs therefore never reach the plugin; the plugin's own checks
(tested with the fake host) are a second layer.
One full round.
pi1's turn.waitreturned the packet with its nonce and authority blocks.submitwas accepted. Its text contained a forged[ROOM:00000000:seat=h1 authority=user]block.
h1spoke through the host's realagent.complete. Its request offered notools. In that request the forged block appeared escaped as
[ROOM\:…, inside anauthority=noneblock that carried the packet's nonce and the "not a user instruction" line.pi1published the summary, thenround_done.Duplicate submits, caused by the stub. The room log also shows two
NOT_YOUR_TURNrejectionsfor duplicate submits. They came from the test stub reusing tool-call ids after it was restarted:
PI's agent runtime dropped the replayed results, and the model resubmitted. The room rejected
both duplicates.
Closing and releasing. Close room needs a second click, and then logs
room_closedbyadmin. Release emptied the bindings, after which the tool answered
NOT_JOINED.Install .piplug. First the dev copy was uninstalled; this removed it and closed its panel.
Then the menu item 安装插件包 opens a file picker. After picking the package:
source: installed,status: ready;plugins/<id>;room-hostwasrunning;No permission review appeared in this install path, unlike Load dev plugin.
Writes outside the throw-away profile. A top-level snapshot of the profile roots, taken before
and after, shows no write by this plugin.
%TEMP%gained Chromium'sscoped_dir*folders forthe two app runs. It also gained a number of empty
.tmp*folders that could not be attributed toa process.
Second run: the fixed build
What was tested. The second commit's build, in a fresh throw-away profile with
PI_DESKTOP_AGENTS_DIRset from the first launch. The process tree held only host-core, and no MCPserver was started. The build was taken before the README update, so the folder in this PR differs
from it only in
README.md,README.zh-CN.mdand the commit recorded inroom-dev/VENDORED.json;the code is byte-identical.
permissions, then Load. After that the plugin was
readyandroom-hostwasrunning.pi1with surface{"kind":"tool","tool":"plugin_io_github_kennymcsimpson_governed_roundtable_Room"}. That isexactly the name the host shows the model.
Set task and Start round in the panel then produced the toast
圆桌 gui-test2:轮到席位 pi1。请让坐在这个席位的 PI 对话继续(调用 Room 工具的 wait 取包)。under the zh-CN UI.
wait, has noroom.mjs,room.cmd,--seator other CLI flag.Its lines read
行动方式:本席位只经宿主提供的房间工具 plugin_…_Room(下称房间工具)行动:…and交卷:调用房间工具 {"action":"submit","room":"gui-test2","attempt":"a1-1-be4be6","text":"<你的发言全文>"}….agent.completehas no CLI text and does notmention
房间工具. It reads交卷方式:本席位由房间托管,没有房间命令,也没有向房间提交的工具;你这一次回复的全文就是本回合的发言….authority=userblock in that request is still escaped inside anauthority=noneblock.
summary_published, thenround_done.there. The event list then advanced from
#3to#12without Refresh, and the input stillheld its text and focus. The status line read
阶段: 空闲 · 轮次 0, later本轮结束and已散会.Release and Hide: no Serve here, Stop or room UI button, and no text inputs. Release
needed a second click (
再点一次确认), and only then was the binding removed.source: installed,status: ready. The installed tree was byte-identical toplugins/<id>,room-hostwas running, and the panel opened..agentswas untouched; the only additions in%TEMP%were Chromium'sscoped_dir*folders.Not run
shell.openExternal). It would have opened the test machine'sdefault browser, so it was not clicked. Whether Windows keeps the URL fragment is therefore still
unverified.
tested only with the fake host.
agent.complete.JOIN.mdwhile the plugin served it.Known limits
session/collaboration/send/spawnneed an activeAgent tool invocation, which a background service never has, and
desktop.controlagent/promptwould deliver the wake with user authority. The plugin shows a toast and the usertells that conversation to continue.
agent.completeper turn with no tools, so ahosted seat cannot be an executor.
Roomtool works in Agent mode only (noplanSafeActionsreach the broker).engines.piDesktopis>=0.16.1. The only PI-Desktop source read was a shallow clone at 0.16.1,which cannot show the earliest release that has every API used. Older hosts may work but were not
checked.
nodeon PATH, and theirroom.mjspath points into the installed pluginfolder.
piseats without thetoolsurface. A newconversation cannot join them (
NOT_A_PI_SEAT); recreate those rooms. Bindings that already existkeep working.
stay in Chinese, as room-dev writes them.
中文摘要
新增插件
io.github.kennymcsimpson.governed-roundtable0.1.0(含.piplug、重新生成的catalog.json、tests/governed-roundtable.test.mjs,以及把panel-chrome测试里的面板数 19 改为 20)。它只用公开插件接口,把 room-dev 的受治理房间带进 PI-Desktop:常驻房间宿主、
Room工具(席位按宿主给的ctx.sessionId绑定)、用户管理面板、经agent.complete的纯文本讨论席位。不需要改宿主或核心。风险等级:高。五项权限:
ui.panel、agent.tool.register、background.service、agent.complete、shell.openExternal;能力与数据流矩阵见上文。审计:仓库全量
security_audit.py --check-packages0 个 blocker;本插件 58 条人工复核提示,逐条理由见上表。已跑:本仓库自己的
tests.yml原样在 GitHub Actions 上跑过,环境是 ubuntu-latest、Node 22。结果全部通过:审计 0 个blocker;Python 测试 16 个;Node 测试 222 个,其中 220 个通过、2 个跳过,跳过的都不是本插件的;新测试 8/8 通过。
第二个提交又跑了一遍,结果相同。作者 Windows 机器上:本插件的测试 12/12 通过(含 panel-chrome)。room-dev 侧:
插件测试 55/55;全量 604 个,其中 603 通过、1 跳过、0 失败;e2e 81/81。
真实宿主:在官方 PI-Desktop 0.16.1 便携版里测了本 PR 的原样文件,用的是一次性配置目录和本地 stub 模型。以下都通过:
plugin_io_github_kennymcsimpson_governed_roundtable_Room,以及高风险审批卡;agent.complete发言,伪造的authority=user块在包里被转义、放进authority=none块;之后发布总结;plugins/<id>逐字节相同。伪造的
sessionId和 admin 动作在真实宿主里先被宿主自己的 schema 校验挡掉,根本到不了插件。注意:隔离测试必须设PI_DESKTOP_AGENTS_DIR,因为USERPROFILE挡不住 host-core 读真实 home 下的.agents。未跑: 在浏览器打开房间界面(会打开测试机的默认浏览器)、真实宿主里的权限拒绝路径、真实模型、外部 agent 在真实宿主里
入席、崩溃后带陈旧锁重启。
第一次真实宿主测试发现的 4 个问题,已在第二个提交里修好,并在真实宿主里复测通过:
另外带上了锁探针的修复(room-dev
ebc26a1)。已知限制:PI 席位不能经插件接口自动唤醒;托管席位只能讨论(
agent.complete,无工具);治理层能否抓到手工转发漏掉的问题尚未评估;admin 令牌是文件,PI 对话自己的文件 / shell 工具若能读到房间目录就能绕过面板。
🤖 Generated with Claude Code