Compatibility Policy¶
This document defines versioning rules, stability contracts, and promotion criteria for Typsastra's language provider and editing policy systems.
Provider ID stability¶
A provider's id() value is stored in user settings to persist installed dictionaries and language preferences. Once a provider ID is declared stable, it must not change. Changing a stable ID is a breaking change and requires a migration entry.
Rules:
- IDs must be lowercase with only letters, digits, hyphens, and underscores.
- Convention: BCP 47 tag (lo, bn_BD) or engine:locale (hunspell:th).
- Experimental providers may change their ID before reaching stable status, but must document the change in their PR.
- Stable providers must not rename their ID. If a rename is unavoidable, ship a migration record (see below).
Capability schema versioning¶
The PROVIDER_CAPABILITY_SCHEMA_VERSION constant in src-tauri/src/segmentation/provider.rs versions the serialized capability shape. The TypeScript frontend reads this to determine which fields are available.
Rules:
- Any additive change (new optional field with a default) increments the patch version in a comment only; the constant stays the same.
- Any breaking change (renamed field, removed field, changed semantics) increments PROVIDER_CAPABILITY_SCHEMA_VERSION by 1.
- When the schema version increments, the TypeScript frontend must be updated in the same PR to handle both the old and new schema, or drop support for the old one with a documented migration path.
Current schema version: 1
Settings migrations¶
When a stable provider ID changes or a capability schema field is removed, a migration record must be added to the settings validation logic in src/settings.ts.
A migration record must include:
- The old ID or field name.
- The new ID or field name (or null if removed).
- The version at which the change was made.
- A brief rationale.
If an installed language entry refers to an unknown provider ID, Typsastra must silently remove the entry rather than error. The provider can be re-installed by the user.
Promotion criteria: experimental → stable¶
A language provider or editing policy must meet all of the following criteria before its stability() changes from "experimental" to "stable":
1. Named maintainer¶
A GitHub username or a link to an upstream project is declared in the provider source file. The maintainer is responsible for reviewing future changes to the provider's fixtures and dictionary data.
2. Fixture coverage¶
All fixture categories in tests/fixtures/<language>/language.json and (if applicable) tests/fixtures/<script>/editing.json must be filled with real language examples reviewed by someone with language knowledge:
| Fixture category | Required |
|---|---|
| Canonical words (known) | ✅ |
| Unknown / misspelled words | ✅ |
| Non-canonical / normalized forms | ✅ |
| Mixed-script ranges | ✅ |
| Non-BMP code points in surrounding text | ✅ |
| Performance sample (~100 words) | ✅ |
3. Validation matrix¶
All commands in the validation matrix must pass on both Windows and Linux release builds:
4. Performance gates¶
- Language analysis p95 latency after debounce: ≤ 100 ms
- Suggestion lookup p95 latency: ≤ 50 ms
- Suggestions capped at
limitentries (never unbounded). - No full-dictionary scan in the interactive analysis path.
Measure by running bun test tests/performanceDiagnostics.test.ts and comparing against the budgets defined in docs/PERFORMANCE_GATES.md.
5. Documented limitations¶
Known limitations must be documented in docs/LANGUAGE_TOOLS.md under the language's entry. Examples of required documentation:
- Compound words that the tokenizer splits incorrectly.
- Script variants or dialects not covered by the dictionary.
- Known false-positive or false-negative classes in spellcheck.
- Any condition under which
analyze()returns an error.
6. No Khmer regression¶
Running bun test tests/khmerReference.test.ts must produce identical results to the baseline. Any difference is a blocker.
7. License declaration¶
license() must return a valid SPDX expression or attribution string. "unknown" and empty strings are rejected by the registry.
Additive vs. breaking changes¶
| Change type | Breaking? | Action required |
|---|---|---|
Adding an optional field to ProviderCapabilities |
No | Update default in trait; add handling in TypeScript |
Renaming a ProviderCapabilities field |
Yes | Increment schema version; add migration |
Removing a ProviderCapabilities field |
Yes | Increment schema version; add migration |
Changing a stable provider's id() |
Yes | Add migration; update stored settings |
Changing an experimental provider's id() |
No | Document in PR |
| Adding a new language provider | No | Follow contributor guide; start as experimental |
Changing SCRIPT_EDITING_POLICY_CONTRACT_VERSION |
Yes | Update all registered policies in the same PR |
Changing a policy's scripts ownership |
Yes | Confirm no overlap; run full conform suite |
Deprecation process¶
- Mark the provider as deprecated in its
display_name()or a// @deprecatedcomment. - Set
stability()to"deprecated"if the trait is extended to support that value; otherwise keep it as"experimental". - Keep the provider registered for one minor release cycle (or two months, whichever is longer).
- Remove the provider in the following release, adding a migration record if the ID was stable.
CI enforcement (P9.9)¶
The contributor-contracts.yml GitHub Actions workflow automatically checks:
bun run conform— policy and provider conformance tests.cargo test --lib segmentation— includesall_registered_providers_have_licenses.cargo test --lib examples— example workspace integrity.- Khmer regression:
bun test tests/khmerReference.test.tsmust be unchanged.
A PR that fails any of these checks cannot be merged.