Measured while compiling packages/plugin-ai/README.md's snippets for objectui#5174 batch 27 (PR to follow). Not fixed there — that batch's licence is the README and one ledger entry, and ⛔ no edit to packages/plugin-ai/src/** or packages/types/src/**. Filing so the shape is not lost.
This is the plugin-ai instance of the class objectui#7742 already carries for KanbanSchema (three zero-read members + one undeclared read, enforce-or-remove). objectui#5098 was the plugin-form README instance of the same thing. Nothing here is a duplicate of either: different package, different keys.
What was measured
Every key below is declared by its schema type in packages/types/src/ai.ts and never read by the component that the schema drives. The three components in packages/plugin-ai/src/ are the only consumers of these three types repo-wide (grep -rln over packages/*/src and apps/*/src returns the three components plus the declaration and the barrel).
| Key |
Declared |
Read at runtime? |
Note |
AIFormAssistSchema.formId |
ai.ts:97 |
no — zero occurrences in AIFormAssist.tsx |
|
AIFormAssistSchema.objectName |
ai.ts:102 |
no — zero occurrences |
|
AIFormAssistSchema.fields |
ai.ts:107 |
no — zero occurrences |
|
AIFormAssistSchema.autoFill |
ai.ts:127 |
dead read — destructured at AIFormAssist.tsx:31 with a default, never referenced again |
the only occurrence of the identifier in the file is that destructure |
AIRecommendationsSchema.objectName |
ai.ts:209 |
no — zero occurrences in AIRecommendations.tsx |
|
AIRecommendationsSchema.maxResults |
ai.ts:229 |
no — zero occurrences |
see below |
NLQuerySchema.objectName |
ai.ts:321 |
no — zero occurrences in NLQueryInput.tsx |
|
What each component does read, for contrast (the destructure is the whole surface in all three):
AIFormAssist.tsx:27-32 — suggestions, showConfidence, showReasoning, autoFill (dead).
AIRecommendations.tsx:27-33 — recommendations, showScores, layout, loading, emptyMessage.
NLQueryInput.tsx:25-32 — placeholder, result, suggestions, showHistory, history, loading.
Why maxResults is the sharp one
Its doc comment reads Maximum number of results to display. AIRecommendations renders every item in recommendations — there is no slice, no cap, no read of the key at all. An author who writes maxResults: 5 against a 50-item list gets 50 rows and no diagnostic. That is a declared capability the runtime does not honour, which is the exact failure mode the coding standards' contract-first rule and the dispatch framework's third axis (making it structurally hard for an AI to write wrong metadata) exist to prevent.
grep -rn maxResults packages/*/src returns exactly three hits: the declaration (types/src/ai.ts:229), the designer input below, and nothing else.
The designer amplifies five of the seven
packages/plugin-ai/src/index.tsx advertises these keys as authorable inputs in its ComponentRegistry.register metadata, so the field designer offers them and a metadata author can pick them from a list:
ai-form-assist (index.tsx:24-30) — offers formId, objectName, fields, autoFill.
ai-recommendations (index.tsx:41-51) — offers objectName, maxResults.
nl-query (index.tsx:60-65) — offers objectName.
So the loop is closed the wrong way: the type declares it, the designer offers it, the JSON validates, and the renderer ignores it — silently, at every depth (objectui#7869 explains why nesting makes even the value check vacuous). This is the mirror image of objectui#7712 / #8171 / #8172 / #8174, which all report a key the renderer reads but the registration does not declare; here the registration and the type declare what nothing reads.
Not decided here
Enforce-or-remove is a maintainer call and the two directions have different costs, so this card does not pick one:
- Remove — retire the seven members and their designer inputs. Cheapest, matches the startup-stage focus principle (an unpulled declaration surface defaults to strict) and the immediate-retirement ruling. Cost:
objectName reads like context an AI backend would eventually want, and removing it is visible in a published .d.ts.
- Enforce — implement the reads (
maxResults as a slice, fields/formId/objectName as the context the suggestion call needs). Larger, and it is only worth it if a real caller wants it — which is the first axis, and nothing in the repo currently pulls on these.
The measurement above is what the decision needs either way; note that until one is chosen, packages/plugin-ai/README.md teaches five of the seven keys in its examples (they are declared, so the repaired snippets compile — the gate cannot see inertness, only types).
Measured while compiling
packages/plugin-ai/README.md's snippets for objectui#5174 batch 27 (PR to follow). Not fixed there — that batch's licence is the README and one ledger entry, and ⛔ no edit topackages/plugin-ai/src/**orpackages/types/src/**. Filing so the shape is not lost.This is the plugin-ai instance of the class objectui#7742 already carries for
KanbanSchema(three zero-read members + one undeclared read, enforce-or-remove). objectui#5098 was the plugin-form README instance of the same thing. Nothing here is a duplicate of either: different package, different keys.What was measured
Every key below is declared by its schema type in
packages/types/src/ai.tsand never read by the component that the schema drives. The three components inpackages/plugin-ai/src/are the only consumers of these three types repo-wide (grep -rlnoverpackages/*/srcandapps/*/srcreturns the three components plus the declaration and the barrel).AIFormAssistSchema.formIdai.ts:97AIFormAssist.tsxAIFormAssistSchema.objectNameai.ts:102AIFormAssistSchema.fieldsai.ts:107AIFormAssistSchema.autoFillai.ts:127AIFormAssist.tsx:31with a default, never referenced againAIRecommendationsSchema.objectNameai.ts:209AIRecommendations.tsxAIRecommendationsSchema.maxResultsai.ts:229NLQuerySchema.objectNameai.ts:321NLQueryInput.tsxWhat each component does read, for contrast (the destructure is the whole surface in all three):
AIFormAssist.tsx:27-32—suggestions,showConfidence,showReasoning,autoFill(dead).AIRecommendations.tsx:27-33—recommendations,showScores,layout,loading,emptyMessage.NLQueryInput.tsx:25-32—placeholder,result,suggestions,showHistory,history,loading.Why
maxResultsis the sharp oneIts doc comment reads
Maximum number of results to display.AIRecommendationsrenders every item inrecommendations— there is no slice, no cap, no read of the key at all. An author who writesmaxResults: 5against a 50-item list gets 50 rows and no diagnostic. That is a declared capability the runtime does not honour, which is the exact failure mode the coding standards' contract-first rule and the dispatch framework's third axis (making it structurally hard for an AI to write wrong metadata) exist to prevent.grep -rn maxResults packages/*/srcreturns exactly three hits: the declaration (types/src/ai.ts:229), the designer input below, and nothing else.The designer amplifies five of the seven
packages/plugin-ai/src/index.tsxadvertises these keys as authorable inputs in itsComponentRegistry.registermetadata, so the field designer offers them and a metadata author can pick them from a list:ai-form-assist(index.tsx:24-30) — offersformId,objectName,fields,autoFill.ai-recommendations(index.tsx:41-51) — offersobjectName,maxResults.nl-query(index.tsx:60-65) — offersobjectName.So the loop is closed the wrong way: the type declares it, the designer offers it, the JSON validates, and the renderer ignores it — silently, at every depth (objectui#7869 explains why nesting makes even the value check vacuous). This is the mirror image of objectui#7712 / #8171 / #8172 / #8174, which all report a key the renderer reads but the registration does not declare; here the registration and the type declare what nothing reads.
Not decided here
Enforce-or-remove is a maintainer call and the two directions have different costs, so this card does not pick one:
objectNamereads like context an AI backend would eventually want, and removing it is visible in a published.d.ts.maxResultsas a slice,fields/formId/objectNameas the context the suggestion call needs). Larger, and it is only worth it if a real caller wants it — which is the first axis, and nothing in the repo currently pulls on these.The measurement above is what the decision needs either way; note that until one is chosen,
packages/plugin-ai/README.mdteaches five of the seven keys in its examples (they are declared, so the repaired snippets compile — the gate cannot see inertness, only types).