Skip to content

fix(console): the skill download teaches delete_record confirm: true and mirrors the served SKILL.md - #31015

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-gk3fer
Nov 6, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-gk3fer

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

Fixes #30865

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:Console 集成页「Download skill」下载的 SKILL.md 现在与 MCP 服务端下发的文本逐字一致:delete_record 带上 confirm: true 及拒收说明,并补上 list_actions / run_action / resume_run / validate_expression 和 OAuth 接入方式。
  • 为什么改:服务端自 feat(mcp)!: delete_record refuses a call without confirm: true #30861 起拒绝不带 confirm: true 的删除(ACTION_CONFIRMATION_REQUIRED),照旧下载件操作的 AI 代理每次删除都会失败;下载件还漏教了业务动作工具。
  • 风险与回滚:只改一个纯文本渲染函数和它的测试,不碰服务端;回滚即 revert 本 PR。
  • 先看:ui/apps/console/src/pages/developer/objectstack-skill.test.ts(新的漂移钉:从源码导入服务端渲染函数逐字比对)、objectstack-skill.ts 的 Tools 段、changeset。
  • 两分钟验证:pnpm --dir ui exec vitest run apps/console/src/pages/developer/objectstack-skill.test.ts,预期 13 个测试全绿。
  • 需要你做的:无,席位落地。
  • 席位意见:ui 席 2 对照 head 828224c8 的 diff 复核:3 个文件、+158 / −29,无受治理路径。控制台「下载技能」的 SKILL.md 改为与 MCP 服务端 renderSkillMarkdown 无 OAuth 范围时的文本逐字节一致(delete_record 带 confirm: true 及确认规则、补齐 validate_expression、list_actions/run_action/resume_run、OAuth 连接与 Bearer 密钥写法);测试在 node 环境按相对路径从源码导入服务端渲染器,五种参数逐字节比对,另钉住 11 个工具的顺序与删除调用形状,消融两侧各红。只改 packages/mcp/src/skill-md.ts 的 PR 不会触发这条比对(CI 过滤器缺口),已立卡 CI: a pull request that edits only the MCP server's SKILL.md renderer skips the Console test that pins its download mirror #31017。Clause-② no,不欠契约复审。同意落地。

What changes

  • ui/apps/console/src/pages/developer/objectstack-skill.ts: the mirror now renders exactly what renderSkillMarkdown (packages/mcp/src/skill-md.ts) serves to a caller with no OAuth scopes (an API key or a session), which is the data skill with no authoring section and no federation tools. It gains OBJECTSTACK_MCP_SERVER_NAME for the claude mcp add snippet. The header says what it mirrors and which test holds it.
  • objectstack-skill.test.ts: a drift pin. The test runs in the node environment, imports renderSkillMarkdown and the identity constants from source by relative path (the console does not depend on @objectstack/mcp, which is not browser-safe), and asserts byte equality for five option shapes (none, URL, env name, both padded, blank). Explicit pins sit beside it: the ordered tool list (11 tools) and the delete_record call shape with its confirmation sentence. The old "not Bearer" assertion is replaced by an x-api-key header assertion, because the server now teaches Authorization: Bearer as an accepted key form.
  • .changeset/30865-console-skill-download-confirm.md: @object-ui/console patch (the package is not private).

No mirror text differs from the canonical render on purpose, so the pin is full-text equality rather than the tool-list fallback.

Tests

Measured drift before the fix (mirror vs canonical, same URL and env name, origin/main 8ae0ab9)

diff mirror-before.md canonical.md with { mcpUrl: 'https://acme.objectos.app/api/v1/mcp', envName: 'Acme CRM' }: 85 insertions, 16 deletions, 9 hunks.

  1. Intro: canonical names business actions as tools and the OAuth consent-scope bound; the mirror said "runs as you" with data objects only.
  2. When to use: canonical adds "run a business action" and "an action is always better than hand-editing".
  3. Connect: canonical teaches two tracks, OAuth (with the claude mcp add --transport http objectstack URL example) and API key; the mirror taught the API key only.
  4. Accepted headers: canonical accepts Authorization: Bearer KEY too; the mirror named only ApiKey.
  5. Discover: canonical adds step 3, list_actions.
  6. Tools: the mirror lacked validate_expression.
  7. Tools: the mirror taught delete_record({ objectName, recordId }) with no confirm; canonical teaches delete_record({ objectName, recordId, confirm }) and the ACTION_CONFIRMATION_REQUIRED refusal. The mirror also lacked list_actions, run_action and resume_run.
  8. Conventions: canonical adds "Prefer actions over hand-edits".
  9. Recommended workflow: canonical adds list_actions in step 1 and run_action in step 4.

Frontmatter (name, description) was already identical. After the fix: the five equality cases pass, so the diff is empty for every shape tested.

Test run (head 828224c)

pnpm --dir ui exec vitest run apps/console/src/pages/developer/objectstack-skill.test.ts → Test Files 1 passed (1), Tests 13 passed (13).

Ablation (scripts/ablation-replace.mjs, both legs restored to the HEAD blob)
  • Leg 1, the confirm line: - **delete_record({ objectName, recordId, confirm })** — delete a record, → - **delete_record({ objectName, recordId })** — delete a record, in the mirror (anchor 1 → 0, blob 8612fdae0978 → 7cea2fc32802). Result: 6 failed, 7 passed. Red: "teaches delete_record with confirm: true, which the server requires" and all five "renders the canonical text for …" cases. Restored blob 8612fdae0978 == HEAD.
  • Leg 2, a canonical-side edit (shows the pin catches drift from either side): - **Page large reads.** Use → - **Page large reads, always.** Use in packages/mcp/src/skill-md.ts. Result: 5 failed, 8 passed (the five equality cases). Restored, git diff HEAD empty.

No build sits between the test and either mutated file: both are imported from source.

Verification

Local gates (derived with dispatch-gates.mjs --commands against this diff)

Head 828224c88f. 35 derived, 35 run, 0 NOT-MEASURED (dispatch-gates.mjs --ran reconciliation exit 0). Every line exit 0:

node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0

Also pnpm --dir ui exec vitest run apps/console/src/pages/developer/: Test Files 20 passed (20), Tests 165 passed (165). pnpm --dir ui exec vitest run scripts/: Test Files 170 passed, 2 skipped; Tests 4991 passed, 2 skipped.

Console type-check (the relative source import brings packages/mcp/src/skill-md.ts into the console tsc program)

pnpm exec turbo run type-check --concurrency=2 --filter=@object-ui/console → @object-ui/console:type-check: cache miss, executing, Tasks 73 successful, 73 total; lock VERDICT command-exit 0. Also pnpm --dir ui run check:phantom-deps, check:self-import, check:unreferenced-sources: exit 0 each.

Acceptance notes

  • CI scoping blind spot (noted, not filed). The drift pin lives in Test UI. A later PR that changes only packages/mcp/src/skill-md.ts matches neither the ui nor the ui_consumers filter in ci.yml (packages/mcp/** is not among the seven ui_consumers packages), so Test UI does not run on that PR or its queue entry; the pin goes red on the next main scheduled or dispatched full run instead. Closing it needs packages/mcp/src/skill-md.ts in the ui filter, which is root ci.yml and out of this card's bounds. Carrier: seat.
  • Open PRs checked for the serial rule: none touches objectstack-skill.ts, its test or packages/mcp/src/skill-md.ts. feat(i18n)!: the Console's language packs follow the platform locale table, keyed by its tags, and Traditional Chinese (zh-Hant) ships #30902 touches two other test files in ui/apps/console/src/pages/developer/ (consolePagesLocale-13460.test.tsx, flowRunsClientDiagnostic-25916.test.tsx), with no overlap.

…and mirrors the served SKILL.md

The Console's SKILL.md mirror had drifted from renderSkillMarkdown: it taught
delete_record without confirm (now refused with ACTION_CONFIRMATION_REQUIRED)
and lacked list_actions, run_action, resume_run, validate_expression and the
OAuth track. The mirror now renders the canonical default-scope text, and its
test imports the canonical renderer from source and compares byte for byte.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwpdnaEYjR2FGdUuxD
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 6, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#2 · os-tesla · session_01L9qibw7DekEe3wx5f3zphf

席位核对 · ACCEPT · 2026-11-06T17:59Z · head 828224c88f3de41678c1ea7a1cfdd9fec45713c3

Seat domain:ui#2 reviewed the diff of its own dispatch (claim 6690569152 on #30865, card thread session_01L9qibwpdnaEYjR2FGdUuxD, report 6691357143). The same seat dispatched and reviews; the code is the thread's.

  1. Shape: 3 files, +158 / -29. ui/apps/console/src/pages/developer/objectstack-skill.ts now renders the text renderSkillMarkdown (packages/mcp/src/skill-md.ts) serves to a caller with no OAuth scopes, byte for byte. Measured drift was 9 hunks: delete_record without confirm, and missing validate_expression, list_actions, run_action, resume_run, the OAuth track and the Bearer key form. The test runs in the node environment, imports the canonical renderer from source by relative path (the console keeps no dependency on the non-browser-safe @objectstack/mcp), asserts equality over 5 option shapes, and pins the 11-tool order and the delete_record({ objectName, recordId, confirm }) shape. Fixes #30865.
  2. Premise measured: on main the download taught delete_record({ objectName, recordId }), which the server refuses since c77dd17f26 (PR feat(mcp)!: delete_record refuses a call without confirm: true #30861). Per report.
  3. Gates / check-runs: 35 derived gates run, all exit 0, --ran reconciled. Console type-check is green (the relative import brings skill-md.ts into its program). The seat re-ran check:cross-package-test-inputs on this tree: exit 0. Ablation: reverting the confirm line reds 6/13; an edit on the canonical side reds 5/13; both restored to HEAD. Check runs: all success or skipped on this head (55 check runs, 44 success, 11 skipped, 0 red).
  4. Accepted deviation: the test reaches packages/mcp/src by relative path from a ui test, as the order allowed for a drift pin.
  5. Out of scope: filed CI: a pull request that edits only the MCP server's SKILL.md renderer skips the Console test that pins its download mirror #31017 (class b, carrier: seat): a PR touching only packages/mcp/src/skill-md.ts matches neither the ui nor the ui_consumers filter in ci.yml, so this pin skips on that PR and its queue entry. Metadata-protocol: none; Skills-docs: not owed (the mirror is a download, not skills/**).
  6. Landing: check-governed-merges --branch on the final list: not governed, 187 changed lines, so Tier S, with no human approval owed. Clause-②: no, and no packages/spec/src file is touched, so no contract review is owed. Landing on the maintainer's standing words 「按 pm-dispatch 审过的pr你可以自主落地」 (2026-10-30T14:20Z) and 「你应该是使用 pm-dispatch 技能自主审核和落地 pr」 (2026-11-06T14:09Z): relay pr_ready, then automerge_enable. On merge the card closes.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 6, 2026 18:02
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 6, 2026
Merged via the queue into main with commit 7d9f1e9 Nov 6, 2026
60 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-gk3fer branch November 6, 2026 18:24
os-tesla pushed a commit that referenced this pull request Nov 6, 2026
…ords bullet

#31015's drift pin compares the console's renderObjectStackSkill with the
MCP server's renderSkillMarkdown byte for byte; the server's SKILL.md now
teaches delete_records, so the console copy carries the same bullet and the
tool-name pin lists it. The server-side bullet is reflowed to the file's
line width; its words are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibx1NhZMrqCvW7FBxg5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui: Console MCP skill mirror should teach delete_record confirm: true (after #30813)

1 participant