2026-08-07 — Documentation tags and the type layout

Two passes over the source ahead of the 1.0.0 tag, both structural rather than behavioural. No exported symbol changed: lib/index.d.ts carries the same 42 names before and after.

Kind tags lead the block

Every doc block opened with its summary and carried its kind tag — @class, @interface, @typedef, @module, @constant, @function — near the bottom, wedged between the last @typeParam and @author. The tag now comes first:

/**
 * @class
 *
 * A limiter that counts nothing.
 * ...
 */

54 files: the 52 under src/, plus eslint.config.ts and rollup.config.ts. Two blocks carried no kind tag at all — eslint.config.ts's default export and rollup.config.ts's header — and were given @constant and @module.

The nine test/**/*.spec.ts files were left alone. Their top block documents a describe() call rather than an exported declaration, and they sit outside both TypeDoc's entry points and ESLint's files list, so a tag there would be inert.

Not enforced yet. The documentation plugin already carries kind-tag-without-argument, which checks that a kind tag has no argument but not that one exists or leads the block. A fourth rule would close the gap; without one this holds only as long as everyone remembers it, which is the same reason the other three exist.

types/ grouped into subdirectories

types/capabilities/ had grown to 21 flat files, over half of them supporting shapes rather than capabilities. A capability that owns shapes now gets a directory and takes them with it:

Directory Contents
object/ ObjectStore, StoredObject
request/ RequestMetadata, RequestFacts
sql/ DataStore, SqlConnectionProvider, SqlCredentials, SqlStatement, SqlTarget, SqlWriteResult
telemetry/ TelemetrySink, RequestMetric
vector/ VectorIndex, VectorMatch

Capability stays at the root, along with the five capabilities that are a single interface each — CacheStore, CoordinationStore, InferenceEngine, MessageQueue, RateLimiter. A subject with one shape to its name does not earn a directory.

Membership follows what a shape belongs to rather than what it is named, which is worth stating because two of the placements read as wrong at a glance:

  • RequestMetric is under telemetry/, not with the two types that share its prefix. TelemetrySink is the only thing that accepts one, and request/ is otherwise about deciding which header may be believed.
  • DataStore is under sql/. It is relational storage addressed with SQL and it imports SqlStatement and SqlWriteResult; leaving it flat would have split the SQL surface across two levels.

Under types/ itself, logging/ now holds LogLevel and LogContext. LoggingSettings stays at the root beside SecuritySettings and SystemConfiguration — it is read through resolve('logging') like any other settings shape — and is re-exported through logging/index.ts, so the grouping shows up in the barrel without splitting the configuration shapes across two directories.

Each new directory has an index.ts with a @module block, matching core/noop/, and the parent barrels re-export from the directory rather than reaching into files. SqlTarget's relative link to SqlCredentials survived the move untouched; LogLevel's link to Logger needed a second ../.

SecuritySettings, SystemConfiguration, and Overrides are the one cluster left flat. A configuration/ directory would finish the pattern and is deliberately deferred rather than forgotten.

Verification

npm run lint, npm run test:run (85 specs, nine suites), npm run build, and npm run build:docs all clean. The docs build is the one that matters for a move of this size: typedoc.json sets treatWarningsAsErrors alongside validation.invalidLink, so a relative link left pointing at an old path fails the build rather than shipping as a dead link.

results matching ""

    No results matching ""