Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
# `instruments`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Lazily resolves the OpenTelemetry instruments (`Counter`, `Histogram`)
the plugin emits from its production paths. The bundle is built on
first call and cached; tests call `resetTenantPluginInstruments` after
installing a fresh `MeterProvider` so subsequent calls rebind to the
test exporter. This pattern lets the package work seamlessly in
production (where the global provider is the OTel SDK) and under test
(where the global provider is an `InMemoryMetricExporter`).
## Features
- Four instruments: `resolutionsTotal` (counter),
`resolutionDurationMs` (histogram), `cacheTotal` (counter),
`managementOpsTotal` (counter).
- Lazy initialisation — the meter is resolved on first call so test
polyfills installed before the package loads bind correctly.
- `resetTenantPluginInstruments` clears the cache so a re-bind is
forced; primarily useful in test setup hooks.
## Usage: Basic Example
```ts
import { getTenantPluginInstruments } from "@suaveplan/api-plugin-tenant";
const instruments = getTenantPluginInstruments();
instruments.resolutionsTotal.add(1, { outcome: "resolved", strategy: "header" });
instruments.resolutionDurationMs.record(12.4, { strategy: "header" });
```
## Usage: Advanced Example
```ts
import {
getTenantPluginInstruments,
resetTenantPluginInstruments,
} from "@suaveplan/api-plugin-tenant";
import { metrics } from "@opentelemetry/api";
import { InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader, AggregationTemporality } from "@opentelemetry/sdk-metrics";
// In test setup before the package's other modules load:
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetTenantPluginInstruments();
// Later — assert the counters that were emitted:
await provider.forceFlush();
const collected = exporter.getMetrics();
const resolutions = collected[0]?.scopeMetrics[0]?.metrics.find(
(m) => m.descriptor.name === "tenant_plugin.resolutions_total"
);
console.assert(resolutions !== undefined);
```
## API Reference
- `interface TenantPluginInstruments` — `{ resolutionsTotal: Counter,
resolutionDurationMs: Histogram, cacheTotal: Counter,
managementOpsTotal: Counter }`.
- `function getTenantPluginInstruments(): TenantPluginInstruments` —
returns the cached bundle, building it on first call.
- `function resetTenantPluginInstruments(): void` — drops the cache.
## Implementation Notes
The lazy pattern is essential — calling `metrics.getMeter("...")` at
module top-level binds to whichever `MeterProvider` was installed at
import time. Because Vitest's `setupFiles` run before `src/` modules
import, installing the in-memory provider there guarantees the test
bundle binds correctly. Production callers that install their OTel SDK
late (e.g. behind a feature flag) call `resetTenantPluginInstruments`
once the SDK is up so the plugin rebinds. The instrument names use
`tenant_plugin.` rather than `tenant.` so dashboards can cleanly
distinguish the plugin's emissions from the underlying
`@suaveplan/api-tenant` library's instruments (if any are added later).