Skip to content

Add breaking change policy to website #6049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 1, 2025
Merged
1 change: 1 addition & 0 deletions website/src/content/current-sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const sidebar: SidebarItem[] = [
"handbook/formatter",
"handbook/package-manager",
"handbook/reproducibility",
"handbook/breaking-change-policy",
{
label: "Configuration",
items: ["handbook/configuration/configuration", "handbook/configuration/tracing"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
title: Breaking Change Policy
---

# Breaking Change Policy

import { Badge } from "@astrojs/starlight/components";

:::note
The information in this document is applicable to TypeSpec packages with version 1.0.0 or greater.
:::

## Versioning Scheme

The TypeSpec Compiler and libraries follow a major, minor, patch versioning scheme according to the following policy:

## Breaking Change Philosophy

Existing language syntax and semantics will not change without a major version.
The runtime behavior for a given TypeSpec will not change without a major version.
TypeSpecs leveraging new or updated features may cause runtime API consumers to fail
(e.g. because a new type is unhandled in an emitter or library that it uses)
or builds to fail (e.g. because exhaustive unions are no longer exhaustive).

- The language syntax and semantics for existing language elements will not change within a major version.
- A spec that builds successfully with a version of the TypeSpec compiler and its libraries will build successfully with a newer version of the compiler and libraries within the same major version.
- New types and functionality may be added in a minor version release to the compiler or any TypeSpec library.
- If a spec uses the new type or functionality, existing libraries or emitters may not work with it, and this is not considered a breaking change in the compiler or library that introduced the type. Spec authors should expect that _existing_ specs will continue to work with their workflows, but not that newly-added features will work with their existing workflows every time.
- TypeScript API types in TypeScript might change in ways that introduce TypeScript type checking errors (e.g. adding a new variant to a union). TypeScript type checking errors in library builds are not considered breaking changes, and library authors working in TypeScript should take care to program defensively as appropriate. More information about TypeScript API guarantees is provided in the section _Categories of Breaking Changes_ below.

### Bugs

A bug fix that introduces a technically breaking change will not be considered a breaking change for the purposes of TypeSpec versioning if it is clear that the existing behavior was broken or unintended in the first place.

## Categories of Breaking Changes

- <Badge text="Tier 0" variant="success" />: These are stable core APIs and language features that
define fundamental semantics and will not be broken without a major version update. We recommend
that library authors depend on these APIs.
- <Badge text="Tier 1" variant="caution" />: These are APIs that have very limited use cases and may
be broken without a major version update. We recommend that library authors avoid depending on
these APIs.
- <Badge text="Tier 2" variant="danger" />: These are internal APIs intended only for use by the
TypeSpec compiler and core libraries. Tier 2 APIs may be changed without a a major version update
or even documentation of the change. Consuming these APIs is _at your own risk_!
- <Badge text="Tier 3" variant="note" />: These are APIs and language features that don't describe
semantically meaningful information, but provide information that emitters and libraries may
choose to use and may introduce changes in emitter output when the features are changed. For
example: formatting.

| Example | Tier | Description |
| ----------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TypeKits | <Badge text="0" variant="success" /> | TypeKits are the recommend way to expose APIs from a library. TypeKits that are only available through experimental subpaths may be broken without a major version update, but TypeKits that are available by default may be considered highly stable. |
| Additional library helper functions | <Badge text="0" variant="success" /> | Helper and metadata accessor functions exported from the public surface of the compiler or a TypeSpec library are generally considered stable unless otherwise specified or only exported through an experimental subpath. |
| TypeSpec AST (`Node`) | <Badge text="1" variant="caution" /> | The TypeSpec abstract syntax tree may change at any time. **Note**: this is not the same thing as the _type graph_ (`Type` and its variants), which is a <Badge text="Tier 0" variant="success" />, stable feature; this only applies to `Node` and its variants. The only sanctioned reason for using the AST is for some syntax based linting rule or writing codefixes. Libraries depend on the abstract syntax tree _at their own risk_! |
| Checker | <Badge text="2" variant="danger" /> | Direct use of the Program's type checker instance is considered for internal use only and its API may change at any time. |
| Symbols | <Badge text="2" variant="danger" /> | TypeSpec node symbols (not JavaScript symbols or state keys, rather the internal symbols used to relate TypeSpec types in the parser and type checker) are for internal use only. |
| Stdout | <Badge text="2" variant="danger" /> | TypeSpec does not provide any contract with the output emitted to `stdout`/`stderr`. The CLI might change the output at any time. Stderr is used to output progress tracking and should NOT be counted as a failure. |
| `@internal` exports | <Badge text="2" variant="danger" /> | Any function, class or JS component that is exported but doesn't have a TypeScript type due to being marked `@internal` is considered for internal use only and its API may change at any time. |
| `/internals` exports | <Badge text="2" variant="danger" /> | Any types exported from a sub export with the name `/internals` is considered for internal use only and its API may change at any time. |
| `/experimental` exports | <Badge text="2" variant="danger" /> | Any types exported from a sub export with the name `/experimental` is considered for experimental and its API may change at any time. [See experiemental api](#experimental-apis) |
| Formatter | <Badge text="3" variant="note" /> | Formatting shouldn't affect the meaning of the language. Changes to the formatting should be taken with consideration, as changes in formatting may introduce significant and unexpected differences in formatted output, but changes to the formatter output are not considered breaking changes for the purposes of issuing a major version change. |
| Bug fixes | [See bug](#bugs) | Bug fixes will not be considered breaking changes for the purposes of TypeSpec versioning if the existing behavior is _clearly_ broken or unintentional (e.g. if it violates the documented and expected behavior, or if there is no reasonable interpretation of the buggy behavior), even if the change is technically a breaking change. Bug fixes that are technically breaking will be documented as breaking changes in the release notes, but will not introduce a major version revision. However, if a bug's behavior has become so widely used as to be considered a "feature," we will consider the impact of the bugfix and make a reasonable determination to the best of our abilities and depending on the non-breaking mitigation strategies we have at our disposal. We will not break behaviors in stable releases that are known to be widely depended upon, even if we believe they are the result of a bug. |

### Supported Node.js Versions

TypeSpec will support all [current, active, and maintenance LTS Node.js releases](https://nodejs.org/en/about/previous-releases). We aim to support newly released current LTS versions as soon as possible, and we will provide a six month "grace period" after an LTS release leaves maintenance support before we cease testing it. After we drop support for a maintenance LTS version of Node.js, we may begin using syntax and runtime features that outdated Node.js versions may not support in new minor versions of published packages.

TypeSpec does not guarantee support for any alternative JavaScript engines or runtimes.

### Using Experimental APIs <Badge text="Tier 3" variant="danger" />

TypeSpec compiler and libraries may expose experimental APIs that are not yet stable. These APIs are subject to change without notice.
Experimental APIs or types are exported from sub exports with the name `/experimental` or a sub export (e.g. `/experimental/feature`).

When those APIs become stable the unstable APIs will be deprecated then removed and users will need to migrate to the stable version.

### Emitter output

Emitter output are not guaranteed to be producing the exact same output as the previous version for the same input. A change that is semantically equivalent wouldn't be considered a breaking change by the emitter.
Loading