Uh oh!
There was an error while loading. Please reload this page.
fix(ai): author the canonical agent id everywhere the platform teaches one (#14461) - #14780
Conversation
…s one (#14461) `skills/objectstack-ai` tells authors `data_chat` / `metadata_assistant` are "not vocabulary — always write `ask` / `build`", and every live example the platform shipped taught the opposite. Measured rather than assumed — the card left this undecidable because the consumer lives in the closed `cloud` repo. At `cloud` main@3856fbf7, `service-ai-studio/src/agents/metadata-assistant-agent.ts:12,40` ships the record as `name: BUILD_AGENT_NAME` = 'build' and `plugin.ts:58` registers `metadata_assistant` as a one-way, resolution-only legacy alias. The canonical id IS `build`; the reading that made this a ruling is falsified. - `studio.app.ts` — the repo's only `app.defaultAgent` usage, re-pinned from the alias to `'build'`. Not cosmetic: alias resolution depends on an in-memory `registerAgentAlias` call having run, which cloud documents silently no-op'ing under bundle load ordering; the canonical id never touches the alias table. - `mcp-server-runtime.ts` — the `agent_prompt` `agentName` example named two retired aliases and neither canonical id, to every MCP client that asked. - `validate-ai-agent-authoring` — the value limb reused the four-name roster, so the gate deliberately passed the spelling the catalogue bans. The two limbs now read different tables: declaration keeps all four (shadowing is shadowing), value takes `ask` / `build` with legacy aliases under their own rule id `default-agent-legacy-alias`, because an alias resolves and an unknown name does not. #6041's operative decisions are intact — warning tier, no Zod enum. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 17 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 5d575e9eb27f9d5603d454353bcf4eb69d1bba11 && git checkout 5d575e9eb27f9d5603d454353bcf4eb69d1bba11
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin df657d9df1fac5a2222f183008532613a1df585f 2a18188f8d6899b85f3090ea849eebe2ec4aa697 && git checkout -B drift-repro df657d9df1fac5a2222f183008532613a1df585f && git merge --no-ff 2a18188f8d6899b85f3090ea849eebe2ec4aa697
node scripts/docs-audit/affected-docs.mjs --json df657d9df1fac5a2222f183008532613a1df585f
|
Uh oh!
There was an error while loading. Please reload this page.
Closes#14461. Maintainer ruling (2026-09-03): option A, full — Studio re-pinned, MCP example corrected, lint value roster narrowed.
The finding, and the one thing that made it a ruling
skills/objectstack-aitells authors thatdata_chatandmetadata_assistant"are not vocabulary — always writeask/build". Every live example the platform shipped taught the opposite. The card could not decide which side moves, because the deciding fact lived in the closedcloudrepo: doesservice-ai-studioregister under the legacy id? If it did, re-pinning would be a behaviour change in a consumer this repo cannot see.Measured, not assumed. At
cloudmain@3856fbf7:The alias table is one-way, legacy→canonical, and
service-ai/src/agents/agent-aliases.ts:20-23states it is "resolution-only: they are NOT separate metadata records". The canonical id isbuild. The reading that made this undecidable is falsified; the skill's sentence was right and the code was residue.Three sites, one spelling
1.
studio.app.ts— the repo's onlyapp.defaultAgentusage.This is not cosmetic. The alias resolves only if an in-memory
registerAgentAliascall has actually run, and cloud carries two defensive docblocks about that registration silently no-op'ing for real under bundle load ordering —service-ai-studio/src/plugin.ts:44-57(use the string constant, neverAGENT.name, or the guard no-ops and "dropsbuildfrom both the legacy alias AND the framework'slistAgentscatalog") andservice-ai/src/agent-runtime.ts:30-41("a missed alias must never hide a real platform agent likebuild"). The canonical id never touches the alias table, so the re-pin removes a load-order dependency from the platform's own flagship authoring surface.Nothing moves on the UI side:
objectui'sAGENT_ALIAS_GROUPSis bidirectional and canonical-first (['build','metadata_assistant']),surfaceAgent.ts:82bounds the key by group membership, andSURFACE_DEFAULT['studio-build']was already'build'. Measured atobjectuimain@e3784607f.2.
mcp-server-runtime.ts:1349— a site the card's census did not reach, and the louder one, because it is served to LLM clients at runtime:Two retired aliases, neither canonical id present. Every MCP client asking what to pass was handed the exact two spellings the catalogue forbids.
3.
validate-ai-agent-authoring— the gate itself. ThedefaultAgentvalue limb reused the four-namePLATFORM_AGENT_NAMESset, so it deliberately acceptedmetadata_assistant. The rule that exists to make authoring mistakes loud waved through the banned spelling — the silent-tolerance shape ADR-0078 exists to close, committed by the gate.The two limbs now read different tables, because they ask different questions:
metadata_assistantshadowsbuildthrough the alias exactly as declaringbuilddoesask/builddefault-agent-legacy-alias(exported)Separate rule ids because the two defects are genuinely different: an alias resolves (the app gets the agent it meant — a spelling defect), an unknown name does not (the pin is inert). A message describing the alias as "has no effect" would send an author hunting a bug that is not there; there is a test pinning exactly that distinction.
#6041's ruling is intact. Its two operative decisions were warning tier, not error and no Zod enum narrowing. Both stand.
defaultAgent: 'metadata_assistant'still parses, still builds, still resolves — the only change is that authoring it now says so.Two corrections to the card's suggested inputs
defaultAgentappears inpackages/platform-objectsonly atstudio.app.ts:48,50— the comment and the value. One-liner plus its comment; nothing to update.packages/spec/src/migrations/entries/retired-keys/(76 entries) is keyed<domain>/<Type>:<key>— it records retired keys.metadata_assistantis a retired value of a live key, which that registry has no shape for. The residue is recorded where it will actually be read instead: the pin site's comment, the rule's docblock, and the tests. A value-level ledger shape is a separate card if it is wanted.Verification
@objectstack/lintreference-integrity-suitemembership)@objectstack/mcp@objectstack/platform-objectsturbo buildgreen for all three (dts emitted)check:skill-identifier-liveness,check:corpus-claim-drift,check:doc-authoring,check:empty-changeset,check:adr-0087-registration,check:changeset-gate-self-tests— all EXIT=0Not breaking: nothing an author can write was removed, and both aliases stay resolvable for old bookmarks and persisted
agent_ids — the only job ADR-0063 §2 ever gave them.🤖 Generated with Claude Code