Repository navigation
Commit 06cccd3
fix(service-messaging,mcp): the inbox list hides the raw topic; an MCP argument refusal ends at the fix (#30688)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DY5gzehJPFXRJ6RuAr8coQ1)_
domain:server#4 · os-elon-musk · session_016WV4cxrNurGFU9PsE6NwNT
Part of #30126 (rows 8 and 15 land here; rows 9, 12, 13 and 16 stay on
the card, see Acceptance notes)
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:收件箱「我的通知」列表不再显示 `notify` 这类原始主题 id(只剩标题、级别、时间);MCP
工具收到没声明的参数时,报错只说错在哪、该怎么写,不再追加一句给内部开发者看的历史说明。
- 为什么改:真实用户走查里,通知列表的 Topic 列读成 `notify`,读者看不懂;MCP 报错末尾「This argument
used to be dropped silently…」对调用方没有用,只是噪音。
- 风险与回滚:很小。`topic` 字段本身没动,仍可搜索、可被其他视图使用;MCP 照旧拒收每个未声明参数,只是少了最后一句。回滚即撤本
PR。
- 先看:`packages/mcp/src/mcp-http-tools.ts` 的 `withoutHistorySentence` 与
`strictToolInput`;`packages/services/service-messaging/src/objects/inbox-message.object.ts`
的 `mine` 视图 `columns`。
- 两分钟验证:`pnpm --filter @objectstack/mcp exec vitest run
src/mcp-http-tools.unknown-argument-keys.test.ts`,预期 13 条全绿;另有 `pnpm
--filter @objectstack/service-messaging exec vitest run
src/objects/inbox-message-mine-view.test.ts` 2 条全绿。
- 需要你做的:无,席位落地(非受管面)。行 9、13、16 的取舍另由席位呈决裁。
## What changes
- **Row 8, `@objectstack/service-messaging`.** `sys_inbox_message`'s
`mine` list view (a person's own notifications) projected `['title',
'topic', 'severity', 'created_at']`. `topic` is the producer's machine
id (`notify` from a flow's notify node, `collab.mention` from a mention)
and no catalog labels it, so the column read `notify`. The view now
projects `['title', 'severity', 'created_at']`. The card's suggestion
was "hide it or give it a label"; there is nothing to label it from, so
it is hidden. The `topic` field is unchanged and still `searchable`.
- **Row 15, `@objectstack/mcp`.** Every MCP tool closes its argument
shape with `strictUnknownKeyError` (`@objectstack/spec/shared`), which
ends each message with the surface's `history` sentence. The MCP tools
passed `UNKNOWN_ARG_HISTORY` ("This argument used to be dropped silently
and the call still succeeded, …"). They now pass an empty history
through a small wrapper, `withoutHistorySentence`, which trims the
separator the factory leaves, so the message ends at its last fix
channel. The explanation of the posture stays in the file's comments.
`packages/spec` is not touched: the factory is unchanged for every
authorable schema.
## Tests
-
`packages/services/service-messaging/src/objects/inbox-message-mine-view.test.ts`
(new, 2): the `mine` view's columns are exactly title, severity, time;
`topic` stays a searchable field.
- `packages/mcp/src/mcp-http-tools.unknown-argument-keys.test.ts` (new
top-level `describe` in the existing harness, 2): the reported `sort`
call is refused with `` `sort` → `orderBy` `` and no history sentence;
over every advertised tool, no refusal carries the sentence or ends in
whitespace.
- Ablations through `scripts/ablation-replace.mjs`, each restored with
`git diff HEAD` empty: the old history sentence put back → 2 failed of
13 in the MCP file; `topic` put back in the view → 1 failed of 2. Both
test files import `src`.
- `@objectstack/mcp` full suite: 56 files, 680 passed.
`@objectstack/service-messaging` full suite: 67 files, 847 passed.
`typecheck` for both: exit 0.
## Acceptance notes
- **Row 9 (mention title follows the recipient's locale): not built,
`needs_decision`.** The delivery chain is the maintainer's ruling quoted
in `recipient-locale.ts` (「解析链 = 收件人 `locale` → 部署默认」), which also lists
a request-scoped locale as deliberately not in the chain. Since the card
was filed, PR #30539 and PR #30597 save a language picked on the sign-in
and register pages as the person's own when they have none. Whether a
person who never picks a language should get one stamped, or whether a
"last used" rung should join the chain, is a product choice; the options
go to the maintainer through the seat.
- **Row 12 (Setup app refusal in English): not built.** It shares
`packages/rest/src/meta-item-read-gate.ts` with open PR #30459, which is
still waiting on the maintainer, so per the claim's serial constraint it
is left for after that lands.
- **Row 13 (`os package export` `-u`/`-t` vs `os package install`
`-r`/`--email`/`--password`): not built, `needs_decision`.** About
twenty commands use `-u/--url` + `-t/--token`; `install` uses
`-r/--runtime` with a session sign-in, and `publish` uses `-s/--server`.
One way to name them means renaming a published option (breaking; this
repo keeps no alias window) and, for `install`, choosing which
credential kinds it takes. Options go to the maintainer.
- **Row 16 (`list_actions` lists admin-only identity actions to a plain
member): not built, `needs_decision`.** The listing is in
`packages/runtime/src/domains/mcp.ts`, outside the claimed
`packages/mcp/src/**`. The actions' admin gate lives only in each
target's own mount (`/api/v1/auth/admin/*`, `plugin-auth`'s
`judgePlatformAdmin`, and different gates for SSO and manager doors) and
in a display-only `visible` predicate; no key the action door reads
states it. Hiding or marking them means either a declared gate on the
actions or a second copy of the targets' predicates in the runtime, and
the two precedents (`actionPermissionError` hides, the #28178 / #28943
credential table marks `unavailable`) point different ways. Every
refusal is unchanged. `invite_user` appearing four times is four objects
each declaring it, which `run_action`'s `objectName` disambiguates.
- Noted, not filed: the MCP refusal still carries the spec factory's
upgrade-guide sentence ("Keys retired before the previous protocol major
…"), which is about metadata keys rather than tool arguments. Out of row
15's ask.
## Verification
<details><summary>Derived gates and suites</summary>
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `18552efc` (5 paths vs merge base
`b77c160a`): 63 commands, each run with its exit code captured before
any pipe. 60 exit 0 on the first pass; three exit 3 (prerequisite):
- `node scripts/check-plugin-teardown-shape.mjs --self-test`: exit 0
after fetching its pinned fixture commit `621a4876` (48 cases).
- `pnpm check:i18n`: exit 0 after its own named prerequisite build (CLI
+ the ten extract packages): "all bundles in sync, no undeclared
authoring keys".
- `pnpm check:dual-build-cjs-loads`: NOT MEASURED locally (needs a
whole-workspace build); CI's Lint & Repo Gates runs it.
- `dispatch-gates --ran`: 63 derived, 62 run, 1 NOT-MEASURED (the one
above), 0 UNRUN, exit 0. Changed lines: 126 (+107 / -19, 5 files).
- `pnpm --filter @objectstack/mcp typecheck`, `pnpm --filter
@objectstack/service-messaging typecheck`: exit 0 (after a full build of
both closures).
- Suites: `@objectstack/mcp` 56 files / 680 tests passed;
`@objectstack/service-messaging` 67 files / 847 tests passed.
- Merged `origin/main` (`a2437b56`) before opening; the incoming commits
touch neither package, so nothing was re-run. Final head `3a5b38d6`. CI
check-runs: not read at the time of writing.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cxrNurGFU9PsE6NwNT)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 71318af commit 06cccd3
5 files changed
Lines changed: 107 additions & 19 deletions
File tree
- .changeset
- packages
- mcp/src
- services/service-messaging/src/objects
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
696 | 696 | | |
697 | 697 | | |
698 | 698 | | |
699 | | - | |
700 | | - | |
| 699 | + | |
| 700 | + | |
701 | 701 | | |
702 | | - | |
703 | | - | |
704 | | - | |
705 | | - | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
706 | 711 | | |
707 | | - | |
708 | | - | |
709 | | - | |
710 | | - | |
711 | | - | |
712 | | - | |
713 | | - | |
714 | | - | |
715 | | - | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
716 | 718 | | |
717 | 719 | | |
718 | 720 | | |
| |||
786 | 788 | | |
787 | 789 | | |
788 | 790 | | |
789 | | - | |
| 791 | + | |
790 | 792 | | |
791 | 793 | | |
792 | 794 | | |
793 | | - | |
794 | | - | |
| 795 | + | |
| 796 | + | |
795 | 797 | | |
796 | 798 | | |
797 | 799 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
42 | 46 | | |
43 | 47 | | |
44 | 48 | | |
| |||
0 commit comments