# TCGC Documentation Knowledge Base

## Environment Notes

- The repository requires Node.js >=22.0.0 for builds. The `.npmrc` has `engine-strict=true`.
- The `tspd` tool for regenerating reference docs requires the core submodule to be built first (`git submodule update --init && cd core && pnpm install && pnpm build`).
- To regenerate reference docs: `cd packages/typespec-client-generator-core && pnpm regen-docs`.
- To build azure-http-specs: `cd packages/azure-http-specs && pnpm build && pnpm validate-mock-apis`.
- `pnpm` is not pre-installed globally; install with `npm install -g pnpm`.

## Decorator Catalog

### Core Decorators (lib/decorators.tsp) — 21 decorators

1. `@clientName(rename, scope?)` — rename any type/operation
2. `@convenientAPI(target, flag?, scope?)` — control convenience method generation
3. `@protocolAPI(target, flag?, scope?)` — control protocol method generation
4. `@client(target, options?, scope?)` — define explicit client; ClientOptions has service, name, autoMergeService
5. `@operationGroup(target, scope?)` — DEPRECATED, use @client
6. `@usage(target, value, scope?)` — mark model/enum/union/namespace usage (input/output/json/xml); on namespace, propagates recursively to all contained types
7. `@access(target, value, scope?)` — public/internal visibility
8. `@override(target, override, scope?)` — customize method signatures
9. `@useSystemTextJsonConverter(target, scope?)` — C# backward compat only
10. `@clientInitialization(target, options, scope?)` — customize client init; options has parameters model and initializedBy flags
11. `@paramAlias(target, alias, scope?)` — alias client init parameter names
12. `@clientNamespace(target, rename, scope?)` — customize namespace
13. `@alternateType(target, alternate, scope?)` — replace types; alternate can be ExternalType with identity/package/minVersion
14. `@scope(target, scope?)` — language-specific scoping for operations/properties
15. `@apiVersion(target, value?, scope?)` — mark/unmark parameter as API version
16. `@clientApiVersions(target, value, scope?)` — extend client API version enum
17. `@deserializeEmptyStringAsNull(target, scope?)` — null deserialization for empty strings
18. `@responseAsBool(target, scope?)` — HEAD operations return boolean (2xx=true, 404=false)
19. `@clientLocation(source, target, scope?)` — move operations/params between clients
20. `@clientDoc(target, documentation, mode, scope?)` — override docs with append/replace mode
21. `@clientOption(target, name, value, scope?)` — pass experimental flags to emitters

### Legacy Decorators (lib/legacy.tsp) — 7 decorators

22. `@hierarchyBuilding(target, value, scope?)` — change base type of a model in SDK; lifts properties from removed intermediates, reconciles duplicates with new base chain
23. `@flattenProperty(target, scope?)` — flatten model properties
24. `@markAsLro(target, scope?)` — force operation as LRO
25. `@markAsPageable(target, scope?)` — force operation as pageable
26. `@disablePageable(target, scope?)` — disable auto-detected pagination
27. `@nextLinkVerb(target, verb, scope?)` — set HTTP verb for next link (GET or POST)
28. `@clientDefaultValue(target, value, scope?)` — set client-level defaults

### Functions (lib/functions.tsp) — 5 functions

29. `replaceParameter(operation, selector, replacement)` — replace operation parameter
30. `removeParameter(operation, selector)` — remove optional parameter
31. `addParameter(operation, parameter)` — add new parameter
32. `reorderParameters(operation, order)` — reorder parameters by name list
33. `exact(name)` — mark a client name as exact, preventing casing transformations; used with @clientName; sets `isExactName: true` on the type graph

## TSP Doc Comment Issues Found

- `@clientApiVersions` had incorrect @param description for `value` (was copy-pasted from @apiVersion). Fixed.
- `@paramAlias` example comment was confusing about what gets elevated. Fixed.

## Documentation File Map

| File                        | Topics                                                                                                                                          |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| 00howtogen.mdx              | Overview, language emitter setup                                                                                                                |
| 01setup.mdx                 | TCGC customization setup                                                                                                                        |
| 02package.mdx               | @service, @clientNamespace, license                                                                                                             |
| 03client.mdx                | @client, @clientLocation, @clientInitialization, @clientName, @clientNamespace, InitializedBy                                                   |
| 04method.mdx                | @convenientAPI, @protocolAPI, @override, @access, @usage, functions, @responseAsBool                                                            |
| 05pagingOperations.mdx      | @list, @pageItems, @nextLink, @continuationToken, @markAsPageable, @disablePageable, @nextLinkVerb                                              |
| 06longRunningOperations.mdx | LRO patterns, @pollingOperation, @markAsLro                                                                                                     |
| 07multipart.mdx             | @multipartBody, HttpPart, file upload                                                                                                           |
| 08types.mdx                 | @clientNamespace, @clientDefaultValue, @clientName, @discriminator, @alternateType, @clientDoc, @flattenProperty, @deserializeEmptyStringAsNull |
| 09renaming.mdx              | @clientName, @encodedName, exact()                                                                                                              |
| 10versioning.mdx            | @versioned, @added, @removed, @apiVersion, @clientApiVersions                                                                                   |
| 11hierarchyBuilding.mdx     | @hierarchyBuilding (Legacy)                                                                                                                     |
| 12clientOptions.mdx         | @clientOption                                                                                                                                   |

## Documentation Patterns

- All howto .mdx files use frontmatter with `title:` and `llmstxt: true`
- All import `{ ClientTabs, ClientTabItem } from "@components/client-tabs"`
- Code examples use `<ClientTabs>` with 6 language blocks: typespec, python, csharp, typescript, java, go
- **Every `<ClientTabs>` block must be generated by the @doc-example-generator skill** — never hand-write
- Legacy decorator sections use `:::caution` alert blocks
- Heading hierarchy: H2 for main sections, H3/H4 for subsections

## Spector Spec Coverage

### Covered in azure/client-generator-core/

access, alternate-type, api-version, client-default-value, client-doc, client-initialization, client-location, deserialize-empty-string-as-null, exact-name, flatten-property, hierarchy-building, next-link-verb, override, response-as-bool, usage

### Covered in client/

namespace (@clientNamespace), naming (@clientName), overload, structure (@client)

### Not Yet Covered (candidates for future specs)

- `@scope` — language-specific scoping
- `@markAsLro` — force LRO behavior
- `@markAsPageable` / `@disablePageable` — force/disable pagination
- `@clientOption` — experimental flags
- `@clientApiVersions` — extend API versions
- `@useSystemTextJsonConverter` — C# specific
- Functions (replaceParameter, removeParameter, addParameter, reorderParameters)

### Specs Removed (feedback from PR #4268)

- `convenient-api` — removed because @convenientAPI/@protocolAPI are code-generation controls that aren't testable at the wire level via Spector

## Guideline.md (Emitter Developer Docs) Notes

- UsageFlags reference table was missing — added with all 13 flag values and descriptions.
- InitializedByFlags documentation was incomplete — added Individually, Parent, CustomizeCode descriptions.
- The `CustomizeCode` (4) flag means initialization is omitted from generated code and handled manually.
- `serializationOptions` on SdkModelType properties was already documented. Now also documented on `SdkBodyParameter` and `SdkHttpResponseBase` in the HTTP Operation Parameters and Response sections.
- `baseModel` property on SdkModelType is not documented in guideline.md but exists in interfaces.ts.

## Diagnostics

- `operation-not-in-client`: REMOVED in May 2026. This diagnostic no longer exists.
- `inconsistent-multiple-service-dependency` (warning): Emitted when services merged into the same client depend on different versions of a shared library dependency. Documented in 03client.mdx under the "One Client from Multiple Services" section and in guideline.md under "Client Detection".
- `legacy-hierarchy-building-conflict` (warning): Now only has `property-type-mismatch` message ID (the old `property-missing` and `type-mismatch` message IDs were removed). Emitted during property reconciliation when a dropped property's type is incompatible with the same-named property on the new base chain.
- `override-parameters-mismatch` (error): In addition to the general "different parameters definition" case, `@override` now reports this when the override operation drops a parameter that is realized as a `@path` parameter in the original operation's HTTP route, or redeclares it without `@path` (the underlying route still needs it). The check is skipped when any override parameter carries `@clientLocation` (intentional relocation). Matching between original/override parameters is by **name**, not position (so overrides may add/remove/regroup parameters). "Realized path parameter" is resolved from `getHttpOperation(...).parameters` (route ground truth), not from the `@path` decorator alone, because templated params (e.g. ARM scope models) can carry `@path` without appearing in the route. Documented in 04method.mdx `@override` section as a `:::caution`.
- `client-location-conflict` / `parameterTypeConflict` (warning): `@clientLocation` cannot move multiple parameters that share a name but have different types to the same client. Common when `@clientLocation` is on a templated parameter instantiated with different types across operations; the client parameter collapses to a single (last) type, breaking the SDK. Fix: move the parameter on each operation instead. Validated in `src/validations/types.ts` (`validateClientLocationParameterTypes`). Documented in 04method.mdx `@clientLocation` section as a `:::caution`.

## External Type Usage Propagation

- Types marked as external (via `@alternateType` with `ExternalTypeInfo`) only receive the `External` usage flag. TCGC blocks propagation of non-`External` usage flags (`Input`, `Output`, `Json`, etc.) through external types. This was a bug fix — previously, types reachable through external types could incorrectly get `Input`/`Output` flags.
- The `External` usage flag description in guideline.md was expanded to explain the propagation blocking behavior.
- The `@alternateType` external types Notes section in 08types.mdx was updated to explain that types only reachable through external types won't get `Input`/`Output` flags.

## Encoding Context Awareness

- The `encode` property on `SdkBuiltInType` is not only set by the `@encode` decorator. TCGC also sets it contextually — for example, `bytes` in a `multipart/form-data` part get `encode: "bytes"` (raw binary) instead of the default `"base64"`. This is handled in `addMultipartPropertiesToModelType` in `src/types.ts`, which calls `addEncodeInfo` with the part's default content type.
- The guideline.md description of `SdkBuiltInType.encode` was updated to reflect this contextual encoding behavior.

## Common Mistakes to Avoid

- Don't copy @param descriptions between decorators — @clientApiVersions had @apiVersion's description.
- The 03client.mdx file had a typo "@clientLocaton" (missing 'i') — fixed to "@clientLocation".
- In mockapi.ts files, query parameters use `query:` not `params:` in the request object.
- The guideline.md previously said `encode` is set only when `@encode` exists — this was inaccurate since encode can also be set contextually (e.g., multipart).
- Use `// NOT_SUPPORTED` for language examples where an emitter doesn't support a feature. Do NOT use `// TODO: fill in X example manually`.
- Separate changesets: TCGC documentation updates use "internal" changeKind. Spector spec additions use "feature" changeKind with a separate changeset file.
- Don't add Spector specs for code-generation controls like @convenientAPI/@protocolAPI — they aren't testable at the HTTP wire level.
- The `@deserializeEmptyStringAsNull` section was removed from 08types.mdx in feedback PR #4268. Don't re-add it unless specifically requested.
- Spector response-as-bool spec needs BOTH a success (200) case AND a 404 case to be complete.
- TypeSpec examples in docs with operations MUST include `@route` decorators to be valid TypeSpec (feedback PR #4398).
- In @hierarchyBuilding language examples: each language handles inheritance differently. Python doesn't use real hierarchy (copies all props to each class). Go uses flat structs. C# and TypeScript use real inheritance. Java uses class inheritance.
- C# property names that conflict with their enclosing class name should use a suffix (e.g., `CProperty` not `C` for a property in class `C`).
- The "Body Model Properties Named apiVersion" section was removed from 10versioning.mdx during review (PR #4398) — don't re-add as a separate section. The behavior is covered implicitly by the main description.

## @responseAsBool Internal Design

- HTTP response objects have `type: undefined` when @responseAsBool is applied. The boolean is computed at the method response level only.
- The method response `optional` is never set for @responseAsBool operations (boolean is always true or false, never optional).
- The 404 response is promoted from exception to valid response with status code 404.

## @hierarchyBuilding Reconciliation (May 2026 Overhaul)

- No validation at decoration time. Property reconciliation happens during SDK type graph building.
- Properties from removed intermediate ancestors are "lifted" onto the rebased model.
- Properties whose names are supplied by the new base chain are dropped (inherited instead).
- Discriminator properties are never dropped, even if new base has same-named property.
- Type compatibility uses TypeSpec's `isAssignableTo` in both directions — literal/sub-scalar types assignable to a wider base type are silently dropped.
- The diagnostic message ID changed from "property-missing"/"type-mismatch" to just "property-type-mismatch".

## Content-Type/Accept Header Design (May 2026)

- Single content type: constant value.
- Multiple request content types: enum with one value per content type.
- Multiple response content types: single constant with comma-joined string (structured types first).
- Constants and enums get proper generated names via the naming context path (e.g., `DownloadFileMultipleContentTypesAccept`).
- For file bodies with multiple content types, TCGC reuses the File model's `contentType` property's union type so that the synthesized `contentType` header parameter and the File model's property reference the same `SdkEnumType` instance.

## Example Matching (June 2026)

- Example file operation IDs are resolved under the `autorest` scope (not the per-language scope) to avoid per-language `@clientLocation`/`@clientName` overrides breaking example linkage. This ensures the same example file matches regardless of which language emitter is consuming TCGC.

## BinarySerializationOptions (June 2026)

- The `filename` property on `BinarySerializationOptions` is of type `SdkModelPropertyType` (not the raw TypeSpec `ModelProperty`). This was corrected from the original implementation to use TCGC's own type system consistently.

## Usage Flag Propagation

- Readonly properties have Input flag stripped but other flags (Output, Json, Xml) still propagate through.
- External types (via @alternateType with ExternalTypeInfo) block propagation of all non-External flags.
- `@apiVersion(false)` prevents a parameter from matching to a client API version parameter, keeping it on the method.
- Body model properties named "apiVersion" are NOT treated as API version params — only HTTP metadata params (header/query/path/cookie) and server URL template parameters (from `@server`) are matched by name.
- Server URL template parameters (declared in `@server` decorator's parameter model) named `apiVersion`/`api-version` are recognized as API version params, even with plain `string` type in versioned services.

## isExactName Property (May 2026)

- The `isExactName: boolean` property was added to many SDK type interfaces: SdkModelType, SdkEnumType, SdkUnionType, SdkConstantType, SdkNullableType, SdkClientInitializationType, SdkModelPropertyTypeBase (base for all property types), SdkClientType, SdkEnumValueType, and SdkServiceMethodBase.
- Set to `true` when a name is wrapped with the `exact()` function in `@clientName`.
- The `exact()` function internally prepends `_exact_:` prefix which is stripped by `normalizeExactName()` before the name reaches the type graph.
- Exported helpers: `hasExactNameMarker()`, `normalizeExactName()` from the TCGC package index. `EXACT_NAME_PREFIX` is internal (defined in `internal-utils.ts`).
- Public utility: `isExactClientName(context, type)` checks whether a type has exact name override.
- Documented in guideline.md under Common Properties and in 09renaming.mdx under "Preserving exact casing".

## Feedback Lessons (PR #4416)

- In TypeScript code examples, keep method signatures on a single line when they fit within ~120 characters. Don't use multi-line formatting for short method signatures.

## Feedback Lessons (PR #4481)

- For exact-name Spector specs: use per-language underscore-prefixed names (e.g., `_my_name`, `_myName`, `_MyName`) to truly verify that language naming logic does not strip or recase the name. Simple camelCase/snake_case names don't prove exactness because they'd survive normal casing rules.
- `@clientName` description in docs: say it "allows emitters to apply language-specific casing transformations to the provided name." The `exact()` function "prevents this and preserves the name exactly as specified."
- guideline.md formatting: do NOT add extra blank lines between numbered list items and their sub-items (keep `  -` sub-items immediately after the numbered item).
- Keep exact() doc examples simple: prefer showing only scoped renames (per-language). Don't combine global rename + scoped rename in the same example.
- Language tabs for exact() should show `# not supported` / `// not supported` since no emitter supports `isExactName` yet.

## Orphan Type Detection (May 2026 Refactoring)

- `listOrphanTypes` no longer iterates only user-defined namespaces. It now uses `listScopedDecoratorData` to find all types and namespaces with an explicit `@usage` decorator, including types in imported libraries (e.g., `@@usage(Azure.Core.Foundations.Error, Usage.input)`).
- When `@usage` is applied to a namespace, the function recursively descends into sub-namespaces to collect all models, enums, and unions.
- Types with `@hierarchyBuilding` are also collected separately (only when legacy hierarchy building is enabled).
- **Ordering**: `listOrphanTypes` returns types in a stable order: models first, then enums, then unions. This ensures anonymous types (e.g., anonymous model variants inside unions) get their generated name from the model property context rather than the union context, producing stable names like `OuterWithNullableValue` instead of `RecursiveNullableType1`.

## Feedback Lessons (PR #4430)

- Only ONE `#suppress "experimental-feature" "exact"` directive is needed per property — it covers all subsequent `@clientName(exact(...))` decorators on that property.
- When creating exact-name Spector specs, the namespace needs `@clientNamespace` for BOTH Java (`"azure.clientgenerator.core.exactname"`) AND Python (`"specs.azure.clientgenerator.core.exactname"`) so tests pass in both language emitter test suites.
- The @clientNamespace for python should be formatted multi-line if it exceeds a reasonable line length.

## Per-Service API Version (June 2026)

- The `api-version` emitter option now accepts `string | Record<string, string>`. The Record form maps service namespace full names to version strings, enabling per-service API version control in multi-service packages.
- `resolveApiVersionForService` in `src/internal-utils.ts` is the central resolution function (internal, not exported). It handles string vs Record config dispatch.
- For multi-service packages, `"all"` is NOT supported — it falls back to `undefined` (latest version). This applies in both the string and Record forms.
- `"latest"` is a global keyword that applies regardless of single/multi-service.
- In the Record form, services not listed in the map return `undefined` (latest version).
- `SdkPackage.metadata.apiVersions` (Map) stores the resolved version per service. `metadata.apiVersion` (string, deprecated) is `undefined` for multi-service.
- No Spector spec was added for this feature — it's a code-generation-time config behavior, not a wire-level behavior. The unit tests in `test/package/api-versions-metadata.test.ts` and `test/clients/structure.test.ts` thoroughly cover it.
- The guideline.md was updated to document `SdkPackage.metadata` (both `apiVersion` and `apiVersions`).
- The 10versioning.mdx was updated to mention the Record form and add a "Per-service versioning (multi-service packages)" section.

## Linter Rules Documentation

- Linter rules live in `packages/typespec-client-generator-core/src/rules/` and are registered in `src/linter.ts` (both the general `rules` array and the `csharpRules` array for C#-specific rules).
- Each rule has a user-facing doc page under `website/src/content/docs/docs/libraries/typespec-client-generator-core/rules/<rule-name>.md` and a row in the auto-listed `reference/linter.md` table. These are typically added by the rule's own source PR — verify they exist before adding.
- Rule doc page format: frontmatter `title:`, a `Full name` code block with the fully-qualified rule id, a one-line description, then `#### ❌ Incorrect` and `#### ✅ Correct` `tsp` examples (no `<ClientTabs>` needed — rule docs use plain `tsp` blocks).

### csharp-no-url-suffix (PR #4541)

- Warning rule: flags model properties whose **C#-resolved** name ends with `Url`, suggesting `Uri` instead (.NET convention). Uses `getLibraryName(tcgcContext, property, "csharp")`, so it respects `@clientName` overrides (both directions — it can also fire when `@clientName` introduces a `Url` suffix for C#). Case-sensitive (`imageurl` is not flagged); `Urls` plural is not flagged.
- Provides a codefix that writes `@@clientName(Model.prop, "<name>Uri", "csharp")` into `client.tsp`.
- Codefix helpers added in `src/rules/codefix-helpers.ts` are reusable by other rules:
  - `createAugmentDecoratorCodeFix(target, decoratorName, args?)` — appends an `@@`-augment decorator at the end of the SAME file as the target.
  - `createClientTspAugmentDecoratorCodeFix(target, decoratorName, program, args?)` — writes the augment decorator to `client.tsp` (creates imports/usings as needed, uses short refs when the namespace `using` is in scope, else FQN). Assumes `client.tsp` is imported via tspconfig.

## doc-updater Mechanics

- The incremental `changes.commits[].diff` only contains `packages/typespec-client-generator-core/src/` (source) diffs — NOT the doc files those same PRs may have changed. So a source PR that adds a linter rule, reference table row, or howto section will already have those docs in the tree at checkout. Always check the current doc state before adding; the doc work may already be done, leaving only cross-cutting howto notes for you.
- Validation/diagnostic-only changes (new warnings/errors) and linter rules do not need Spector coverage — Spector demonstrates positive wire-level client generation, not error conditions. Document them as `:::caution`/`:::note` admonitions in the relevant howto section instead of new `<ClientTabs>` blocks.

## Feedback Lessons (PR #4683)

- In versioning (and any API-version) examples, use realistic **date-based** api-version identifiers (e.g. `2024-01-01`, enum members like `v2024_01_01: "2024-01-01"`) — NOT placeholder names like `av1`/`bv1`. Human reviewers rewrote placeholder versions to date-based ones. Keep the enum member name and its string value consistent (e.g. `v2024_05_01: "2024-05-01"`).

## Collection Type Serialization Options (July 2026)

- `SdkArrayType` and `SdkDictionaryType` gained an optional `serializationOptions?: SerializationOptions` property (`src/interfaces.ts`).
- It is populated ONLY when the collection is a _named_ model carrying explicit serialization decorators, e.g. `@Xml.name("Foo") model Foo is Bar[];` or `@encodedName("application/xml", ...) model Foo is Bar[];`. Anonymous/inline arrays and records leave it `undefined`.
- Rationale (`updateSerializationOptions`/`setSerializationOptions` in `src/types.ts`): for un-decorated collections the wrapping element name comes from the referencing property/model, so emitting a name on the collection itself would be spurious. `setSerializationOptions(context, type, [])` is called with an empty content-type list so only explicitly-defined info is captured.
- Documented in guideline.md "Collection Types" bullet. No Spector spec needed — this is emitter-consumed type-graph metadata, covered by unit tests in `test/types/serialization-options.test.ts` (array model with `@Xml.name`, with `@encodedName`, and without decorators).

## @clientLocation + scoped @client validation (July 2026)

- Bug fix in `src/validations/types.ts`: `@clientLocation` name-collision validation now skips operations that belong to an explicit `@client` scoped to a _different_ language than the scope being validated (`isClientForOtherScopeOnly`). Prevents false-positive collisions for `is`-derived operations inside a `@client(..., "java")` interface. Internal validation only — no user-facing doc change.

## SdkClientType.versionsEnum (July 2026)

- `SdkClientType` gained `versionsEnum?: SdkEnumType` (`src/interfaces.ts`, populated by `getVersionsEnum` in `src/clients.ts`). It is the API-versions enum for the client's service, `usage` includes `UsageFlags.ApiVersionEnum` (8), and it is the SAME object instance that appears in `SdkPackage.enums`.
- `undefined` for unversioned services and for multi-service root clients (spanning >1 service). Sub-clients that map to a single service still get their own service's enum. Verified by `test/package/versioning.test.ts` ("client has versionsEnum reference", "multi-service client has no versionsEnum").
- Context caches these per-service via `__serviceToVersionsSdkEnum` and exposes `getPackageVersionSdkEnum(): Map<Namespace, SdkEnumType>` (emitter helper on `TCGCContext`/`SdkContext`).
- Documented in guideline.md "Client" section. Emitter-consumed type-graph metadata — no Spector spec needed.

## SSE Metadata (July 2026)

- `SdkBodyParameter` and `SdkMethodResponse` gained `sseMetadata?: SdkSseMetadata`, set ALONGSIDE `streamMetadata` when the body/response is a server-sent event stream (`text/event-stream`, `SSEStream`). `undefined` for non-event streams like JSONL. Built by `buildSdkSseMetadata` in `src/http.ts`.
- `SdkSseMetadata.events` is `SdkSseEventMetadata[]`, one entry per variant of the streamed `@events` union. Derived from `@typespec/events` event definitions plus the `@typespec/sse` `@terminalEvent` marker. Fields: `eventType?` (SSE `event:` name from named variant; undefined→`message` event), `isTerminalEvent`, `isEventEnvelope`, `type`/`contentType`, `payloadType`/`payloadContentType`. When `isEventEnvelope` is false, `type`==`payloadType` and content types match.
- Kept separate from `SdkStreamMetadata` because SSE, streaming, and events are modeled by three distinct TypeSpec libraries (`@typespec/sse`, `@typespec/http`, `@typespec/events`).
- Documented in guideline.md "Operation" section under a new "Streaming and Server-Sent Events" subsection (also introduced `streamMetadata` documentation there, which was previously undocumented). Tests: `test/methods/sse.test.ts`, `test/methods/streams.test.ts`. Emitter type-graph metadata — no Spector spec needed.

## no-unnamed-types Linter Rule REMOVED (July 2026)

- The `no-unnamed-types` rule was removed from `src/linter.ts` (both the rules array and `no-unnamed-types.rule.ts` / `.md` deleted). `reference/linter.md` no longer lists it — already consistent. Do NOT re-add it.
- Rule source files were renamed to the `<name>.rule.ts` convention (e.g. `property-name-conflict.ts` → `property-name-conflict.rule.ts`); `csharp-no-url-suffix` still uses `.ts`.

## Diagnostic Messages Externalized (July 2026)

- Diagnostic message definitions were moved out of `src/lib.ts` into individual `src/diagnostics/<name>.md` files (loaded at build). Purely an authoring refactor; reference docs regenerate the same content. No user-facing doc action.
