Repository navigation
docs(skills): the automation mcp recipe teaches the providerConfig.toolsSnapshot pin - #28597
Conversation
…olsSnapshot pin One paragraph under recipe 2 (remote MCP): what toolsSnapshot pins and that a pinned name include leaves out is refused at boot; where the digests come from (computeMcpToolsSnapshot, or the served digest the degraded reason prints); what an author sees when a pin no longer matches; the link to the connectors page. Paid for under the skills token ratchet by deleting restatements in the same file that keep a home elsewhere; the file lands at 2487/2488 tokens. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…quires rule, fix the docs table row Review round on the mcp recipe's toolsSnapshot paragraph: a pinned tool the server no longer lists takes the credential path when the instance's credential reached the server (recipe 2's bearer over http does) and CONNECTOR_UPSTREAM_CHANGED otherwise, read off credentialSent in mcp-provider.ts; the "keep automation in requires whenever a connector is declared" rule is restored; the connectors page's failure-mode row for the pin now says the same two cases as its prose and the code. Paid under the skills token ratchet by same-file cuts with a surviving home; the file lands at 2488/2488 tokens. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…ith skills-homed restatements Review round 2: "(an agent or API key is refused)" and the vendor redirect to GET .../connectors/oauth/callback return to recipe 6 (the eval expects the latter). Paid under the skills token ratchet only with text restated elsewhere in skills/: the scheduled-run trigger-user comment (examples-flows.md), the organization-pinning comment (SKILL.md's runAs system rule), the WeChat aside's "write no plugin" half (SKILL.md § Integrations), and a wording tightening in the toolsSnapshot paragraph that drops no fact. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U Contract reviewServed-tier: Isolated full review ①–④ at the ① Derived judgmentsAccuracy of the
The edited Losses — every deleted or shortened line of the recipe file, with its home on this branch (git grep at
The two restored guardrails are present at head: Weighing the four docs-only losses (does losing it from the skill make an AI-authored app more likely to be wrong?):
② Semver level
③ Boundary flags
④ Design judgmentAgainst the card's own test — "would an app-authoring agent reading the skills first author an MCP connector app with no protection against a server silently changing what a tool means?" — the paragraph now closes that exposure in the one place the recipe already shows Must-fix: none. Should-fix (none blocks the hand-off; each fits the 6-token / 24-byte headroom on its own, not all together — pick or let the maintainer pick):
Implemented-by: VERDICT: PASS |
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U 席位核对ACCEPT at head
维护者速读
席位意见:建议按现状批准。这一段讲的每一句都和代码对得上,评审员逐句核对过。两个可选改动都不影响正确性:大写摘要会在启动时直接报错,不会悄悄失效; |
Fixes #28582
Clause-②: no
Metadata-protocol: none
维护者速读
skills/objectstack-automation/references/integration-recipes.md的mcp配方(第 2 则,GitHub 远程 MCP)新增一段,教providerConfig.toolsSnapshot钉住工具定义:钉的是什么、钉名必须在include里、摘要从哪来(computeMcpToolsSnapshot,或占位钉后读降级原因里打印的实际摘要)、钉不匹配时作者看到什么,并链接 connectors 文档的 pin 小节;配套一个@objectstack/skills的patchchangeset。skills/**(Tier H);写应用的 agent 先读 skills,配方里没有 pin 就等于每个 MCP 应用都不设防,服务端悄悄改一个工具的含义不会被发现。packages/connectors/connector-mcp/src/mcp-provider.ts与tool-snapshot.ts在本基点的实现写成,没有运行时不兑现的键。integration-recipes.md第 2 则代码块后的新段(唯一的新增内容);② 同文件为付 token 棘轮而删掉的几处重复(Holds 的input条、第 4 则的签名格式句、第 6 则的连接细节、WeChat 条的括号)——每处在 SKILL.md、objectstack-platform 或 connectors 文档页另有原文;③.changeset/28582-skills-mcp-tools-snapshot.md。node scripts/check-skills-token-ratchet.mjs,预期看到integration-recipes.md is 2487 tokens (ceiling 2488; headroom 1),且结尾57 authored bundle file(s) within their ceilings。skills/**是 Tier H,本 PR 等待维护者批准或合入;无其他动作。What changes
skills/objectstack-automation/references/integration-recipes.md, recipe 2 (remote MCP server): one paragraph after the code block teachingproviderConfig.toolsSnapshot— tool name → sha256 of the tool'stools/listdefinition; a pinned nameincludeleaves out is refused at boot; digests fromcomputeMcpToolsSnapshot(tools)(@objectstack/connector-mcp) or, with a 64-hex placeholder pin, from the served digest the degraded reason prints; a pinned tool served differently degrades the instance with no actions (CONNECTOR_UPSTREAM_CHANGED), one no longer listed too, with the reason onGET /api/v1/automation/connectorsnaming each tool and the digest it now serves; link to the connectors page's pin section. Every clause is read offpackages/connectors/connector-mcp/src/mcp-provider.ts(parseToolsSnapshot, the include-coverage refusal,compareToolsSnapshot,toolsSnapshotDriftError,pinnedToolsHiddenError) andtool-snapshot.tsat the base commitcd065d36; no example block is added.inputbullet's{…}-token refusal and "os validatedoes not judge theinputSchemafit yet" (verbatim in SKILL.md'sconnector_actionrow); recipe 4'sx-objectstack-signatureformat (SKILL.md § Inbound webhook, Signature; the recipe now points there); the intro'splugins:/requiresreminder (objectstack-platform SKILL.md, therequirestable and its "Keepautomationwheneverplugins:lists a connector" bullet); recipe 6's "(organization admins by default)", "for the admin to open" and "GETreads the status;DELETErevokes" (the connectors page); recipe 2's "folded into the request headers" aside and recipe 4's// no trigger user(recipe 1's own comment); the WeChat bullet'salipay-v3aside (the Holdsauthlist). The file lands at 2487 tokens against its 2488 ceiling; no ceiling moves..changeset/28582-skills-mcp-tools-snapshot.md:@objectstack/skillspatch(theskills/**tree ships as that package), carryingClause-②: noandMetadata-protocol: none.Skills readings (
skills/**diff — line and token counts, before → after)cd065d36)64882e22)integration-recipes.md, linesintegration-recipes.md, bytes / ratchet tokensskills/**, lines (every tracked file)SKILL.mdfiles, lines (sum of 11)check-skills-token-ratchetbundle total)Net content is a small deletion (−3 bytes, −1 token); the two added lines are wrap, not growth.
Tests
integration-recipes.md is 2496 tokens; the ratchet ceiling is 2488 (over by 8), exit 1 — and after the last cut it is green at 2487/2488, exit 0 (log below). That red→green is the reading that the gate prices this file.grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'→ no match (exit 1).Acceptance notes
include, the recipe already showsinclude, and an app author has a no-code path to the digests — pin a 64-hex placeholder, boot, and read the served digest off the degraded reason onGET /api/v1/automation/connectors(toolsSnapshotDriftErrorprintstool 'X' changed (it now hashes to …)).computeMcpToolsSnapshot(tools)is exported for anyone with a tool list in code; there is no CLI command that prints a server's digests today (a finding, not a defect: the docs page says the same and the placeholder route is what the runtime delivers).authreached the server (pinnedToolsHiddenError, a 403 naming both causes). The recipe says such a tool "degrades it too" without naming the code, which is true on both paths; the linked pin section carries the rest.carrier: none):connectors.mdx's failure-mode table row for the pin folds the "no longer listed" case underCONNECTOR_UPSTREAM_CHANGED, while the prose above it andmcp-provider.tsroute that case through the credential-rejected path when the instance's credential reached the server; the prose is correct and the row is a summary, so this is read as a precision note, not a contract violation.Skills-docs:line: not owed (Clause-②: no,Metadata-protocol: none).Verification
Final head
64882e22(git rev-parse --short HEADat the time of the sweep; the working tree had no further edits). Gate list derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff (2 paths vs merge basecd065d36), every command run with its exit captured before any pipe, then reconciled with--ran.✓ dispatch-gates --ran: 44 derived famil(ies) accounted for — 40 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3).— 0 UNRUN.check-skills-token-ratchet(check-skills-token-ratchet: skills/objectstack-automation/references/integration-recipes.md is 2487 tokens (ceiling 2488; headroom 1).),check:skill-identifier-liveness,check:skill-frame-sync,check:skill-compatibility,@objectstack/spec check:skill-refs,check:nul-bytes,check:doc-authoring,check:pm-skill-id-lint,check:empty-changeset,check:changeset-no-major,check:adr-0087-registration,check:closing-keyword-parity.@objectstack/lint check:doc-formula-expressionsfirst answered exit 3 (its@objectstack/formula/@objectstack/lintdist absent in a fresh worktree); afterturbo run build --filter=@objectstack/formula --filter=@objectstack/lintunderos-verify-lock.sh(VERDICT command-exit 0) it re-ran green, exit 0.PREREQUISITE NOT MET— each reads thedist/of the whole 129-package closure, which this diff does not touch):check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content. CI runs them after its build; read them off this PR's check-runs.integration-recipes.md is 2496 tokens; the ratchet ceiling is 2488 (over by 8)(exit 1), then the final green above (exit 0).pnpm lint,test:repoand the rest of the repo-wide farm (CI'sLint & Repo Gates,Test Core); no package test or typecheck is owed by a diff that touches no package.check:dev-prereqs,check:skill-frame-freshness): the derivation did not name them and the diff touches no four-axis frame file orpackages/specbuild, so they were not run.Run record (`ran.list`, the input to `--ran`): 44 commands with exit codes
`check-skills-token-ratchet` final lines on `64882e22`
Generated by Claude Code