docs: generate each subsystem's cordis surface into its own page; delete the flat catalogs

Rebuild of the region machinery (PR3) on the post-#904 Typert projection:
renderPageRegion/renderInheritedPage live in dsh-typert-generator beside the
projection; scripts/gen-cordis-catalog.ts owns the curated SERVICE_PAGE /
EVENT_SCOPE_PAGE / SERVICE_WALK_EXEMPTIONS / LINK_MAP partition (fail-loud in
both directions, with the independent Context-merge scan backstopping the
projection's blind spot), spliceRegion, and the guarded pair auto-record.
docs/cordis-catalog/ is deleted: the flat events/services catalogs dissolve
into per-page regions and docs/cordis-catalog/core moves to docs/cordis-api/
with the inherited tier as its own generated page. The partition absorbs the
post-regrouping surface: ctx.typert → invariants.md, ctx.directoryPicker →
workspace.md, skills/* events → skills.md, and the four launcher-provided tui
accessor values join the named exemptions.
This commit is contained in:
Tianyi Cui
2026-07-30 21:40:58 +08:00
parent 44b035c711
commit f7323354bb
214 changed files with 10434 additions and 4447 deletions

364
docs/cordis-api/context.md Normal file
View File

@@ -0,0 +1,364 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Context
The context is the core Cordis object: every service, event, and lifecycle API is reached through `ctx`. Event methods are documented on [Events](events.md), effects and the current fiber on [Fiber](fiber.md), and plugin loading on [Registry](registry.md).
Root and child dependency containers for Cordis plugins.
A context is a proxy: normal property reads go through the service resolver, while `extend()`, `isolate()`, and `intercept()` create scoped child contexts without mutating their parent.
[Source](../../vendor/cordis/src/context.ts#L42)
### ctx.extend(meta?)
```ts cordis-catalog
/**
* Create a child context with extra metadata on top of the current scope.
*
* The child prototypally inherits every property of this context; own
* properties of `meta` shadow the inherited ones. The parent is not mutated.
*
* @param meta — own properties (including symbol keys) to define on the child.
* @returns a child context inheriting from this one.
*/
extend(meta = {}): this
```
Create a child context with extra metadata on top of the current scope.
The child prototypally inherits every property of this context; own properties of `meta` shadow the inherited ones. The parent is not mutated.
- `meta` — own properties (including symbol keys) to define on the child.
**Returns** a child context inheriting from this one.
[Source](../../vendor/cordis/src/context.ts#L99)
### ctx.isolate(name, label?)
```ts cordis-catalog
/**
* Create a child context with an independent service scope for `name`.
*
* Below the returned context, reads and writes of the service `name`
* resolve against the new label instead of the parent's, so a different
* implementation can be provided without affecting the parent scope.
* Passing the same `label` to two `isolate()` calls joins their scopes.
*
* @param name — the service name to isolate.
* @param label — scope label to join; defaults to a fresh unique symbol.
* @returns a child context whose `name` service resolves in the new scope.
*/
isolate(name: string, label?: symbol)
```
Create a child context with an independent service scope for `name`.
Below the returned context, reads and writes of the service `name` resolve against the new label instead of the parent's, so a different implementation can be provided without affecting the parent scope. Passing the same `label` to two `isolate()` calls joins their scopes.
- `name` — the service name to isolate.
- `label` — scope label to join; defaults to a fresh unique symbol.
**Returns** a child context whose `name` service resolves in the new scope.
[Source](../../vendor/cordis/src/context.ts#L121)
### ctx.intercept(name, config)
```ts cordis-catalog
/**
* Add service-specific intercept config for plugins started below this
* context.
*
* Plugins loaded under the returned context see `config` merged into the
* service's resolved config (ancestor entries first; see
* `Service[symbols.resolveConfig]`). The parent context is not affected.
*
* @param name — the service name whose config to intercept.
* @param config — the intercept config to merge for that service.
* @returns a child context carrying the additional intercept entry.
*/
intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): this
intercept(name: string, config: any): this
```
Add service-specific intercept config for plugins started below this context.
Plugins loaded under the returned context see `config` merged into the service's resolved config (ancestor entries first; see `Service[symbols.resolveConfig]`). The parent context is not affected.
- `name` — the service name whose config to intercept.
- `config` — the intercept config to merge for that service.
**Returns** a child context carrying the additional intercept entry.
[Source](../../vendor/cordis/src/context.ts#L139)
### ctx.root
```ts cordis-catalog
/** The root context of the application (every child context shares it). @experimental */
root: this
```
The root context of the application (every child context shares it). @experimental
[Source](../../vendor/cordis/src/context.ts#L22)
### ctx.baseUrl
```ts cordis-catalog
/** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */
baseUrl?: string
```
Base URL used to resolve relative plugin/module specifiers, if the runtime sets one.
[Source](../../vendor/cordis/src/context.ts#L24)
### ctx.events
```ts cordis-catalog
/** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */
events: EventsService
```
The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...).
[Source](../../vendor/cordis/src/context.ts#L26)
### ctx.logger
```ts cordis-catalog
/** The logging service. Call `ctx.logger(name)` for a named logger. */
logger: LoggerService
```
The logging service. Call `ctx.logger(name)` for a named logger.
[Source](../../vendor/cordis/src/context.ts#L28)
### ctx.reflect
```ts cordis-catalog
/** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */
reflect: ReflectService
```
The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...).
[Source](../../vendor/cordis/src/context.ts#L30)
### ctx.registry
```ts cordis-catalog
/** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */
registry: RegistryService
```
The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`).
[Source](../../vendor/cordis/src/context.ts#L32)
## Static members
### Context.effect
```ts cordis-catalog
/** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
static readonly effect: unique symbol
```
Symbol key under which a disposer exposes its EffectMeta diagnostics tree.
[Source](../../vendor/cordis/src/context.ts#L44)
### Context.filter
```ts cordis-catalog
/** Symbol key for a context's listener filter, consulted on every event dispatch. */
static readonly filter: unique symbol
```
Symbol key for a context's listener filter, consulted on every event dispatch.
[Source](../../vendor/cordis/src/context.ts#L46)
### Context.isolate
```ts cordis-catalog
/** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
static readonly isolate: unique symbol
```
Symbol key of the isolation map (see the `Context[symbols.isolate]` property).
[Source](../../vendor/cordis/src/context.ts#L48)
### Context.intercept
```ts cordis-catalog
/** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
static readonly intercept: unique symbol
```
Symbol key of the intercept map (see the `Context[symbols.intercept]` property).
[Source](../../vendor/cordis/src/context.ts#L50)
### Context.is(value)
```ts cordis-catalog
/**
* Returns true for Cordis context proxies and context prototypes.
*
* Works across realms and across multiple copies of cordis, because the
* brand is keyed by a global symbol rather than by `instanceof`.
*
* @param value — the value to test.
* @returns `true` if `value` is a Cordis context, narrowing its type.
*/
static is(value: any): value is Context
```
Returns true for Cordis context proxies and context prototypes.
Works across realms and across multiple copies of cordis, because the brand is keyed by a global symbol rather than by `instanceof`.
- `value` — the value to test.
**Returns** `true` if `value` is a Cordis context, narrowing its type.
[Source](../../vendor/cordis/src/context.ts#L61)
## Service store and mixins
### ctx.get(name, strict?)
```ts cordis-catalog
/**
* Read a service from the store without the inject requirement.
*
* @param name — the service name.
* @param strict — when `true` (default), only return implementations
* whose providing fiber is currently active.
* @returns the service value, or `undefined` when not (yet) provided.
*/
get<K extends string & keyof this>(name: K, strict?: boolean): undefined | this[K]
get(name: string, strict?: boolean): any
```
Read a service from the store without the inject requirement.
- `name` — the service name.
- `strict` — when `true` (default), only return implementations whose providing fiber is currently active.
**Returns** the service value, or `undefined` when not (yet) provided.
[Source](../../vendor/cordis/src/reflect.ts#L17)
### ctx.set(name, value)
```ts cordis-catalog
/**
* Overwrite a provided service's value.
*
* Only the fiber that provided the service may set it; setting an
* unprovided name throws.
*
* @param name — the service name.
* @param value — the new service value.
*/
set<K extends string & keyof this>(name: K, value: undefined | this[K]): void
set(name: string, value: any): void
```
Overwrite a provided service's value.
Only the fiber that provided the service may set it; setting an unprovided name throws.
- `name` — the service name.
- `value` — the new service value.
[Source](../../vendor/cordis/src/reflect.ts#L29)
### ctx.provide(name, value)
```ts cordis-catalog
/**
* Register a service implementation owned by the current fiber.
*
* The service becomes visible to dependents in the same isolation scope
* once the fiber is active; it is unregistered (waking dependents) when
* the returned disposer runs or the fiber unloads. Throws if the name is
* already provided in this scope or declared as an accessor.
*
* @param name — the service name.
* @param value — the service value.
* @returns a disposer that unregisters the service.
*/
provide<K extends string & keyof this>(name: K, value: undefined | this[K]): () => void
provide(name: string, value?: any): () => void
```
Register a service implementation owned by the current fiber.
The service becomes visible to dependents in the same isolation scope once the fiber is active; it is unregistered (waking dependents) when the returned disposer runs or the fiber unloads. Throws if the name is already provided in this scope or declared as an accessor.
- `name` — the service name.
- `value` — the service value.
**Returns** a disposer that unregisters the service.
[Source](../../vendor/cordis/src/reflect.ts#L44)
### ctx.accessor(name, options)
```ts cordis-catalog
/**
* Define a computed context property backed by get/set hooks.
*
* The accessor is removed when the current fiber unloads. Throws if the
* name is already declared.
*
* @param name — the context property name.
* @param options — the `get` hook and optional `set` hook.
*/
accessor(name: string, options: Omit<Property.Accessor, 'type'>): void
```
Define a computed context property backed by get/set hooks.
The accessor is removed when the current fiber unloads. Throws if the name is already declared.
- `name` — the context property name.
- `options` — the `get` hook and optional `set` hook.
[Source](../../vendor/cordis/src/reflect.ts#L56)
### ctx.mixin(name, mixins)
```ts cordis-catalog
/**
* Expose selected members of a service directly on `ctx`.
*
* Each mixed-in key becomes an accessor that forwards to the service
* (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`.
* Mixins are removed when the current fiber unloads.
*
* @param name — the context property holding the source service.
* @param mixins — keys to forward, or a source-key → ctx-key map.
*/
mixin<K extends string & keyof this>(name: K, mixins: (keyof this & keyof this[K])[] | Dict<string>): void
mixin<T extends {}>(source: T, mixins: (keyof this & keyof T)[] | Dict<string>): void
```
Expose selected members of a service directly on `ctx`.
Each mixed-in key becomes an accessor that forwards to the service (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`. Mixins are removed when the current fiber unloads.
- `name` — the context property holding the source service.
- `mixins` — keys to forward, or a source-key → ctx-key map.
[Source](../../vendor/cordis/src/reflect.ts#L67)

207
docs/cordis-api/events.md Normal file
View File

@@ -0,0 +1,207 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Events
The event-dispatch API mixed into every context. Harness event declarations and their dispatch modes are generated into each owning [subsystem page](../subsystems/core.md).
### ctx.parallel(name, ...args)
```ts cordis-catalog
/**
* Dispatch an event, running all listeners concurrently.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
* @returns a promise resolving once every listener has settled.
*/
parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>
parallel<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promise<void>
```
Dispatch an event, running all listeners concurrently.
- `name` — the event name.
- `args` — arguments passed to every listener.
**Returns** a promise resolving once every listener has settled.
[Source](../../vendor/cordis/src/events.ts#L44)
### ctx.emit(name, ...args)
```ts cordis-catalog
/**
* Dispatch an event synchronously, ignoring listener return values.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
*/
emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void
emit<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): void
```
Dispatch an event synchronously, ignoring listener return values.
- `name` — the event name.
- `args` — arguments passed to every listener.
[Source](../../vendor/cordis/src/events.ts#L53)
### ctx.serial(name, ...args)
```ts cordis-catalog
/**
* Dispatch an event, awaiting listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
serial<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
serial<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
```
Dispatch an event, awaiting listeners in order until one bails.
- `name` — the event name.
- `args` — arguments passed to each listener.
**Returns** the first bail value (non-null, non-false, non-undefined), if any.
[Source](../../vendor/cordis/src/events.ts#L63)
### ctx.bail(name, ...args)
```ts cordis-catalog
/**
* Dispatch an event, calling listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
bail<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
bail<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
```
Dispatch an event, calling listeners in order until one bails.
- `name` — the event name.
- `args` — arguments passed to each listener.
**Returns** the first bail value (non-null, non-false, non-undefined), if any.
[Source](../../vendor/cordis/src/events.ts#L73)
### ctx.waterfall(name, ...args)
```ts cordis-catalog
/**
* Dispatch an event whose last argument is a `next` continuation.
*
* Each listener wraps the rest of the chain: calling `next()` invokes the
* next listener (finally the built-in behavior); not calling it vetoes.
*
* @param name — the event name.
* @param args — listener arguments; the final one is the innermost `next`.
* @returns the outermost listener's return value.
*/
waterfall<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
waterfall<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
```
Dispatch an event whose last argument is a `next` continuation.
Each listener wraps the rest of the chain: calling `next()` invokes the next listener (finally the built-in behavior); not calling it vetoes.
- `name` — the event name.
- `args` — listener arguments; the final one is the innermost `next`.
**Returns** the outermost listener's return value.
[Source](../../vendor/cordis/src/events.ts#L86)
### ctx.on(name, listener, options?)
```ts cordis-catalog
/**
* Register an event listener owned by the current fiber.
*
* @param name — the event name to listen for.
* @param listener — called with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
on<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
```
Register an event listener owned by the current fiber.
- `name` — the event name to listen for.
- `listener` — called with the dispatch arguments.
- `options` — listener options; a boolean is shorthand for `prepend`.
**Returns** a disposer removing the listener; `true` if it was still registered.
[Source](../../vendor/cordis/src/events.ts#L97)
### ctx.once(name, listener, options?)
```ts cordis-catalog
/**
* Same as `on()`, but the listener disposes itself after its first call.
*
* @param name — the event name to listen for.
* @param listener — called at most once with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
once<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
```
Same as `on()`, but the listener disposes itself after its first call.
- `name` — the event name to listen for.
- `listener` — called at most once with the dispatch arguments.
- `options` — listener options; a boolean is shorthand for `prepend`.
**Returns** a disposer removing the listener; `true` if it was still registered.
[Source](../../vendor/cordis/src/events.ts#L106)
## EventOptions
Options accepted by `ctx.on()` and `ctx.once()`.
```ts cordis-catalog
/** Options accepted by `ctx.on()` and `ctx.once()`. */
interface EventOptions {
/** Add the listener before existing listeners for the same event. */
prepend?: boolean
/** Receive the event regardless of context filter checks. */
global?: boolean
}
```
[Source](../../vendor/cordis/src/events.ts#L112)
## DispatchMode
Event dispatch strategy used by the event service.
`emit` runs synchronous listeners without awaiting them, `parallel` awaits all listeners together, `serial` awaits them in order until one bails, `bail` stops on the first synchronous bail value, and `waterfall` composes listeners around a final `next` callback.
```ts cordis-catalog
/**
* Event dispatch strategy used by the event service.
*
* `emit` runs synchronous listeners without awaiting them, `parallel` awaits
* all listeners together, `serial` awaits them in order until one bails,
* `bail` stops on the first synchronous bail value, and `waterfall` composes
* listeners around a final `next` callback.
*/
type DispatchMode = 'emit' | 'parallel' | 'serial' | 'bail' | 'waterfall'
```
[Source](../../vendor/cordis/src/events.ts#L32)

375
docs/cordis-api/fiber.md Normal file
View File

@@ -0,0 +1,375 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Fiber
A fiber is one loaded plugin instance: its lifecycle state, validated config, and registered effects. `ctx.fiber` is the current fiber, and `ctx.effect()` delegates to it.
### ctx.effect(execute, label?)
```ts cordis-catalog
/**
* Register a cleanup-aware effect on this fiber.
*
* `execute` runs immediately; the disposers it produces are collected and
* run (in reverse order) either when the returned disposer is called or
* when the fiber unloads, whichever comes first. Calling the disposer twice
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
* already disposed, and `TypeError` if `execute` returns an invalid shape.
*
* @param execute — the effect body; see {@link Effect} for accepted shapes.
* @param label — effect label shown in `getEffects()` diagnostics.
* @returns a disposer that tears the effect down and settles once done.
*/
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
```
Register a cleanup-aware effect on this fiber.
`execute` runs immediately; the disposers it produces are collected and run (in reverse order) either when the returned disposer is called or when the fiber unloads, whichever comes first. Calling the disposer twice is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is already disposed, and `TypeError` if `execute` returns an invalid shape.
- `execute` — the effect body; see `Effect` for accepted shapes.
- `label` — effect label shown in `getEffects()` diagnostics.
**Returns** a disposer that tears the effect down and settles once done.
[Source](../../vendor/cordis/src/fiber.ts#L420)
### ctx.fiber
```ts cordis-catalog
/** The fiber (plugin runtime instance) that owns this context. */
fiber: Fiber
```
The fiber (plugin runtime instance) that owns this context.
[Source](../../vendor/cordis/src/fiber.ts#L12)
## The Fiber class
Runtime instance of one plugin application.
A fiber tracks dependency state, validated config, lifecycle effects, and cleanup for the plugin context returned by `ctx.plugin()`.
[Source](../../vendor/cordis/src/fiber.ts#L184)
### fiber.uid
```ts cordis-catalog
/** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
public uid: number | null
```
Unique id within the registry; 0 for the root fiber, `null` once disposed.
[Source](../../vendor/cordis/src/fiber.ts#L186)
### fiber.ctx
```ts cordis-catalog
/** The context this fiber's plugin runs in (extends the parent context). */
public readonly ctx: Context
```
The context this fiber's plugin runs in (extends the parent context).
[Source](../../vendor/cordis/src/fiber.ts#L188)
### fiber.config
```ts cordis-catalog
/** The validated plugin config (updated by `update()`). */
public config: any
```
The validated plugin config (updated by `update()`).
[Source](../../vendor/cordis/src/fiber.ts#L190)
### fiber.state
```ts cordis-catalog
/** Current lifecycle state; transitions emit `internal/status`. */
public state
```
Current lifecycle state; transitions emit `internal/status`.
[Source](../../vendor/cordis/src/fiber.ts#L192)
### fiber.dispose
```ts cordis-catalog
/** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
public readonly dispose: () => Promise<void>
```
Dispose this fiber: unload the plugin, then settle once cleanup finished.
[Source](../../vendor/cordis/src/fiber.ts#L194)
### fiber.store
```ts cordis-catalog
/** Snapshot of required service implementations while loaded; `undefined` otherwise. */
public store: Dict<Impl> | undefined
```
Snapshot of required service implementations while loaded; `undefined` otherwise.
[Source](../../vendor/cordis/src/fiber.ts#L196)
### fiber.inertia
```ts cordis-catalog
/** The in-flight load/unload transition, if one is currently running. */
public inertia: Promise<void> | undefined
```
The in-flight load/unload transition, if one is currently running.
[Source](../../vendor/cordis/src/fiber.ts#L198)
### fiber.name
```ts cordis-catalog
/** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
get name()
```
The plugin's display name, inherited from the nearest named ancestor, else `'root'`.
[Source](../../vendor/cordis/src/fiber.ts#L341)
### fiber.assertActive()
```ts cordis-catalog
/**
* Throw if the fiber has already been disposed.
*
* @returns nothing when the fiber is still active.
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
*/
assertActive()
```
Throw if the fiber has already been disposed.
**Returns** nothing when the fiber is still active.
[Source](../../vendor/cordis/src/fiber.ts#L356)
### fiber.effect(execute, label?)
```ts cordis-catalog
/**
* Register a cleanup-aware effect on this fiber.
*
* `execute` runs immediately; the disposers it produces are collected and
* run (in reverse order) either when the returned disposer is called or
* when the fiber unloads, whichever comes first. Calling the disposer twice
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
* already disposed, and `TypeError` if `execute` returns an invalid shape.
*
* @param execute — the effect body; see {@link Effect} for accepted shapes.
* @param label — effect label shown in `getEffects()` diagnostics.
* @returns a disposer that tears the effect down and settles once done.
*/
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
```
Register a cleanup-aware effect on this fiber.
`execute` runs immediately; the disposers it produces are collected and run (in reverse order) either when the returned disposer is called or when the fiber unloads, whichever comes first. Calling the disposer twice is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is already disposed, and `TypeError` if `execute` returns an invalid shape.
- `execute` — the effect body; see `Effect` for accepted shapes.
- `label` — effect label shown in `getEffects()` diagnostics.
**Returns** a disposer that tears the effect down and settles once done.
[Source](../../vendor/cordis/src/fiber.ts#L420)
### fiber.getEffects()
```ts cordis-catalog
/**
* Return metadata for currently registered effects.
*
* @returns one {@link EffectMeta} tree per labeled live effect.
*/
getEffects()
```
Return metadata for currently registered effects.
**Returns** one `EffectMeta` tree per labeled live effect.
[Source](../../vendor/cordis/src/fiber.ts#L573)
### fiber.await()
```ts cordis-catalog
/**
* Wait for current lifecycle work and rethrow startup errors.
*
* @returns this fiber, once it has settled into a stable state.
* @throws the config-validation or plugin-startup error, if any.
*/
async await()
```
Wait for current lifecycle work and rethrow startup errors.
**Returns** this fiber, once it has settled into a stable state.
[Source](../../vendor/cordis/src/fiber.ts#L702)
### fiber.restart()
```ts cordis-catalog
/**
* Dispose and immediately reload this plugin with its current config.
*
* @returns a promise resolving once the reload settled.
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
*/
async restart()
```
Dispose and immediately reload this plugin with its current config.
**Returns** a promise resolving once the reload settled.
[Source](../../vendor/cordis/src/fiber.ts#L716)
### fiber.update(config, noSave?)
```ts cordis-catalog
/**
* Validate and apply new config, then restart the plugin.
*
* Runs the `internal/update` waterfall first, so update hooks (and HMR)
* can veto or replace the restart.
*
* @param config — the new raw config; validated before anything restarts.
* @param noSave — hint for persistence hooks not to write the change back.
* @returns the update waterfall result; the default restart returns a promise.
* @throws when validation, an update listener, or the restarted plugin fails.
*/
update(config: any, noSave = false)
```
Validate and apply new config, then restart the plugin.
Runs the `internal/update` waterfall first, so update hooks (and HMR) can veto or replace the restart.
- `config` — the new raw config; validated before anything restarts.
- `noSave` — hint for persistence hooks not to write the change back.
**Returns** the update waterfall result; the default restart returns a promise.
[Source](../../vendor/cordis/src/fiber.ts#L734)
## Effect
Effect body result accepted by `ctx.effect()` and plugin startup.
Either a single disposer, a promise of one, or a (possibly async) iterable yielding several — generator effects register each yielded disposer as it is produced.
```ts cordis-catalog
/**
* Effect body result accepted by `ctx.effect()` and plugin startup.
*
* Either a single disposer, a promise of one, or a (possibly async) iterable
* yielding several — generator effects register each yielded disposer as it
* is produced.
*/
type Effect<T = any> =
| SyncEffect<T>
| AsyncEffect<T>
```
[Source](../../vendor/cordis/src/fiber.ts#L83)
## Disposable
Function returned by an effect to release resources during disposal.
Disposers run in reverse registration order when the owning fiber unloads; they may be async, in which case unloading awaits them.
```ts cordis-catalog
/**
* Function returned by an effect to release resources during disposal.
*
* Disposers run in reverse registration order when the owning fiber unloads;
* they may be async, in which case unloading awaits them.
*/
type Disposable<T = any> = () => T
```
[Source](../../vendor/cordis/src/fiber.ts#L74)
## EffectMeta
Tree node used to expose nested effect labels for diagnostics.
```ts cordis-catalog
/** Tree node used to expose nested effect labels for diagnostics. */
interface EffectMeta {
/** Human-readable effect label, e.g. `ctx.on("event")` or `ctx.provide("name")`. */
label: string
/** Metadata of nested effects registered while this effect ran. */
children: EffectMeta[]
}
```
[Source](../../vendor/cordis/src/fiber.ts#L96)
## CordisError
Framework error with a stable machine-readable code.
```ts cordis-catalog
/** Framework error with a stable machine-readable code. */
class CordisError extends Error {
/**
* @param code — the stable error code; also the default message.
* @param message — optional human-readable override.
*/
constructor(public code: CordisError.Code, message?: string)
}
/** Cordis error code definitions. */
namespace CordisError {
export type Code = keyof typeof Code
export const Code = {
INACTIVE_EFFECT: 'cannot create effect on inactive context',
} as const
}
```
[Source](../../vendor/cordis/src/fiber.ts#L157)
## ValidationError
Error raised when plugin configuration fails standard-schema validation.
```ts cordis-catalog
/** Error raised when plugin configuration fails standard-schema validation. */
class ValidationError extends TypeError {
name = 'ValidationError'
/**
* Build the aggregated message from schema issues.
*
* @param issues — the standard-schema issues, one message line each.
*/
constructor(issues: readonly StandardSchemaV1.Issue[])
}
```
[Source](../../vendor/cordis/src/fiber.ts#L19)

View File

@@ -0,0 +1,39 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Inherited Cordis Surface
The framework `ctx` members and events every plugin sees beyond the harness tier — pinned vendor source ([vendoring policy](../../vendor/README.md)), summarized tersely so the harness pages stay focused on repository-owned vocabulary. Detailed Context, Fiber, Registry, and Service APIs are generated in [context.md](context.md), [fiber.md](fiber.md), [registry.md](registry.md), and [service.md](service.md); the event-dispatch methods in [events.md](events.md).
This file is GENERATED from source (`scripts/gen-cordis-catalog.ts`) and verified fresh by `pnpm run verify-cordis-catalog` (part of `doc-sync`) — do not edit it by hand. Signature blocks use a `ts cordis-catalog` fence and include the original source JSDoc immediately before each event or service method. doc-typecheck skips these bare declaration fragments; type names in a signature link to the page that documents them.
## Inherited `ctx` members (cordis core + loader/hmr/timer)
- `ctx.on / ctx.once` — Register an event listener (disposable). ([`vendor/cordis/src/events.ts:34`](../../vendor/cordis/src/events.ts))
- `ctx.emit / ctx.parallel / ctx.serial / ctx.bail / ctx.waterfall` — Dispatch an event (sync / awaited / first-bail / veto-chain). ([`vendor/cordis/src/events.ts:34`](../../vendor/cordis/src/events.ts))
- `ctx.plugin / ctx.inject` — Load a plugin / declare required services. ([`vendor/cordis/src/registry.ts:164`](../../vendor/cordis/src/registry.ts))
- `ctx.effect` — Register a disposable side effect tied to the fiber. ([`vendor/cordis/src/fiber.ts:9`](../../vendor/cordis/src/fiber.ts))
- `ctx.get / ctx.set / ctx.provide / ctx.accessor / ctx.mixin` — Low-level service-store access and binding. ([`vendor/cordis/src/reflect.ts:7`](../../vendor/cordis/src/reflect.ts))
- `ctx.extend / ctx.isolate / ctx.intercept` — Derive a child context (scoped services / isolation / interception). ([`vendor/cordis/src/context.ts:42`](../../vendor/cordis/src/context.ts))
- `ctx.root / ctx.scope / ctx.fiber / ctx.registry / ctx.reflect / ctx.events / ctx.logger` — Ambient handles onto the running context graph. ([`vendor/cordis/src/context.ts:16`](../../vendor/cordis/src/context.ts))
- `ctx.timer (+ interval / timeout / throttle / debounce / setTimeout / setInterval)` — Disposable timer helpers. The `timer` key is provided at runtime; the six helpers are mixed onto ctx directly (declared via Pick). ([`vendor/timer/src/index.ts:4`](../../vendor/timer/src/index.ts))
- `ctx.loader` — The config Loader that booted the app (present under the loader). ([`vendor/loader/src/index.ts:30`](../../vendor/loader/src/index.ts))
- `ctx.hmr` — The hot-module-reload watcher (present under the hmr plugin). ([`vendor/hmr/src/index.ts:15`](../../vendor/hmr/src/index.ts))
## Inherited events (cordis core + loader/hmr/timer)
- `internal/plugin` — A plugin fiber was created. ([`vendor/cordis/src/events.ts:328`](../../vendor/cordis/src/events.ts))
- `internal/status` — A fiber changed lifecycle state. ([`vendor/cordis/src/events.ts:330`](../../vendor/cordis/src/events.ts))
- `internal/service` — Interception hook for a service binding (no core producer). ([`vendor/cordis/src/events.ts:332`](../../vendor/cordis/src/events.ts))
- `internal/update` — Waterfall: a fiber config update is being applied. ([`vendor/cordis/src/events.ts:334`](../../vendor/cordis/src/events.ts))
- `internal/get` — Waterfall: a service is being read from the store. ([`vendor/cordis/src/events.ts:336`](../../vendor/cordis/src/events.ts))
- `internal/set` — Waterfall: a service is being written to the store. ([`vendor/cordis/src/events.ts:338`](../../vendor/cordis/src/events.ts))
- `internal/listener` — A listener was registered. ([`vendor/cordis/src/events.ts:340`](../../vendor/cordis/src/events.ts))
- `internal/dispatch` — An event is being dispatched to listeners. ([`vendor/cordis/src/events.ts:342`](../../vendor/cordis/src/events.ts))
- `hmr/change` — A watched source file changed on disk. ([`vendor/hmr/src/index.ts:20`](../../vendor/hmr/src/index.ts))
- `hmr/reload` — Plugins are being reloaded after a change. ([`vendor/hmr/src/index.ts:21`](../../vendor/hmr/src/index.ts))
- `exit` — The process is exiting on a signal. ([`vendor/loader/src/index.ts:23`](../../vendor/loader/src/index.ts))
- `loader/config-update` — The loader config tree changed. ([`vendor/loader/src/index.ts:24`](../../vendor/loader/src/index.ts))
- `loader/entry-init` — A config entry is being initialized. ([`vendor/loader/src/index.ts:25`](../../vendor/loader/src/index.ts))
- `loader/partial-dispose` — An entry is being partially disposed on reload. ([`vendor/loader/src/index.ts:26`](../../vendor/loader/src/index.ts))
- `loader/patch-context` — A context is being patched during a reload. ([`vendor/loader/src/index.ts:27`](../../vendor/loader/src/index.ts))

152
docs/cordis-api/registry.md Normal file
View File

@@ -0,0 +1,152 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Registry
Plugin loading and dependency injection.
### ctx.inject(deps, callback)
```ts cordis-catalog
/**
* Run a callback once the requested services are available.
*
* Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback
* is unloaded and re-run whenever a required service changes.
*
* @param deps — required services, as an array or a name → config map.
* @param callback — plugin body called with `(ctx, config)`.
* @returns the fiber; awaiting it settles once loading finished.
*/
inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>
```
Run a callback once the requested services are available.
Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback is unloaded and re-run whenever a required service changes.
- `deps` — required services, as an array or a name → config map.
- `callback` — plugin body called with `(ctx, config)`.
**Returns** the fiber; awaiting it settles once loading finished.
[Source](../../vendor/cordis/src/registry.ts#L176)
### ctx.plugin(plugin, ...args)
```ts cordis-catalog
/**
* Load a plugin in the current context.
*
* @param plugin — a function, class, or `{ apply }` object plugin.
* @param args — the plugin config, validated against its `Config` schema.
* @returns the fiber; awaiting it settles once loading finished
* (rejecting on config or startup errors).
*/
plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>
```
Load a plugin in the current context.
- `plugin` — a function, class, or `{ apply }` object plugin.
- `args` — the plugin config, validated against its `Config` schema.
**Returns** the fiber; awaiting it settles once loading finished (rejecting on config or startup errors).
[Source](../../vendor/cordis/src/registry.ts#L185)
## Plugin
Supported plugin entrypoint shapes.
```ts cordis-catalog
/** Supported plugin entrypoint shapes. */
type Plugin<T = any> =
| Plugin.Function<T>
| Plugin.Constructor<T>
| Plugin.Object<T>
/** Types associated with plugin entrypoints and runtime records. */
namespace Plugin {
/** Shared metadata understood by the plugin registry and related tooling. */
export interface Base<T = any> {
/** Display name used for fiber diagnostics and logger names. */
name?: string
/** Standard-schema validator applied to config before the plugin starts. */
Config?: StandardSchemaV1<any, T>
/** Services the plugin requires; it only loads while all are available. */
inject?: Inject
/** Service name(s) the plugin provides (read by `Service` and by loaders). */
provide?: string | string[]
/** Service names whose intercept config the plugin declares it consumes. */
intercept?: Dict<boolean>
}
export interface Transform<S, T> {
/** Marks the transform object as a schema/config transform. */
schema?: true
/** Convert user-facing config to runtime config. */
Config: (config: S) => T
}
/** Function plugin called with `(ctx, config)`. */
export interface Function<T = any> extends Base<T> {
(ctx: Context, config: T): any
}
/** Class plugin constructed with `(ctx, config)`. */
export interface Constructor<T = any> extends Base<T> {
new (ctx: Context, config: T): any
}
/** Object plugin with an `apply(ctx, config)` method. */
export interface Object<T = any> extends Base<T> {
apply(ctx: Context, config: T): any
}
/** Mutable registry record shared by all fibers of one plugin callback. */
export interface Runtime {
/** Display name copied from the first registered plugin shape. */
name?: string
/** Every live fiber of this plugin (one per `ctx.plugin()` call). */
fibers: DisposableList<Fiber>
/** The executable entrypoint all fibers share (registry identity key). */
callback: globalThis.Function
/** Standard-schema validator applied to each fiber's config. */
Config?: StandardSchemaV1
}
}
```
[Source](../../vendor/cordis/src/registry.ts#L92)
## Inject
Service dependency declaration accepted by plugins and the `@Inject` decorator.
Array form requests services without intercept config. Object form maps each service name to optional intercept config for the plugin context.
```ts cordis-catalog
/**
* Service dependency declaration accepted by plugins and the `@Inject`
* decorator.
*
* Array form requests services without intercept config. Object form maps each
* service name to optional intercept config for the plugin context.
*/
type Inject<M = Dict> = (keyof M)[] | { [K in keyof M]?: M[K] }
/** Utilities for normalizing plugin dependency declarations. */
namespace Inject {
/**
* Convert array/object/class-inherited inject metadata into a plain map.
*
* @param inject — the declaration to normalize; `null`/`undefined` add nothing.
* @param result — the map to fill (service name → intercept config or `null`).
* @returns `result`.
*/
export function resolve(inject: Inject | null | undefined, result: Dict = Object.create(null))
}
```
[Source](../../vendor/cordis/src/registry.ts#L19)

102
docs/cordis-api/service.md Normal file
View File

@@ -0,0 +1,102 @@
<!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
Run `pnpm run gen-cordis-catalog` to regenerate. -->
# Service
The base class for context services. A subclass loaded as a plugin registers itself as `ctx.<name>`.
Base class for services that expose a named API on `ctx`.
Subclasses call `super(ctx, name)` from their constructor. The service is registered immediately and is automatically removed with the owning fiber.
[Source](../../vendor/cordis/src/service.ts#L11)
### service.name
```ts cordis-catalog
/** The service name this instance is registered under. */
public name!: string
```
The service name this instance is registered under.
[Source](../../vendor/cordis/src/service.ts#L30)
## Static members
### Service.init
```ts cordis-catalog
/** Symbol key of an instance method run after construction (class plugins). */
static readonly init: unique symbol
```
Symbol key of an instance method run after construction (class plugins).
[Source](../../vendor/cordis/src/service.ts#L13)
### Service.check
```ts cordis-catalog
/** Symbol key of the availability predicate passed to `ctx.provide()`. */
static readonly check: unique symbol
```
Symbol key of the availability predicate passed to `ctx.provide()`.
[Source](../../vendor/cordis/src/service.ts#L15)
### Service.config
```ts cordis-catalog
/** Symbol key of the phantom intercept-config type parameter. */
static readonly config: unique symbol
```
Symbol key of the phantom intercept-config type parameter.
[Source](../../vendor/cordis/src/service.ts#L17)
### Service.invoke
```ts cordis-catalog
/** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
static readonly invoke: unique symbol
```
Symbol key of the call body making a service callable (e.g. `ctx.logger()`).
[Source](../../vendor/cordis/src/service.ts#L19)
### Service.extend
```ts cordis-catalog
/** Symbol key of the helper deriving an extended service instance. */
static readonly extend: unique symbol
```
Symbol key of the helper deriving an extended service instance.
[Source](../../vendor/cordis/src/service.ts#L21)
### Service.tracker
```ts cordis-catalog
/** Symbol key of the tracker metadata used for context tracing. */
static readonly tracker: unique symbol
```
Symbol key of the tracker metadata used for context tracing.
[Source](../../vendor/cordis/src/service.ts#L23)
### Service.resolveConfig
```ts cordis-catalog
/** Symbol key of the intercept-config resolution helper below. */
static readonly resolveConfig: unique symbol
```
Symbol key of the intercept-config resolution helper below.
[Source](../../vendor/cordis/src/service.ts#L25)