The new API contract tests added in #1018 (branch @ms/api-tests-scaffold) surfaced several inconsistencies across the public TypeScript surface. They are currently encoded as explicit exception sets in the test files so the suite passes today; this issue tracks the cleanup work.
Modules that don't extend BaseModule
BaseModule provides the shared delete() / forwardET() / getInputShape() plumbing and the generateFromFrame JSI binding hook. The following modules skip it and re-implement (or omit) parts of that contract:
OCRModule
VerticalOCRModule
LLMModule
SpeechToTextModule
TextToSpeechModule
TokenizerModule
Listed in SKIPS_BASE_MODULE in __tests__/api/moduleContracts.test.ts.
Modules without a static from* factory
Every other module uses Module.fromModelName(...) / Module.fromCustomModel(...) as the construction entry point:
ExecutorchModule — constructs blank and exposes an instance load() method instead.
TokenizerModule — no factory at all.
Listed in SKIPS_STATIC_FACTORY.
Hook naming inconsistency
Every hook drops the Module suffix from its module class name (ClassificationModule → useClassification, LLMModule → useLLM) except:
ExecutorchModule → useExecutorchModule (keeps the suffix).
Listed in HOOK_NAME_EXCEPTIONS.
Informational: parameterized registry accessor
models.ocr.craft({ language }) requires a language argument, while every other accessor in the registry is either fully parameterless or takes only optional ModelOpts. This is intentional (OCR pipelines are picked per language), but worth flagging because the test walker has to special-case it. Listed in PARAMETERIZED_ACCESSORS in __tests__/api/modelRegistry.test.ts.
How to act on this
Each bullet above corresponds to an entry in one of the exception sets. As an inconsistency is fixed at the source, the matching entry can be deleted and the contract test will start enforcing the rule for that module.
Refs #1018.
The new API contract tests added in #1018 (branch
@ms/api-tests-scaffold) surfaced several inconsistencies across the public TypeScript surface. They are currently encoded as explicit exception sets in the test files so the suite passes today; this issue tracks the cleanup work.Modules that don't extend
BaseModuleBaseModuleprovides the shareddelete()/forwardET()/getInputShape()plumbing and thegenerateFromFrameJSI binding hook. The following modules skip it and re-implement (or omit) parts of that contract:OCRModuleVerticalOCRModuleLLMModuleSpeechToTextModuleTextToSpeechModuleTokenizerModuleListed in
SKIPS_BASE_MODULEin__tests__/api/moduleContracts.test.ts.Modules without a static
from*factoryEvery other module uses
Module.fromModelName(...)/Module.fromCustomModel(...)as the construction entry point:ExecutorchModule— constructs blank and exposes an instanceload()method instead.TokenizerModule— no factory at all.Listed in
SKIPS_STATIC_FACTORY.Hook naming inconsistency
Every hook drops the
Modulesuffix from its module class name (ClassificationModule→useClassification,LLMModule→useLLM) except:ExecutorchModule→useExecutorchModule(keeps the suffix).Listed in
HOOK_NAME_EXCEPTIONS.Informational: parameterized registry accessor
models.ocr.craft({ language })requires alanguageargument, while every other accessor in the registry is either fully parameterless or takes only optionalModelOpts. This is intentional (OCR pipelines are picked per language), but worth flagging because the test walker has to special-case it. Listed inPARAMETERIZED_ACCESSORSin__tests__/api/modelRegistry.test.ts.How to act on this
Each bullet above corresponds to an entry in one of the exception sets. As an inconsistency is fixed at the source, the matching entry can be deleted and the contract test will start enforcing the rule for that module.
Refs #1018.