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,81 @@
# telemetry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Exposes the OpenTelemetry instrument set published by
`@suaveplan/email-templates`. Every public render or registry mutation
emits a counter (and where useful, a duration histogram) so operators can
build dashboards without instrumenting consumers themselves.
The instrument set is constructed lazily on first access — importing this
module does NOT create a meter or instruments, satisfying the
"side-effects: false" contract in `package.json`. Once constructed, the
set is cached and the same object reference is returned forever (the
metric exporter receives stable instrument identity, which is required
for cumulative-temporality counters).
## Features
- Four instruments: `render_total` (Counter), `render_duration_ms`
(Histogram, unit `ms`), `registry_register_total` (Counter),
`validation_failure_total` (Counter).
- Stable meter name: `@suaveplan/email-templates`.
- `resetEmailTemplatesInstrumentsCacheForTest()` helper to drop the cache
between test runs that swap the global `MeterProvider`.
## Usage: Basic
```ts
import { getEmailTemplatesInstruments } from "@suaveplan/email-templates/otel";
const instruments = getEmailTemplatesInstruments();
instruments.renderCounter.add(1, { template: "welcome", outcome: "ok" });
```
## Usage: Advanced
Wire a real metric exporter in test setup and assert the recorded series
on every render call (the package uses this pattern internally):
```ts
import {
AggregationTemporality,
InMemoryMetricExporter,
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";
const exporter = new InMemoryMetricExporter(AggregationTemporality.DELTA);
const reader = new PeriodicExportingMetricReader({ exporter });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
// ... drive the renderer ...
await reader.forceFlush();
const series = exporter.getMetrics();
// assert series contains email_templates.render_total ...
```
## API Reference
| Symbol | Kind | Description |
| -------------------------------------------- | -------- | -------------------------------------------- |
| `getEmailTemplatesInstruments()` | function | Returns the cached `EmailTemplatesInstruments`. |
| `resetEmailTemplatesInstrumentsCacheForTest()` | function | Drops the module-local cache — test-only. |
| `EmailTemplatesInstruments` | type | The shape of the instrument set. |
## Implementation Notes
The accessor must remain idempotent. Repeated calls return the same
object reference; the test corpus asserts that fact because cumulative
counters lose their backing storage if a meter is re-created mid-flight.
The module never reads `process.env`, `globalThis.window`, or any
DOM-resident global — it is universal (`engines.bun`, `engines.node`,
browser) without conditional code paths.