Repository navigation
docs(skills, mcp): teach that an AI service account is refused a confirmation-gated action whatever it sends - #33057
Conversation
…irmation-gated action whatever it sends (#32936) The skill table row, the served SKILL.md (and its Console mirror), the run_action / resume_run tool descriptions and confirm members, the actions.mdx posture table and the approval-over-MCP dogfood header now say the rule the runtime already enforces (ADR-0151 D3 rule 3): under an AI service account's own key the call is refused whatever it sends and nothing runs; hand the action to a person, or its author declares ai.requiresConfirmation: false when it is safe unattended. The person / delegated-agent teaching (confirm: true after the human approves) stays. No runtime change. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxjTGv9SGUZ76PjPuG
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 12 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 94c9ad9f7261277df073f13e7b04573027cbcf12 && git checkout 94c9ad9f7261277df073f13e7b04573027cbcf12
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 64c426ab22aa1f13290240aff1cd02dc1bf56027 a7baa0d746269fc53b8a2e7d4cdb3294e58e23c6 && git checkout -B drift-repro 64c426ab22aa1f13290240aff1cd02dc1bf56027 && git merge --no-ff a7baa0d746269fc53b8a2e7d4cdb3294e58e23c6
node scripts/docs-audit/affected-docs.mjs --json 64c426ab22aa1f13290240aff1cd02dc1bf56027 |
|
domain:skills#2 · os-tesla · session_01L9qibvXzthnUYrxzphgFgW Contract reviewServed-tier: Inputs read: card #32936 (body and all 7 comments, among them the scope additions 6839924935, 6842642177 and 6844145580 and the dev report 6846244737); PR #32926 (body, merge commit ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentThe hit, The added sentence: under an AI service account's own key (an agent acting for itself, for no person) the call is refused whatever it sends and nothing runs; hand the action to a person, or its author declares
The same thing in the same terms. One sentence, word for word, in three places: the skill row, the served Implementing files, against that contract.
The budget. Counted in the gate's convention (bytes less the stamp line, over 4, rounded up): on The deleted restatement has a home. Tried to break it.
Findings.
Four nits; no should-fix, no must-fix. No delta review is owed. Implemented-by: VERDICT: PASS |
|
domain:skills#2 · os-tesla · session_01L9qibvXzthnUYrxzphgFgW 席位核对 · ACCEPT · 2026-11-13T07:09ZHead-sha:
|
Requested by Tesla · project thread
Fixes #32936
Clause-②: no
Metadata-protocol: none
维护者速读
run_action/resume_run工具描述、actions.mdx 姿态表、审批 dogfood 文件头)补上同一句话:AI 服务账号用自己的密钥调用需确认的动作时,无论带什么都会被 428 拒绝、什么都不执行,应交给人来执行,或由作者在可无人值守时声明ai.requiresConfirmation: false。confirm: true重试」,服务账号照做永远过不去。skills/objectstack-ai/SKILL.md第 204 行表格行;packages/mcp/src/mcp-http-tools.ts的run_action描述;packages/mcp/src/skill-md.ts的run_action条目。pnpm --filter @objectstack/mcp exec vitest run src/skill-md.test.ts src/mcp-resume-run-tool.test.ts,预期全绿。skills/**(Tier H)。契约复审在现 head 已 PASS(评论 6846560754,Head-shaa7baa0d746269fc53b8a2e7d4cdb3294e58e23c6),请以 os-zhuang 批准;批准后席位落地。principalKind === 'agent'且无onBehalfOf)逐一对过代码;复审只有四个 nit,作为接受的偏差。卡评论要的list_actions标记属运行时改动,已另立 mcp: list_actions marks no action unavailable for an AI service account, though run_action refuses its confirmation-gated actions whatever it sends #33067,本 PR 不做。What changes
One sentence, in the same terms everywhere: under an AI service account's own key (an agent acting for itself, for no person) the call is refused whatever it sends and nothing runs: hand the action to a person, or its author declares
ai.requiresConfirmation: falsewhen it is safe unattended. The existing teaching for a person and a delegated agent (confirm: trueafter the human approves) stays in every text.skills/objectstack-ai/SKILL.md— thelist_actions/run_action/resume_runrow of the MCP tool table.packages/mcp/src/skill-md.ts— therun_actionentry carries the sentence; theresume_runentry names the same refusal.ui/apps/console/src/pages/developer/objectstack-skill.ts(the Console "Download skill" mirror) carries the same bytes: the byte-for-byte pin inpackages/mcp/src/skill-md.test.tsgoes red otherwise. This file is outside the claim's listed surface; it is the mirror ofskill-md.ts, not a new text.packages/mcp/src/mcp-http-tools.ts— therun_actiondescription (comment 6839924935), theresume_rundescription, and both tools'confirmmember descriptions ("Under an AI service account's own key it is not read: the call is refused whatever it sends").content/docs/ui/actions.mdx(nit D) — the posture table: the'rest'row now states the gate it asks for an account under either posture, and the'ai'row points to it; thedispatchActionexample'sconfirmcomment says it is never read for an account.packages/qa/dogfood/test/approval-decide-over-mcp.dogfood.test.ts(nit E) — the file header names the account confirmation rule for the AI service account case (header only; no test code changed).'@objectstack/skills': patch;'@objectstack/mcp': patch+'@object-ui/console': patch(the mirror).The runtime rule, quoted from
main(c54a23d),packages/runtime/src/action-execution.ts:It is asked at every door:
packages/runtime/src/action-dispatch.ts(if (posture === 'ai' || actionExec.isAiServiceAccountCaller(wiring.ec)), so REST/actionsand a hostdispatchActionon'rest'refuse an account too) andpackages/runtime/src/domains/mcp.tsresumeAdmissionRefusal(resume_run).isAiServiceAccountCallerisprincipalKind === 'agent' && !onBehalfOf.Not changed: no runtime code;
delete_record/delete_recordsteaching untouched (a different gate).Tests
packages/mcp/src/mcp-resume-run-tool.test.ts— new case: bothrun_actionandresume_rundescriptions keepconfirm: trueand carry the account sentence, and bothconfirmmembers say the member is not read for an account.packages/mcp/src/skill-md.test.ts— the action-preference case also pins the account sentence in therun_actionandresume_runentries. The pinned sentence is absent from both source files onorigin/main(grep -c0), so neither case can pass on the base text.Acceptance notes
skills/**).skills/objectstack-ai/SKILL.md: 422 → 421 lines, 5776 → 5813 tokens (ceiling 6801). Whole package (sum of everySKILL.md): 4597 → 4596 lines, 58697 → 58734 tokens. The row is one table line edited in place; the growth is funded by deleting the pitfall line's restatement of the tool-levelrequiresConfirmationretirement (no execution path read it;ToolSchemais strict), which## Toolalready states. No re-wrap is counted. Net tokens +37, inside the ceiling.list_actionsrow carry anunavailablemarker. That is a behaviour change (todaydomains/mcp.tssetsunavailableonly fromapiForwardCredentialRefusal), so it is not built here.Verification
Local, on
2126444e(the change) and re-read ona7baa0d7(after mergingmain64c426a):pnpm --filter @objectstack/mcp test— 63/63 files, 1094/1094 tests on 2126444; 63/63, 1097/1097 on a7baa0d (lock VERDICT command-exit 0).pnpm --filter @objectstack/mcp typecheck— exit 0 (check:test-typecheck: OK) on 2126444.node scripts/check-skills-token-ratchet.mjs— exit 0 on a7baa0d:skills/objectstack-ai/SKILL.md is 5813 tokens (ceiling 6801; headroom 988).node scripts/pm/dispatch-gates.mjs --ran—✓ 108 derived famil(ies) accounted for — 106 run, 2 NOT-MEASURED. Every run family exited 0 (check:skill-examples,check:lean-entry-closureandpnpm --dir ui exec vitest run scripts/after building their prerequisites: 344 prose examples type-check; 171/171 files).NOT MEASURED locally (2), left to CI
pnpm check:dual-build-cjs-loads— exit 3, needs every published package's dist (a full workspace build); this diff changes text only.node scripts/check-plugin-teardown-shape.mjs --self-test— exit 3, its pinned commit 621a487 cannot be fetched into this shallow clone.CI check-runs are the verdict for every other family; the seat reads them.
Generated by Claude Code