Uh oh!
There was an error while loading. Please reload this page.
feat(spec): declare mcp:connect-agent in ComponentPropsMap — undeclared keys refused; retire the mcp door-3 exemption (#12344) - #12467
Conversation
…e mcp door-3 exemption (#12344) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
…nknown-keys-refused Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 126 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 2e7df53a2a61b7da64800d685ab12b6f93942a1b && git checkout 2e7df53a2a61b7da64800d685ab12b6f93942a1b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 76c18be8ad56400c85cde381e63c7755bbd6153a 3a65c5d5a2dc5c511d581d55eae7758bdce00dcc && git checkout -B drift-repro 76c18be8ad56400c85cde381e63c7755bbd6153a && git merge --no-ff 3a65c5d5a2dc5c511d581d55eae7758bdce00dcc
node scripts/docs-audit/affected-docs.mjs --json 76c18be8ad56400c85cde381e63c7755bbd6153a
|
…nnect-agent-props-row # Conflicts: # packages/spec/src/migrations/registry.ts
…nnect-agent-props-row
…12344) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
Fixes#12344
Closure A per the 2026-08-25 retriage charter (cross-domain single PR via the exception path, spec-seat-designated): a strict
ComponentPropsMaprow formcp:connect-agent, measured from the objectui renderer's real read points at the current.objectui-shapin, then the standing door-3 exemption and its two guard pins deleted from the mcp canonical-envelope gate. Family precedent: #11575 (PR #11743), followed file-for-file.The measurement (population + control)
Pin resolved from
.objectui-shaat this branch's base:190fbd01d0615e2e168faf9e08b8ad7844bc039d.packages/app-shell/src/console/connect/ConnectAgentWidget.tsx:335—ComponentRegistry.register('mcp:connect-agent', () => <ConnectAgent />, { …, inputs: [] }). The render function discards the schema node entirely andConnectAgent()(line 101) takes no parameters; every value it renders comes from/discovery, i18n and its own component state. Accepted key set: EMPTY — the row is strict-and-empty (emptyProps('mcp:connect-agent')), which is what refuses an undeclared key.git grep "mcp:connect-agent"at the pin returns exactly one registration and one component function (plus two name-list entries inpackages/cli/src/utils/known-schema-types.tsand CHANGELOG rows — not read points).ConnectAgentis referenced only by its own registration and the side-effect import inapp-shell/src/index.ts:258.cloud:ai-model-status(CloudAiModelStatus.tsx:231, same pin) finds a registration that binds(props: CloudAiModelStatusProps)and spreads them into the component — a non-empty read set where one exists.inputs: []happens to agree; the row is the measurement, not the claim (spec:record:reference_railhas no ComponentPropsMap row — an entryfilterparses, typechecks, validates, ships, and silently does nothing #8691/spec:record:alert/record:quick_actions/record:historyhave no ComponentPropsMap row — same silent no-op mechanism #8691 closed for the rail #8744 record where those diverge).What changed
packages/spec/src/ui/component.zod.ts—'mcp:connect-agent': emptyProps('mcp:connect-agent')row (plugin console widgets section), with the measurement recorded in place;emptyPropsdocblock now lists the type.packages/mcp/src/canonical-expression-envelopes.test.ts—exemptUnmappedTypes: ['mcp:connect-agent']→[]; the props-bag-EMPTY pin and the non-vacuity pin deleted (with the exemption gone, both would pass vacuously — the machinery's description survives in the module header for the next exemption); unusedwalkPageComponentsimport removed. The door-3 EXACT assert stays and now demands the empty set.packages/spec/src/ui/component.test.ts— row-defined / accepts-{}/ refuses-any-key-naming-the-surface pins (the feat(spec): declare cloud-connection:panel / marketplace:installed-list in ComponentPropsMap — undeclared keys refused (#11575) #11743 shape).packages/lint/src/validate-component-props.test.ts— dispatch pins: an authored key onmcp:connect-agentis oneCOMPONENT_PROPS_UNKNOWN_KEYfinding; the shipped page's empty bag stays silent.packages/spec/src/migrations/entries/semantic/18.ui-mcp-connect-agent-unknown-keys-refused.ts+ regeneratedregistry.tsblock — ADR-0087 semantic entry, protocol major 18..changeset/ui-mcp-connect-agent-unknown-keys-refused.md—@objectstack/specminor, BREAKING accept-set narrowing with FROM → TO and the registered adr-0087 marker (the feat(spec): declare cloud-connection:panel / marketplace:installed-list in ComponentPropsMap — undeclared keys refused (#11575) #11743 convention).What changes hands (content limb): an undeclared key in this widget's props bag was previously unvalidated-pass (silent no-op — the walker skipped the unmapped type) and is now refused by the #5068 lint gate and the strict row. Nothing previously validated is re-judged; the empty bag the shipped page (
connect_agent,packages/mcp/src/connect-ui.ts) authors stays accepted byte-identically. No governed surface is touched. Clause-②: no — declared=enforced restored, no accepted surface widened.Gate evidence — all on
8886708(final commit; clean tree)Test Files 1 passed · Tests 11 passed (11)). Reverse verification (committed-state mutation): re-addingexemptUnmappedTypes: ['mcp:connect-agent']over the landed row reds the EXACT assert (Tests 1 failed | 10 passed,unmapped component types are EXACTLY the recorded exemptions) — the charter's "reds until they go", observed in the expected direction (the exemption is now vacuous vsunmappedTypes: []). Mutation confirmed on disk by anchoredgrep -c(1→0 / 0→1); no build limb (vitest reads the test source directly); restore proven bygit hash-object== HEAD blob (aa84f1de…, byte-identical) and cleangit diff HEAD.vitest: mcpcanonical-expression-envelopes.test.ts11/11 · specui/component.test.ts228/228 · lintvalidate-component-props.test.ts45/45.pnpm --filter @objectstack/spec check:generated— all 14 artifacts up to date (registry regenerated viagen:migration-registry; nothing else stale).node scripts/pm/dispatch-gates.mjs, 7 paths vs merge-base68c5dba): all 27 matched families run locally, exit 0 — incl.check:adr-0087-registration,check:changeset-gate-self-tests,check:cross-package-test-inputs,check:merge-driver,check:page-declaration-shape,check:type-check-coverage,check:type-check-debt(post fullturbo build, 70/70),check:engine-double-contract,check:where-matcher,check:nul-bytes, docs-audit pair,release-rehearsal-clone --self-test.pnpm lint(eslint . --no-inline-config) — whole-repo sweep, exit 0 (54s under the shared verify lock; no narrowing needed).typecheck: spec / lint / mcp all green (script echo verified). Honest scope note: lint's and mcp'stsc --noEmitprograms exclude**/*.test.ts(--listFileshit count 0 for the edited test files), so their green is NOT a type measurement of the new test code — that is the repo's ledgered hidden-test steady state (check:type-check-coveragedocuments it; both coverage gates green). spec'stsconfig.test.jsonprogram DOES includeui/component.test.ts(--listFileshit count 1). The vitest runs above are the executed measurement for all three files.Deviations
cloud-connection:panelandmarketplace:installed-listhave no ComponentPropsMap row — two more instances of the #8691/#8744 silent no-op class #11575 precedent the charter binds to:packages/lint/src/validate-component-props.test.ts(dispatch pins) and the spec migrations entry/registry — declared in the amended claim comment onmcp:connect-agenthas noComponentPropsMaprow — door 3 of the canonical-envelope gate is blind to its props, and the gate now carries a standing exemption for it #12344.skills/**files touched (no line-budget reading owed).skip-changesetnot applicable — this PR carries a real changeset.🤖 Generated with Claude Code
https://claude.ai/code/session_01E5LFCYBJ3q2s6yW6oMLxwy
Generated by Claude Code
Generated by Claude Code