Skip to content

fix(app-shell): ToolPreview 不再渲染已退役的 ToolSchema 标记徽标 (#3236) - #3258

Merged
xuyushun441-sys merged 1 commit into
mainfrom
claude/issue-3236-toolpreview-requiresconfirmation
Aug 3, 2026
Merged

fix(app-shell): ToolPreview 不再渲染已退役的 ToolSchema 标记徽标 (#3236)#3258
xuyushun441-sys merged 1 commit into
mainfrom
claude/issue-3236-toolpreview-requiresconfirmation

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

Fixes #3236

改了什么

packages/app-shell/src/views/metadata-admin/previews/ToolPreview.tsx 的头部条原先直接从 raw draft 上读四个键、每个画一枚 pill。四个键全部已从 @objectstack/specToolSchema 移除,现已删除:

原渲染 退役出处
requiresConfirmation Requires confirmation(琥珀色 + 警告图标) objectstack#3715 / ADR-0033 §2(16.x 线)
active Active / Disabled objectstack#3896(17.0.0 审计关闭)
builtIn built-in objectstack#3896
category 分类标签 pill objectstack#3896

保留的头部条内容:label、机器名、以及 objectName pill(objectName 仍是 spec 认的键)。参数表、Example LLM Call、Output Schema 一律未动。Pilltone(green/amber)词汇随徽标一起删掉 —— 删完已无调用者,留着正是徽标长回来的入口。

active / builtIn 的核实结论(issue 要求先核实再动)

已核实,确属同型残留,一并清理。 不是照着 issue 猜的,是对着本仓实际安装的 @objectstack/spec@17.0.0-rc.1 跑出来的:

ToolSchema present: true
requiresConfirmation  => REJECTED: Unrecognized key(s) on the tool definition: `requiresConfirmation`. …
active                => REJECTED: Unrecognized key(s) on the tool definition: `active`. …
builtIn               => REJECTED: Unrecognized key(s) on the tool definition: `builtIn`. …
category              => REJECTED: Unrecognized key(s) on the tool definition: `category`. …
permissions           => REJECTED: Unrecognized key(s) on the tool definition: `permissions`. …
objectName+outputSchema => ACCEPTED

spec 源码里的注释也把这四个并列写死了:「categorypermissionsactivebuiltIn 由 2026-07 #3896 安全审计关闭一并移除」。

顺带发现:category 也是同型残留(issue 只点了 active/builtIn)。它由同一次 #3896 移除、在同一条头部条上渲染,是同一次核实查出来的,因此一并删,单独在这里说明。permissions 本预览从未读取,无需处理。

为什么这不是"少画个徽标"的小事

spec 已 .strict() 具名拒收,所以元数据带不进来 —— 但退役前入库的陈旧存量行仍带着这些键,预览照亮不误。危害方向是明确的:

  • Requires confirmation 在宣传一个从未存在的安全暂停。没有任何执行路径读过它 —— 不是 LLM tool set(工具只以 name/description/parameters 到达模型)、不是 ToolRegistry.execute、不是 POST /ai/tools/:name/execute。审阅者看到一个破坏性工具被标成"有确认门",而它并没有。真正的门是 action.ai.requiresConfirmation + HITL 审批队列。
  • Disabled 宣称工具已被撤下,而 ToolRegistry.getAll() 仍在把它交给 LLM、execute 路由仍在跑它。

即 objectui#2962 的同型形状:一个 UI 徽标宣传运行时并不兑现的能力

测试(objectui#3236 要求的钉子)

新增 packages/app-shell/src/views/metadata-admin/previews/ToolPreview.test.tsx:喂一个仍带全部四个退役键的陈旧 draft(requiresConfirmation: trueactive: falsebuiltIn: truecategory: 'data'),断言一枚都不渲染;另有正向断言,保证 label / 机器名 / description / objectName pill / 参数表 / Example LLM Call 都还在。

反向验证做了:把徽标分支临时加回去,断言确实会红(不是永远为真的空断言):

FAIL |dom| ToolPreview.test.tsx > renders no confirmation badge for a stale draft with requiresConfirmation: true
AssertionError: expected < span class="text-foreground "> < /span> to be null
- Expected: null
+ Received: < span class="text-foreground "> Requires confirmation < /span>
 ❯ ToolPreview.test.tsx:62:58
…
 Test Files  1 failed (1)
      Tests  3 failed | 4 passed (7)

删掉徽标后:

 Test Files  1 passed (1)
      Tests  7 passed (7)

同目录/同视图回归(root config,含全部 metadata-admin 测试):

pnpm vitest run packages/app-shell/src/views/metadata-admin --maxWorkers=2
 Test Files  118 passed (118)
      Tests  1045 passed | 1 skipped (1046)
pnpm --filter @object-ui/app-shell test     → 19 files / 153 tests passed
pnpm --filter @object-ui/app-shell type-check → 通过(tsc --noEmit && tsc -p tsconfig.typetests.json)
eslint(两个改动文件)                        → 0 error(2 条既有 react-hooks/exhaustive-deps warning,与本次改动无关)

Changeset

已加 .changeset/toolpreview-drop-retired-flag-pills.md(@object-ui/app-shell: patch)。判断依据:虽然是纯删代码,但用户可见 —— admin 预览里几枚徽标消失了(其中 Active 是以前无条件渲染的),审阅 tool 元数据的人会直接看到差别,该进 release notes。按 AGENTS.md 版本策略不声明 major;check-changeset-no-major.mjscheck-changeset-fixed.mjs 均已本地跑过通过。

范围外发现

apps/console/src/preview-samples.tstool 样例仍带 category / active / requiresConfirmation 三个已退役键 —— 同型残留,但在 apps/console 而非本次 scope fence(packages/app-shell)内,未在本 PR 改动,已另开 #3257 记录。

除此之外,全仓扫描(packages/ apps/ content/ examples/ e2e/)已无其他 requiresConfirmation / tool builtIn 残留。

🤖 Generated with Claude Code

https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa


Generated by Claude Code

…3236)

The tool preview's header strip read four keys straight off the raw draft
and painted a pill for each: `requiresConfirmation`, `active`, `builtIn`
and `category`. All four were removed from `@objectstack/spec`'s
`ToolSchema` — `requiresConfirmation` in the 16.x line (objectstack#3715,
ADR-0033 §2) and the other three in 17.0.0 (objectstack#3896). The schema
is `.strict()` and rejects each by name, verified against the
`@objectstack/spec@17.0.0-rc.1` this repo depends on.

New metadata cannot reach these pills, but rows stored before the removals
still carry the keys and kept lighting them up. `Requires confirmation`
advertised a safety pause no execution path performs (the real gate is
`action.ai.requiresConfirmation` + the HITL approval queue) and `Disabled`
claimed a withdrawal while the registry kept handing the tool to the LLM —
the objectui#2962 shape of a badge advertising a capability the runtime
does not have.

Deleted the reads, the pills, and the now-callerless `tone` vocabulary on
the `Pill` helper. Added ToolPreview.test.tsx, which feeds a stale draft
carrying all four keys and asserts none of them renders.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 3, 2026 8:00am

Request Review

@github-actions github-actions Bot added the tests label Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 28.1 KB 350 KB
Entry file index-Drs0AfrH.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.47KB 3.09KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.12KB 3.41KB
auth (LoginForm.js) 17.86KB 5.29KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.43KB 2.09KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.25KB 0.53KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 476.12KB 104.47KB
core (index.js) 2.25KB 0.80KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 136.23KB 34.75KB
fields (index.js) 223.34KB 54.63KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.46KB 0.96KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 5.37KB 1.72KB
i18n (useObjectLabel.js) 26.14KB 6.07KB
i18n (useSafeTranslation.js) 3.26KB 1.44KB
layout (index.js) 37.91KB 10.53KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.05KB 1.53KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.90KB 12.35KB
plugin-charts (index.js) 60.53KB 17.12KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 111.87KB 28.82KB
plugin-designer (index.js) 210.51KB 42.50KB
plugin-detail (index.js) 230.54KB 56.77KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 111.39KB 26.94KB
plugin-gantt (index.js) 162.26KB 39.53KB
plugin-grid (index.js) 185.04KB 49.00KB
plugin-kanban (index.js) 47.82KB 13.18KB
plugin-list (index.js) 104.86KB 25.30KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 40.48KB 10.57KB
plugin-timeline (index.js) 25.76KB 7.32KB
plugin-tree (index.js) 8.34KB 2.82KB
plugin-view (index.js) 83.54KB 20.39KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 2.46KB 1.21KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@xuyushun441-sys
xuyushun441-sys marked this pull request as ready for review August 3, 2026 08:02
@xuyushun441-sys
xuyushun441-sys added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 30ac2e1 Aug 3, 2026
17 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the claude/issue-3236-toolpreview-requiresconfirmation branch August 3, 2026 08:03
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.

ToolPreview 仍渲染已退役的 requiresConfirmation 徽标 —— spec 侧 #3715 prune 的最后一处残留

2 participants