Skip to content

Require explicit @stability on every module and importable export - #8770

Merged
tim-smart merged 20 commits into
mainfrom
fix/effect-module-stability-tags
Oct 7, 2026
Merged

tim-smart merged 20 commits into
mainfrom
fix/effect-module-stability-tags

Conversation

@fubhy

@fubhy fubhy commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Every public module and directly importable declaration now has an explicit @stability tag, with mandatory JSDoc enforcement and CI coverage.

Closes EFF-1792

Module classification

Stable Effect 3.x modules retain stable status, including renamed successors identified by migration/v3-to-v4.md: Result, JsonSchema, Formatter, Redactable, References, SchemaIssue, SchemaParser, SchemaTransformation, mapped Tx modules, testing/TestClock, and the encoding modules.

Filter, Latch, Pull, Redactable, References, Semaphore, and UndefinedOr are explicitly stable, as requested. Combiner, JsonPatch, JsonPointer, Optic, Reducer, SchemaGetter, SchemaRepresentation, and StandardSchema also remain stable.

Unstable groups include:

  • New v4 APIs: ByteSize, Crypto, ErrorReporter, LayerRef, Newtype, Stdio, TxChunk, testing/TestConsole, and the testing barrel.
  • Former 0.x platform APIs: ChannelSchema, FileSystem, Path, PlatformError, and Terminal.
  • Former experimental APIs: ExecutionPlan, Graph, HashRing, LayerMap, and PartitionedSemaphore.

Current source-header classification counts (non-internal source files, including entry points/barrels and generated/vendor module headers):

  • effect: 126 stable, 251 unstable (377 total).
  • Other packages: 208 unstable; no stable module headers.

Dependency-sensitive export tags

Module stability is the default classification, not a guarantee about every export. This follow-up changes 56 individual declaration tags in stable Effect modules to unstable:

  • Effect/Stream withExecutionPlan and Effect withErrorReporting.
  • All eight ByteSize schema interface/value declarations, three ByteSize transformations, and Stream limitBytes.
  • ConfigProvider fromDotEnv/fromDir and Logger toFile.
  • TxQueueState and its queue interfaces, guards, constructors, and dependent operations; TxPubSub subscribe/acquireSubscriber/releaseSubscriber; TxSubscriptionRef changes.

Containing module headers stay stable. Unrelated exports and APIs that use unstable implementations only internally are not blanket-reclassified.

Enforcement and generation

  • Module JSDoc and directly importable declarations, named export specifiers, and namespace exports require explicit stability. Allowed values are stable, unstable, and experimental. Nested declarations/members retain optional tags.
  • Public index files are included, including hand-maintained Vue and Vitest entry points. Import resolution supports root and nested entry-point package exports.
  • Namespace re-exports are parsed and checked. Minimal tag-only re-export JSDoc remains supported, as used by generated barrels.
  • Entry-point import guidance includes TypeScript-resolved exports, preserving canonical imports of forwarded third-party APIs.
  • Newly exposed entry-point documentation is corrected, including missing sqlite-wasm re-export stability tags.
  • Intentional tools/internal/AI-generated/vendor exclusions remain. StandardSchema is vendored; AI-generated files have unstable module headers but no per-declaration JSDoc.
  • Barrel codegen copies stable tags, CI runs the JSDoc check, and migration/JSDoc/changeset guidance documents the policy.

Verification

All commands run through nix develop -c:

  • pnpm jsdocs --check, pnpm lint, pnpm check, and git diff --check pass.
  • pnpm codegen passes and produces no additional diff.
  • Both enforcement regressions pass; all four targeted mandatory-stability checks pass.
  • Codegen tests: 2 passed. API-diff tests: 43 passed.
  • Full JSDoc suite: 27 passed, 0 failed. Legacy fixtures now document namespace re-exports with minimal stability/since tags and explicitly expect the public index record and namespace API. Both enforcement regressions and all existing diagnostic assertions are preserved; implementation is unchanged in this tests-only follow-up.
  • Follow-up validation: fresh pnpm jsdocs --check, pnpm lint, pnpm check, and git diff --check pass. Combined JSDoc, codegen, and API-diff suites: 72 passed across 11 files.
  • pnpm doctest --run packages/vitest/src/index.ts found no test files (no doctest coverage claimed).

A patch changeset covers effect and the other affected packages.

@changeset-bot

changeset-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1e14d65

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 32 packages
Name Type
effect Patch
@effect/ai-anthropic Patch
@effect/ai-cloudflare Patch
@effect/ai-openai Patch
@effect/ai-openai-compat Patch
@effect/ai-openrouter Patch
@effect/ai-typesafe Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-deno Patch
@effect/platform-node Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/vitest Patch
@effect/docgen Patch
@effect/doctest Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-janitor effect-janitor Bot added the 4.0 label Oct 5, 2026
@fubhy
fubhy requested a review from tim-smart October 5, 2026 16:28
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
arbitrary-combinators.ts 38.79 KB 38.79 KB 0.00 KB (0.00%)
basic.ts 7.06 KB 7.06 KB 0.00 KB (0.00%)
batching.ts 10.14 KB 10.14 KB 0.00 KB (0.00%)
brand.ts 6.73 KB 6.73 KB 0.00 KB (0.00%)
cache.ts 10.89 KB 10.89 KB 0.00 KB (0.00%)
config.ts 22.25 KB 22.25 KB 0.00 KB (0.00%)
differ.ts 21.34 KB 21.34 KB 0.00 KB (0.00%)
http-client.ts 22.67 KB 22.67 KB 0.00 KB (0.00%)
http-router.ts 34.06 KB 34.06 KB 0.00 KB (0.00%)
logger.ts 11.22 KB 11.22 KB 0.00 KB (0.00%)
metric.ts 9.03 KB 9.03 KB 0.00 KB (0.00%)
optic.ts 6.96 KB 6.96 KB 0.00 KB (0.00%)
pubsub.ts 15.18 KB 15.18 KB 0.00 KB (0.00%)
queue.ts 12.13 KB 12.13 KB 0.00 KB (0.00%)
schedule.ts 11.22 KB 11.22 KB 0.00 KB (0.00%)
schema-bigdecimal.ts 13.74 KB 13.74 KB 0.00 KB (0.00%)
schema-binary.ts 40.00 KB 40.00 KB 0.00 KB (0.00%)
schema-class.ts 21.07 KB 21.07 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 32.10 KB 32.10 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 27.28 KB 27.28 KB 0.00 KB (0.00%)
schema-string-transformation.ts 14.48 KB 14.48 KB 0.00 KB (0.00%)
schema-string.ts 12.00 KB 12.00 KB 0.00 KB (0.00%)
schema-template-literal.ts 16.07 KB 16.07 KB 0.00 KB (0.00%)
schema-toArbitrary.ts 38.32 KB 38.32 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 25.30 KB 25.30 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 20.26 KB 20.26 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 20.45 KB 20.45 KB 0.00 KB (0.00%)
schema-toFormatter.ts 20.57 KB 20.57 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 25.03 KB 25.03 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 20.55 KB 20.55 KB 0.00 KB (0.00%)
schema.ts 20.29 KB 20.29 KB 0.00 KB (0.00%)
stm.ts 13.24 KB 13.24 KB 0.00 KB (0.00%)
stream.ts 9.99 KB 9.99 KB 0.00 KB (0.00%)

@fubhy
fubhy requested a review from gcanti October 5, 2026 16:41
@fubhy

fubhy commented Oct 5, 2026

Copy link
Copy Markdown
Member Author

@tim-smart @gcanti please review your respective modules (and also broadly) and decide on a case by case basis. We've missed quite a few (lacking explicit markers).

@fubhy fubhy changed the title Tag every effect module with an explicit @stability Require explicit @stability on every effect module and export Oct 6, 2026
@fubhy fubhy changed the title Require explicit @stability on every effect module and export Require explicit @stability on every effect module and importable export Oct 6, 2026
@fubhy fubhy changed the title Require explicit @stability on every effect module and importable export Require explicit @stability on every module and importable export Oct 6, 2026
@tim-smart

Copy link
Copy Markdown
Contributor

/effect-bot do you think there is anything we might have missed here?

@effect-bot effect-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head, including stability classifications, directly importable exports, JSDoc enforcement, and barrel generation. The seven requested modules and their barrel exports are stable. I found two gaps in the new enforcement contract (inline comments).

Validation: the 27 existing JSDoc/codegen tests pass; pnpm jsdocs --check and pnpm lint pass; rerunning pnpm codegen leaves no diff. Temporary negative probes reproduced both enforcement gaps and were removed; no source changes or commits were made.

Non-blocking: the PR description still lists Filter, Latch, Pull, Semaphore and UndefinedOr as newly unstable, although they are now stable; the classification counts should be refreshed too.

- name: Lint
run: pnpm lint
- name: Check JSDoc
run: pnpm jsdocs --check

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Include public index exports in the stability check

The new CI command uses jsdocs.config.json, which excludes packages/**/src/index.ts altogether. This is not limited to generated barrels: the complete hand-maintained API of @effect/atom-vue and the entry-point exports of @effect/vitest are skipped as well. I removed every @stability tag from packages/atom/vue/src/index.ts locally and pnpm jsdocs --check still exited successfully. Consequently these directly importable exports have no enforcement despite the new all-exports requirement. Please add stability validation for public index files (a dedicated check is fine if the full JSDoc rules cannot apply), with a negative test for a hand-maintained index export.

@@ -2759,7 +2770,9 @@ function parseDocumentedTs(
}
addModelDiagnostics(diagnostics, block.range, block.diagnostics)
if (block.parsed === undefined) return undefined
const tags = buildTags(scope, block.parsed.tags)
// Only names that can be imported directly require @stability.
const requireStability = scope === "declaration" || (scope === "namespace" && ts.isSourceFile(node.parent))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Validate namespace re-exports as directly importable names

The new requirement only runs for nodes passed to parseDocumentedTs, but parseSourceFileDocs handles only ts.isNamedExports in its export-declaration branch and silently skips ts.NamespaceExport. Thus export * as Target from "./Target.ts" never reaches this check, even in an included non-index file. A negative extraction test using the new missingStabilityDiagnostics helper returned zero diagnostics for this export with its stability tag omitted. This export syntax is used throughout the public barrels, so including those files alone will not close the gap. Please validate the namespace-export JSDoc and require its stability tag, with a regression test for this syntax.

@tim-smart

Copy link
Copy Markdown
Contributor

/effect-bot do you think anything is mis-categorized? We also need to make sure individual exports that use other unstable modules or apis are flagged as unstable, even if they are in a stable module.

@effect-bot effect-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependency-sensitive classification audit of the latest head (01c4ebf4211af4594cd86b6c406a50a256b55c35): request changes. The inline findings are new classification issues, separate from the two enforcement gaps in my earlier review. Stable containing modules currently give stable tags to exports that expose or integrate explicitly unstable APIs: ExecutionPlan, ErrorReporter, ByteSize, filesystem/path/platform errors, and TxChunk. Please propagate instability at the individual-export level, including dependent public types.

The seven requested modules (Filter, Latch, Pull, Redactable, References, Semaphore, UndefinedOr) remain stable; I am not proposing to reverse those decisions. Existing unstable Graph, HTTP, and network schema wrappers are appropriate examples of the dependency-sensitive treatment. I found no additional module-level reclassification that I can justify from the current policy.

The earlier index-file exclusion and namespace re-export enforcement findings remain unchanged in the latest head; I have not duplicated their inline comments. The description still lists five of the requested stable modules as unstable and should be refreshed.

Validation for this pass was read-only source/signature and diff inspection, including the reporting implementation and prior review. No code or tests changed, no push, and no tests rerun.

Comment thread packages/effect/src/Effect.ts Outdated
Comment thread packages/effect/src/Effect.ts Outdated
Comment thread packages/effect/src/Schema.ts Outdated
Comment thread packages/effect/src/SchemaTransformation.ts Outdated
Comment thread packages/effect/src/Stream.ts Outdated
Comment thread packages/effect/src/ConfigProvider.ts Outdated
Comment thread packages/effect/src/Logger.ts Outdated
Comment thread packages/effect/src/TxQueue.ts Outdated
@tim-smart

Copy link
Copy Markdown
Contributor

/effect-bot can you fix those findings

fubhy and others added 15 commits October 7, 2026 01:12
Modules that were not stable in effect 3.x are now tagged
@stability unstable. All other modules are tagged @stability stable.
The jsdocs linter and barrel codegen now accept @stability stable.
Tag every public declaration, export specifier, namespace, and namespace
declaration in packages/effect with @stability, inheriting the module or
namespace stability unless already tagged. The jsdocs linter enforces the
tag for files matched by requireStability, and CI now runs
pnpm jsdocs --check.
Declarations inside namespaces are reached through an import, so they no
longer require their own @stability tag. Root declarations, export
specifiers, and namespaces still do.
These packages were 0.x in effect 3.x. Tag every module and directly
importable export @stability unstable so individual modules can be marked
stable selectively, and extend requireStability to all packages.
Every package is now tagged, so the jsdocs linter requires @stability on
module JSDoc, root declarations, export specifiers, and root namespaces
without a config option.
@effect-bot
effect-bot force-pushed the fix/effect-module-stability-tags branch from 96ed7e1 to 4a9f884 Compare October 7, 2026 01:13
@tim-smart

Copy link
Copy Markdown
Contributor

/effect-bot can you fix CI

@tim-smart
tim-smart merged commit 540ecd1 into main Oct 7, 2026
13 checks passed
@tim-smart
tim-smart deleted the fix/effect-module-stability-tags branch October 7, 2026 10:01
brandhaug added a commit to brandhaug/b2b-saas-starter that referenced this pull request Oct 10, 2026
## pnpm-workspace.yaml (default)

## Dependency Updates

| Package | From | To | Type |
| --- | --- | --- | --- |
| `@effect/platform-node` | 4.0.1 | 4.0.2 | patch |
| `@effect/sql-d1` | 4.0.1 | 4.0.2 | patch |
| `@effect/vitest` | 4.0.1 | 4.0.2 | patch |

## Release Notes

<details>
<summary><b>@<!---->effect/platform-node</b> (4.0.1 → 4.0.2)</summary>

### Patch Changes

- [#8770](Effect-TS/effect#8770)
[`540ecd1`](Effect-TS/effect@540ecd1)
Thanks @<!---->fubhy! - Tag every module and directly importable export
with an explicit `@stability`. `@stability stable` follows strict
semver, and `@stability unstable` may receive breaking changes in minor
releases.

- [#8852](Effect-TS/effect#8852)
[`7d8d497`](Effect-TS/effect@7d8d497)
Thanks @<!---->effect-bot! - Report the `101` status of a successful
WebSocket upgrade to server middleware such as `HttpMiddleware.logger`
and `HttpMiddleware.tracer`, instead of the handler's discarded response
status.

- [#8846](Effect-TS/effect#8846)
[`48a373b`](Effect-TS/effect@48a373b)
Thanks @<!---->tim-smart! - Fix keep-alive requests hanging during
graceful HTTP server shutdown.
- Updated dependencies
[[`26c1089`](Effect-TS/effect@26c1089),
[`6c59de7`](Effect-TS/effect@6c59de7),
[`467d3ac`](Effect-TS/effect@467d3ac),
[`375c1b0`](Effect-TS/effect@375c1b0),
[`45a70ce`](Effect-TS/effect@45a70ce),
[`fb757e3`](Effect-TS/effect@fb757e3),
[`716e358`](Effect-TS/effect@716e358),
[`af114e6`](Effect-TS/effect@af114e6),
[`d0b3862`](Effect-TS/effect@d0b3862),
[`7064da9`](Effect-TS/effect@7064da9

…[full
notes](https://github.com/Effect-TS/effect/releases/tag/%40effect/platform-node%404.0.2)

</details>

<details>
<summary><b>@<!---->effect/sql-d1</b> (4.0.1 → 4.0.2)</summary>

### Patch Changes

- [#8770](Effect-TS/effect#8770)
[`540ecd1`](Effect-TS/effect@540ecd1)
Thanks @<!---->fubhy! - Tag every module and directly importable export
with an explicit `@stability`. `@stability stable` follows strict
semver, and `@stability unstable` may receive breaking changes in minor
releases.

- [#8866](Effect-TS/effect#8866)
[`00f1cc7`](Effect-TS/effect@00f1cc7)
Thanks @<!---->Makisuo! - Align SQL tracing with OpenTelemetry database
conventions:
  
- Name statement spans by `db.namespace`, `server.address[:server.port]`
or `db.system.name`, falling back to `sql.execute`. The rules are
exported as `Statement.spanName` and `Statement.spanTarget`.
- Record Effect execution methods in `effect.sql.method` instead of
`db.operation.name`.
- Use internal transaction spans with
`effect.sql.transaction.commit|savepoint|rollback` events.
- Name D1 batches of two or more statements `BATCH`, or `BATCH {target}`
when a target is set, with `db.operation.name` set to `BATCH` and
`db.operation.batch.size`.

- [#8740](Effect-TS/effect#8740)
[`ec54070`](Effect-TS/effect@ec54070)
Thanks @<!---->tim-smart! - Update repository dependencies to their
latest compatible releases.
- Updated dependencies
[[`26c1089`](Effect-TS/effect@26c1089),
[`6c59de7`](Effect-TS/effect@6c59de7),
[`467d3ac`](Effect-TS/effect@467d3ac),
[`375c1b0`](Effect-TS/effect@375c1b0),
[`45a70ce`](Effect-TS/effect@45a70ce),
[`fb757e3`](Effect-TS/effect@fb757

…[full
notes](https://github.com/Effect-TS/effect/releases/tag/%40effect/sql-d1%404.0.2)

</details>

<details>
<summary><b>@<!---->effect/vitest</b> (4.0.1 → 4.0.2)</summary>

### Patch Changes

- [#8770](Effect-TS/effect#8770)
[`540ecd1`](Effect-TS/effect@540ecd1)
Thanks @<!---->fubhy! - Tag every module and directly importable export
with an explicit `@stability`. `@stability stable` follows strict
semver, and `@stability unstable` may receive breaking changes in minor
releases.
- Updated dependencies
[[`26c1089`](Effect-TS/effect@26c1089),
[`6c59de7`](Effect-TS/effect@6c59de7),
[`467d3ac`](Effect-TS/effect@467d3ac),
[`375c1b0`](Effect-TS/effect@375c1b0),
[`45a70ce`](Effect-TS/effect@45a70ce),
[`fb757e3`](Effect-TS/effect@fb757e3),
[`716e358`](Effect-TS/effect@716e358),
[`af114e6`](Effect-TS/effect@af114e6),
[`d0b3862`](Effect-TS/effect@d0b3862),
[`7064da9`](Effect-TS/effect@7064da9),
[`eee0eeb`](Effect-TS/effect@eee0eeb),
[`b9d6581`](Effect-TS/effect@b9d6581),
[`7a721ce`](Effect-TS/effect@7a721ce),
[`a0cb4c2`](Effect-TS/effect@a0cb4c2),
[`3cb395e`](Effect-TS/effect@3cb395e),
[`540ecd1`](Effect-TS/effect@540ecd1),
[`aefe05a`](https://gi

…[full
notes](https://github.com/Effect-TS/effect/releases/tag/%40effect/vitest%404.0.2)

</details>

---
*This PR was auto-generated by
[catalog-update-action](https://github.com/brandhaug/catalog-update-action).*

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
wmaurer added a commit to wmaurer/effect that referenced this pull request Oct 17, 2026
- Add `@stability unstable` to each module JSDoc, each top-level
  export, and each interface the package adds to `effect/ai/Prompt`
  and `effect/ai/Response`, as Effect-TS#8770 requires and as the other AI
  providers do; the barrel's export blocks come from
  `effect-utils codegen`. The package's `tsc` now reports no
  `effect(apiStabilityLeak)` errors
- Fix the JSDoc that `pnpm jsdocs --check` rejected in the package:
  titles for the two `**Example**` sections, a `**Details**` heading on
  the multi-paragraph `JsonSchemaDefinition` and `ConverseRequest`
  descriptions, and a code span for the `ConverseRequest` link to
  `AmazonBedrockLanguageModel.Config`, which does not resolve from the
  schema module
- Regenerate `docs/modules`, which also picks up the schema and config
  changes from the Opus 5.5 structured-output fix
- Add a minor changeset for the structured-output fix, and correct the
  tool-calling changeset, which said Converse has no native json_schema
  mode and that streaming tool calls are unsupported
- Name the generateObject live test for both of its models, one of
  which takes the tool path, and say in TODO.md which models get the
  forced object tool

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants