From f7d76284421933afad4b0747e1f43d3c01754350 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 09:41:36 +0000 Subject: [PATCH] fix(spec): list the five service-ai-studio tools the AI registry was omitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio']` omitted five tools the cloud AI runtime actually registers — `get_authoring_rules`, `load_tools`, `open_record`, `test_flow` and `toggle_flow` — so under ADR-0109, where the default authoring path declares no tool records at all, a skill naming any of them resolved against nothing and was reported by `validate`/`lint` as a FICTIONAL tool reference. That is the exact failure the registry exists to end. Added in the list's existing alphabetical order (verified: both groups were in fact sorted before this change, and the package's own shape test pins it). Nothing else in the registry moves. The pin lives in `packages/lint`, where "refused" and "accepted" are the verdicts: the five now resolve, and a sixth name shaped like them and registered by nobody is still reported — the control, without which the widening pin cannot fail. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x --- .../ai-studio-five-registered-tool-names.md | 11 ++++++++ .../src/validate-ai-tool-references.test.ts | 27 +++++++++++++++++++ .../system/constants/platform-tool-names.ts | 5 ++++ 3 files changed, 43 insertions(+) create mode 100644 .changeset/ai-studio-five-registered-tool-names.md diff --git a/.changeset/ai-studio-five-registered-tool-names.md b/.changeset/ai-studio-five-registered-tool-names.md new file mode 100644 index 0000000000..69bd5a7b49 --- /dev/null +++ b/.changeset/ai-studio-five-registered-tool-names.md @@ -0,0 +1,11 @@ +--- +"@objectstack/spec": minor +--- + +`PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio']` lists the five tools the cloud AI runtime registers that it had been omitting: `get_authoring_rules`, `load_tools`, `open_record`, `test_flow` and `toggle_flow`. Added in the list's existing alphabetical order; nothing else in the registry moves. + +The omission was not cosmetic. `PLATFORM_PROVIDED_TOOL_NAMES` is the load-bearing half of `skill.tools[]` reference integrity under ADR-0109 — the default third-party authoring path declares no tool records at all, so a `skill.tools[]` entry resolves against this registry or against the materialised `action_` family and against nothing else. While these five were absent, a skill naming any of them was reported by `validate` / `lint` as a **fictional** tool reference (`ai-skill-tool-unresolved`), which is precisely the failure the registry was created to end. Five previously-refused references are now accepted; a name registered by nobody is still refused. + +The module's own maintenance contract already said why an omission is worse than no registry at all — "an out-of-date registry is worse than no registry, because consumers now trust it" — and a second consumer had already paid for it: `@objectstack/mcp` gives a listed name `openWorldHint: false`, and the Studio's tool-step labels read the same set. + +This is the data half only. Making the owning package's conformance test **derive** the union from what `plugin.ts` actually registers, instead of restating it, is tracked separately in the cloud repository; re-copying the list correctly resets the clock rather than stopping it. diff --git a/packages/lint/src/validate-ai-tool-references.test.ts b/packages/lint/src/validate-ai-tool-references.test.ts index 995d50f1cc..ad94b00c98 100644 --- a/packages/lint/src/validate-ai-tool-references.test.ts +++ b/packages/lint/src/validate-ai-tool-references.test.ts @@ -159,6 +159,33 @@ describe('validate-ai-tool-references', () => { expect(validateAiToolReferences(stack)).toEqual([]); }); + /** + * [#16512] The five `service-ai-studio` tools the cloud runtime registers + * that the registry did not list. + * + * `PLATFORM_PROVIDED_TOOL_NAMES` is the load-bearing half of + * `skill.tools[]` reference integrity under ADR-0109, so while these five + * were absent a skill naming any of them was reported as a FICTIONAL tool — + * the precise failure the registry exists to end. The pin lives here, not + * beside the constant: "refused" and "accepted" are this rule's verdicts, + * and the list's own file can only pin its shape. + */ + it('resolves the five service-ai-studio tools the registry was missing (#16512)', () => { + const five = ['test_flow', 'toggle_flow', 'get_authoring_rules', 'load_tools', 'open_record']; + expect(validateAiToolReferences({ skills: [{ name: 's', tools: five }] })).toEqual([]); + + // The control, without which this pin cannot fail: a sixth name shaped + // exactly like the five and registered by nobody is STILL reported. A + // universe widened until everything resolves would pass the assertion + // above and fail this one. + const control = validateAiToolReferences({ + skills: [{ name: 's', tools: [...five, 'archive_flow'] }], + }); + expect(control).toHaveLength(1); + expect(control[0].path).toBe('skills[0].tools[5]'); + expect(control[0].message).toContain('archive_flow'); + }); + it('reports stable paths and tolerates junk shapes', () => { const stack = { skills: [{ name: 's', tools: ['query_records', 'nope_tool'] }], diff --git a/packages/spec/src/system/constants/platform-tool-names.ts b/packages/spec/src/system/constants/platform-tool-names.ts index aeaa3a67a4..275579d330 100644 --- a/packages/spec/src/system/constants/platform-tool-names.ts +++ b/packages/spec/src/system/constants/platform-tool-names.ts @@ -65,16 +65,21 @@ export const PLATFORM_TOOLS_BY_PACKAGE: Readonly