Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
# Design — `@suaveplan/overview`
> Non-normative design notes for the enterprise-overview change. Normative
> requirements live in `./specs/overview/spec.md`.
---
## 1. What the library is
`@suaveplan/overview` is the **typed, schema-validated, graph-aware library
form of the monorepo manifest**. The data model mirrors what
`scripts/folder-reorg/generate-manifest.ts` produces ad-hoc today (and that
script's own header comment names this package as the eventual replacement).
It is a **leaf** package. Direct workspace deps:
- `@suaveplan/error` — `SuaveplanError`, `defineCodes`
- `@suaveplan/types` — for option-bundle ergonomics (we re-use `Clock` etc. only
if useful; not required by the core)
Plus catalog deps `zod`, `tslib`, `@opentelemetry/api`.
## 2. Tier model
Universal-tier **for pure data + graph operations**. The discovery surface
(`discoverPackages`) touches `node:fs` and `node:path` and is therefore
server-tier; it ships under the `./discover` sub-path export so universal
consumers (browser, edge, R3F) can `import` only the pure pieces. The package
itself stays universal at the root entry — only the `./discover` sub-path is
server-flavoured. This matches the genesis pattern used by `db-sqlite` /
`packer-browser` etc.
## 3. Data model (Zod-validated)
```ts
type Tier = "python" | "r3f" | "react" | "browser" | "server" | "universal";
interface PackageRecord {
name: string; // "@suaveplan/<short>"
short: string; // "<short>"
category: string; // top-level super-category folder
plugin: string; // mid-level plugin folder
dirName: string; // last path segment
version: string;
description: string;
tier: Tier;
workspaceDeps: string[]; // sorted, deduped @suaveplan/* names
hasBin: boolean;
hasBrowserField: boolean;
}
interface PluginSummary {
category: string;
plugin: string;
packages: number;
workspaceDeps: number; // total edges out
}
interface SuavePlanManifest {
packages: PackageRecord[];
plugins: PluginSummary[];
categories: string[];
tierCounts: Record<Tier, number>;
}
interface WorkspaceGraph {
nodes: Set<string>;
forward: Map<string, Set<string>>; // pkg → deps
reverse: Map<string, Set<string>>; // pkg → dependents
}
```
All four shapes have Zod schemas exported alongside the types.
## 4. Tier inference
Identical priority to `generate-manifest.ts`:
1. `python !== undefined` or `short.startsWith("python-")` → `python`
2. `peerDependencies` includes `@react-three/fiber` or `three` or
`short.startsWith("r3f-")` → `r3f`
3. `peerDependencies` includes `react` or `short.startsWith("react-")` →
`react`
4. `browser !== undefined` or `engines` set with neither `node` nor `bun`
keys → `browser`
5. `bin !== undefined` or `dependencies`/`devDependencies` hit a known
server-only dep (`bun:sqlite`, `pg`, `ioredis`, `better-sqlite3`,
`node:*` namespace) → `server`
6. fallback → `universal`
The hint set is exported as `SERVER_DEP_HINTS` so downstream code can extend
it via a `tierHints` option to `discoverPackages`.
## 5. Discovery semantics
`discoverPackages(options)` walks
`<root>/packages/<category>/<plugin>/<pkg>/package.json` exactly three levels
deep. Anything that fails `JSON.parse` is reported via the
`OVERVIEW.PARSE_FAILED` error path (caller decides: throw or skip). Anything
without a `package.json` is silently ignored — that matches the script
behaviour and reflects partial-migration reality on `genesis`.
The walk is **synchronous by default** (cheap on a populated monorepo) with
an optional async generator variant (`discoverPackagesIter`) that yields one
`PackageRecord` at a time and honours `AbortSignal`.
## 6. Graph utilities
- `buildGraph(records)` returns `WorkspaceGraph`. Only edges where the target
is also in `nodes` are recorded (so a missing-yet-to-migrate dep is dropped
rather than producing a phantom node — matches the script's behaviour).
- `topologicalOrder(graph)` returns packages in dep-first order using
Kahn's algorithm. On a cycle it throws `OVERVIEW.CYCLE_DETECTED` carrying
the cycle nodes.
- `detectCycles(graph)` returns `string[][]` of strongly-connected components
larger than one node (Tarjan).
- `transitiveDependencies(graph, pkg)` / `transitiveDependents(graph, pkg)`
BFS in the respective direction. Returns a sorted `string[]`.
- `leafPackages(graph)` — packages with no incoming workspace edge (no
dependents).
- `rootPackages(graph)` — packages with no outgoing workspace edge (no deps).
## 7. Roll-ups
- `byPlugin(records)` returns a sorted `PluginSummary[]`.
- `byCategory(records)` returns `Record<string, number>` (package count).
- `byTier(records)` returns `Record<Tier, PackageRecord[]>`.
## 8. Error codes
```ts
defineCodes("OVERVIEW", [
"PARSE_FAILED", // package.json failed JSON.parse
"INVALID_RECORD", // a record failed Zod validation
"CYCLE_DETECTED", // topological sort hit a cycle
"UNKNOWN_PACKAGE", // queried a package not in the graph
"DISCOVERY_ABORTED", // AbortSignal fired mid-walk
"INVALID_TIER", // schema rejected an out-of-range tier string
] as const);
```
Every code is thrown from a real call site (no dead entries — §2c).
## 9. OpenTelemetry
Three counters and one histogram, namespaced `overview.*`:
- `overview.packages_discovered_total` — counter incremented per
`discoverPackages` call by `records.length`.
- `overview.records_rejected_total{reason}` — counter (reason ∈
{`parse_failed`, `invalid_record`}).
- `overview.graph_builds_total` — counter incremented per `buildGraph`.
- `overview.discover_duration_ms` — histogram (boundaries 1, 5, 25, 100,
500, 2500) per successful `discoverPackages`.
The OTel meter is obtained via `metrics.getMeter("@suaveplan/overview",
"0.1.0")` so a no-op OTel SDK is the default — no instrumentation cost on
the cold path.
## 10. Why a sub-path for discovery
Tier purity: the package root MUST be safe to import from a universal
context (browser, R3F, edge worker). Node-only `node:fs` / `node:path`
imports live under `./discover` which `package.json` `exports` lists
distinctly. This matches the pattern used by `db-sqlite`.
## 11. Test plan
- **`errors/errors.test.ts`** — every code constructable; cause chain
preserved; `instanceof OverviewError`; code uniqueness.
- **`schemas/schemas.test.ts`** — every shape parses a valid example +
rejects each malformed shape (one negative case per field).
- **`tier/tier.test.ts`** — one case per inference rung incl. server-hint
walk and `python` early-out; `tierHints` extension.
- **`discover/discover.test.ts`** — discovers a temp-dir fixture (real
files, real `package.json`s, no mocks — rule 2); async variant honours
`AbortSignal`; invalid JSON triggers `PARSE_FAILED`; missing field triggers
`INVALID_RECORD`.
- **`graph/graph.test.ts`** — adjacency build; topo on linear + DAG; cycle
case throws + reports; transitive closure correctness on a chain; leaves +
roots on a star; missing-target edge is dropped.
- **`rollups/rollups.test.ts`** — plugin / category / tier aggregates on a
hand-crafted record array.
- **`telemetry/telemetry.test.ts`** — installs an in-memory metric reader,
observes counter + histogram values after `discoverPackages` + `buildGraph`.
Property-based tests via `fast-check` for `topologicalOrder` (random DAG →
all edges respected) and `transitiveDependencies` (closure is reflexive on
self-loops and matches multi-step BFS).
## 12. File-size discipline
The largest implementation file is expected to be `graph/graph.ts` (Tarjan
+ topo + closure) at ~180 lines. Everything else stays under 200. Test
files are budget-aware; if `graph.test.ts` pushes 500, split into
`graph.spec.basics.test.ts` + `graph.spec.cycles.test.ts`.

View File

@@ -0,0 +1,178 @@
# OpenSpec Change: enterprise-overview
- **Change ID**: enterprise-overview
- **Package**: `@suaveplan/overview`
- **Category / plugin**: `devtools/tooling`
- **Target path**: `packages/devtools/tooling/overview`
- **Status**: PROPOSED
- **Date**: 2026-05-25
- **Design**: ./design.md
- **Spec delta**: ./specs/overview/spec.md
- **Reference docs**:
- `/mnt/s/web/suaveplan/enterprise/overview.md` (enterprise contract)
- `/mnt/s/web/suaveplan/packages/universal/overview/` (upstream — documentation-only bundle)
- `scripts/folder-reorg/generate-manifest.ts` (genesis data model — the script
explicitly notes "Replaces @suaveplan/overview"; this migration restores
`overview` as the **library form** of that same data model)
- `CLAUDE.md` foundation listing: "**overview** — machine-readable monorepo
manifest with Zod schemas + graph utilities. Leaf."
---
## Summary
Migrate `@suaveplan/overview` onto genesis as a fresh, enterprise-grade
universal-tier **machine-readable monorepo manifest + graph-utilities library**.
The upstream main-branch package is a documentation bundle (≈90 ad-hoc `.md`
files plus a 27-line `postinstall.ts` that rewrites links). It carries no
runtime API, no tests, no schemas. That artefact is not enterprise-grade and
cannot be ported as-is.
The genesis form is a different package by name only: a typed library that
discovers every `packages/<category>/<plugin>/<pkg>/package.json` on disk,
parses each into a Zod-validated `PackageRecord`, exposes a typed
`SuavePlanManifest`, and provides graph utilities (forward / reverse adjacency,
topological order, cycle detection, transitive closure, leaf / root detection,
tier overlay, plugin and category roll-ups).
The same data model is currently produced ad-hoc by
`scripts/folder-reorg/generate-manifest.ts`, whose own header comment says
"Replaces @suaveplan/overview". This change re-introduces `overview` as the
**library** form of that script — single source of truth, exported as a typed
API, fully testable, with full enterprise instrumentation. The script can later
be refactored to consume the library; that refactor is out of scope for this
change.
---
## Current-state audit (genesis)
- Package directory does not exist on genesis.
- `STATUS.md` lists `@suaveplan/overview` as `–` (yet to migrate) under
`devtools/tooling`.
- `scripts/folder-reorg/assignment.yml` line 665 confirms `tooling/overview`.
- `MANIFEST.md` does not yet contain an `@suaveplan/overview` row.
- `CLAUDE.md` foundation listing already describes the intended genesis shape
(machine-readable manifest + Zod schemas + graph utilities) — this change
realises that description.
**Verified by:** `ls packages/devtools/tooling/` (no `overview/`),
`grep -n "overview" STATUS.md` (one `–` row).
---
## Parity & enhancement checklist
The upstream package has no runtime surface, so this is functionally a
**genesis-original** library aligned to the data model already encoded by
`scripts/folder-reorg/generate-manifest.ts`. Every column below has a
compensating enhancement; nothing is dropped.
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| `.md` documentation bundle | ✅ docs-only | 🚫 dropped | Genesis ships per-package `README.md` + co-located `.md`; central doc bundle is obsolete. Replaced by **machine-readable manifest** as the cross-package index. |
| `postinstall.ts` link-rewriter | ✅ | 🚫 dropped | No `dist/*.md` to rewrite on genesis. Replaced by typed API. |
| Package discovery | 🚫 | ⬆️ NEW | `discoverPackages(root)` walks `packages/<category>/<plugin>/<pkg>/package.json`. |
| Zod schemas for every type | 🚫 | ⬆️ NEW | `PackageRecordSchema`, `SuavePlanManifestSchema`, `TierSchema`, `PluginSummarySchema`. |
| Tier inference | 🚫 | ⬆️ NEW | python → r3f → react → browser → server → universal (matches `openspec/specs/monorepo-structure/spec.md`). |
| Graph utilities | 🚫 | ⬆️ NEW | forward / reverse adjacency, topo sort, cycle detection, transitive closure, leaves, roots. |
| Plugin + category roll-ups | 🚫 | ⬆️ NEW | `byPlugin()`, `byCategory()`, `byTier()`. |
| Stable error codes via `defineCodes` | 🚫 | ⬆️ NEW | 6 `OVERVIEW.*` codes — each thrown from a real call site. |
| OpenTelemetry counters + histogram | 🚫 | ⬆️ NEW | 3 counters + 1 histogram. |
| `AbortSignal` support on async I/O | 🚫 | ⬆️ NEW | `discover` accepts `signal`; aborts mid-walk. |
| 100/100/100/100 Istanbul coverage | 🚫 | ⬆️ NEW | Test gate. |
| Co-located `.md` per implementation `.ts` | 🚫 | ⬆️ NEW | §4 docs rule. |
| Universal tier (zero Node-only run-time imports in library code) | n/a | ✅ | I/O helpers are server-tier and gated behind a sub-path entry; pure data + graph code is universal. |
No 🚫 entry without compensating ⬆️ enhancement.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `SuaveplanError` base + `defineCodes` |
| `@suaveplan/types` (`workspace:^`) | shared `Clock`-style types |
| `tslib` (`catalog:build`) | runtime helpers |
| `zod` (`catalog:forms`) | schemas |
| `@opentelemetry/api` (`catalog:observability`) | counters + histogram |
Dev deps: `@suaveplan/testing` (`workspace:^`), `vitest`,
`@vitest/coverage-istanbul`, `typescript`, `vite`, `vite-plugin-dts`.
---
## Public API surface (summary)
```ts
import {
// schemas
PackageRecordSchema,
SuavePlanManifestSchema,
TierSchema,
// discovery (server sub-path: "@suaveplan/overview/discover")
discoverPackages,
// graph
buildGraph,
topologicalOrder,
detectCycles,
transitiveDependencies,
transitiveDependents,
leafPackages,
rootPackages,
// roll-ups
byPlugin,
byCategory,
byTier,
// errors
OVERVIEW_CODES,
OverviewError,
} from "@suaveplan/overview";
// Types
import type {
PackageRecord,
SuavePlanManifest,
Tier,
PluginSummary,
WorkspaceGraph,
} from "@suaveplan/overview";
```
---
## File layout
```text
packages/devtools/tooling/overview/
package.json, tsconfig.lib.json, vite.config.ts, vitest.config.ts, README.md
src/
index.ts
types/types.ts, types.md
errors/errors.{ts,md,test.ts}
schemas/schemas.{ts,md,test.ts}
tier/tier.{ts,md,test.ts}
discover/discover.{ts,md,test.ts}
graph/graph.{ts,md,test.ts}
rollups/rollups.{ts,md,test.ts}
telemetry/telemetry.{ts,md,test.ts}
tests/setup/polyfills.ts
```
---
## Impact
### Affected dependents
- No `@suaveplan/*` consumer currently imports `@suaveplan/overview` on
genesis. The library is consumable by `scripts/folder-reorg/generate-manifest.ts`
in a future cleanup change (out of scope here).
- Downstream tools (CLI dashboards, dependency-graph visualisers, ratings
dashboards) can adopt the typed API instead of re-implementing manifest
discovery.
**Breaking changes**: none (new package on genesis; upstream was docs-only
with no runtime API).

View File

@@ -0,0 +1,246 @@
<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: overview (overview)
**Package**: `@suaveplan/overview`
**Status**: PROPOSED
> Every requirement below carries a `**Verified by:**` line at authoring time.
## ADDED Requirements
### Requirement: Stable error registry
The package SHALL expose `OVERVIEW_CODES` registered via `defineCodes("OVERVIEW", [...])`
and a `OverviewError` class extending `@suaveplan/error`'s `SuaveplanError`. The
registry SHALL contain exactly six entries: `PARSE_FAILED`, `INVALID_RECORD`,
`CYCLE_DETECTED`, `UNKNOWN_PACKAGE`, `DISCOVERY_ABORTED`, `INVALID_TIER`. Each
code MUST be reachable from a real call site exercised by tests; no dead entries.
#### Scenario: error code uniqueness
- **WHEN** the test enumerates `Object.values(OVERVIEW_CODES)`
- **THEN** every value is a unique string in the form `"OVERVIEW.<NAME>"` and
`new OverviewError(code, "msg")` produces an instance whose `code` field equals
the input
#### Scenario: every code is thrown somewhere
- **WHEN** the test asserts each code appears as a `throw new OverviewError(...)`
argument in at least one `src/**/*.ts` file
- **THEN** the assertion passes — `PARSE_FAILED` from `discover`, `INVALID_RECORD`
from `discover`/`schemas`, `CYCLE_DETECTED` from `graph`, `UNKNOWN_PACKAGE` from
`graph`, `DISCOVERY_ABORTED` from `discover`, `INVALID_TIER` from `schemas`
**Verified by:** `src/errors/errors.test.ts::"every OVERVIEW code is unique"` AND `src/errors/errors.test.ts::"every code has a real call site in src/"`
---
### Requirement: Zod-validated data model
The package SHALL export Zod schemas `TierSchema`, `PackageRecordSchema`,
`PluginSummarySchema`, and `SuavePlanManifestSchema`, each paired with an
inferred TypeScript type. Schemas SHALL reject malformed inputs at the package
boundary and `INVALID_RECORD` SHALL be thrown when a discovered `package.json`
fails to parse against `PackageRecordSchema`.
#### Scenario: valid PackageRecord parses
- **WHEN** `PackageRecordSchema.safeParse({ name: "@suaveplan/x", short: "x",
category: "foundation", plugin: "core", dirName: "x", version: "0.1.0",
description: "d", tier: "universal", workspaceDeps: [], hasBin: false,
hasBrowserField: false })` runs
- **THEN** `success === true`
#### Scenario: malformed tier rejected
- **WHEN** `TierSchema.safeParse("rust")` runs
- **THEN** `success === false`
**Verified by:** `src/schemas/schemas.test.ts::"TierSchema accepts every tier"` AND `src/schemas/schemas.test.ts::"PackageRecordSchema rejects bad input per field"`
---
### Requirement: Tier inference
The package SHALL provide `inferTier(short, pkgJson, hints?)` that returns a
`Tier` using the priority order: python → r3f → react → browser → server →
universal. The hint set for the server-tier walk SHALL be exported as
`SERVER_DEP_HINTS` and SHALL be extensible per call via an optional
`hints: Set<string>` parameter.
#### Scenario: python wins
- **WHEN** `inferTier("python-foo", { python: {} })` runs
- **THEN** the return value is `"python"`
#### Scenario: server hint matches a Node-only dep
- **WHEN** `inferTier("x", { dependencies: { "node:fs": "*" } })` runs
- **THEN** the return value is `"server"`
#### Scenario: universal fallback
- **WHEN** `inferTier("x", {})` runs
- **THEN** the return value is `"universal"`
**Verified by:** `src/tier/tier.test.ts::"inferTier prioritises python > r3f > react > browser > server > universal"` AND `src/tier/tier.test.ts::"inferTier honours extension hints"`
---
### Requirement: Filesystem discovery (server sub-path)
The package SHALL expose `discoverPackages(options)` from the `./discover`
sub-path export. The function SHALL walk
`<root>/packages/<category>/<plugin>/<pkg>/package.json` exactly three folder
levels deep, parse each file as JSON, validate against `PackageRecordSchema`,
and return `SuavePlanManifest`. Invalid JSON SHALL produce `OVERVIEW.PARSE_FAILED`;
validation failure SHALL produce `OVERVIEW.INVALID_RECORD` (default behaviour:
throw; opt-in `onError: "skip"` collects errors into a returned array).
#### Scenario: temp-dir fixture discovers two packages
- **WHEN** the test creates a temp `packages/foundation/core/{a,b}/package.json`
fixture and calls `discoverPackages({ root: tmp })`
- **THEN** the returned manifest contains two records sorted by name
#### Scenario: invalid JSON throws PARSE_FAILED
- **WHEN** a fixture `package.json` is unparseable and `onError: "throw"`
- **THEN** an `OverviewError` with `code === "OVERVIEW.PARSE_FAILED"` is thrown
**Verified by:** `src/discover/discover.test.ts::"discovers a 3-level fixture"` AND `src/discover/discover.test.ts::"throws PARSE_FAILED on invalid JSON"` AND `src/discover/discover.test.ts::"throws INVALID_RECORD when fields missing"`
---
### Requirement: AbortSignal-aware async discovery
The package SHALL export `discoverPackagesIter(options)` returning an
`AsyncGenerator<PackageRecord>` that honours `options.signal`. On abort the
generator SHALL throw `OVERVIEW.DISCOVERY_ABORTED`.
#### Scenario: abort mid-walk
- **WHEN** a controller is aborted between the first and second yielded record
- **THEN** the second `.next()` rejects with `OverviewError` whose code is
`OVERVIEW.DISCOVERY_ABORTED`
**Verified by:** `src/discover/discover.test.ts::"discoverPackagesIter honours AbortSignal"`
---
### Requirement: Workspace graph utilities
The package SHALL export `buildGraph(records)`, `topologicalOrder(graph)`,
`detectCycles(graph)`, `transitiveDependencies(graph, pkg)`,
`transitiveDependents(graph, pkg)`, `leafPackages(graph)`, and
`rootPackages(graph)`. Graph edges SHALL only be recorded when both endpoints
are nodes (orphan dep names are dropped). Topological order SHALL throw
`OVERVIEW.CYCLE_DETECTED` carrying the offending cycle. Queries against
unknown packages SHALL throw `OVERVIEW.UNKNOWN_PACKAGE`.
#### Scenario: topo on a linear chain
- **WHEN** `topologicalOrder` runs over `a → b → c`
- **THEN** the result is `["c", "b", "a"]` (deps first)
#### Scenario: cycle detected
- **WHEN** `topologicalOrder` runs over `a → b → a`
- **THEN** an `OverviewError` with `code === "OVERVIEW.CYCLE_DETECTED"` is thrown
whose `context.cycle` contains both `a` and `b`
#### Scenario: transitive closure
- **WHEN** `transitiveDependencies(graph, "a")` runs over `a → b → c, b → d`
- **THEN** the result is `["b", "c", "d"]` sorted
#### Scenario: unknown package query
- **WHEN** `transitiveDependencies(graph, "missing")` runs
- **THEN** an `OverviewError` with `code === "OVERVIEW.UNKNOWN_PACKAGE"` is thrown
**Verified by:** `src/graph/graph.test.ts::"topologicalOrder respects dependency direction"` AND `src/graph/graph.test.ts::"topologicalOrder throws CYCLE_DETECTED on a cycle"` AND `src/graph/graph.test.ts::"transitiveDependencies BFS closure"` AND `src/graph/graph.test.ts::"transitiveDependencies throws UNKNOWN_PACKAGE"` AND `src/graph/graph.test.ts::"leaves and roots on a star"`
---
### Requirement: Roll-up aggregates
The package SHALL export `byPlugin(records)`, `byCategory(records)`, and
`byTier(records)`. `byPlugin` SHALL return `PluginSummary[]` sorted by
`"<category>/<plugin>"`. `byCategory` SHALL return `Record<string, number>`
of package counts. `byTier` SHALL return `Record<Tier, PackageRecord[]>` for
all six tiers (empty arrays when absent).
#### Scenario: byPlugin aggregates counts and dep totals
- **WHEN** `byPlugin` runs over three records across two `(category, plugin)`
pairs with workspace-dep counts `[2, 3, 1]` and the two pairs have `[2, 1]`
records respectively
- **THEN** the summary rows carry the expected `packages` and `workspaceDeps`
totals
#### Scenario: byTier covers all tiers
- **WHEN** `byTier` runs over an empty list
- **THEN** the returned record has every tier key with an empty array value
**Verified by:** `src/rollups/rollups.test.ts::"byPlugin aggregates packages + workspace deps"` AND `src/rollups/rollups.test.ts::"byCategory counts packages"` AND `src/rollups/rollups.test.ts::"byTier covers every Tier key"`
---
### Requirement: OpenTelemetry instrumentation
The package SHALL emit three counters and one histogram via
`metrics.getMeter("@suaveplan/overview", "0.1.0")`:
`overview.packages_discovered_total`,
`overview.records_rejected_total{reason}`, `overview.graph_builds_total`, and
`overview.discover_duration_ms`. Counters and histograms SHALL increment / record
during the normal API paths.
#### Scenario: counters move on discovery
- **WHEN** an in-memory metric reader is installed and `discoverPackages` runs
against a fixture
- **THEN** `overview.packages_discovered_total` increases by `records.length`
and `overview.discover_duration_ms` records one observation
**Verified by:** `src/telemetry/telemetry.test.ts::"discoverPackages emits counter + histogram"` AND `src/telemetry/telemetry.test.ts::"buildGraph emits graph_builds_total"`
---
### Requirement: Tier purity at the root entry
The package root entry SHALL NOT import `node:*` modules. Node-only behaviour
SHALL live exclusively under the `./discover` sub-path export so universal-tier
consumers (browser, R3F, edge) can import the root safely.
#### Scenario: root barrel has no node: imports
- **WHEN** the test parses `src/index.ts` and every transitive import not under
`src/discover/`
- **THEN** none of the resolved files contain `from "node:` or `require("node:`
literal strings
**Verified by:** `src/discover/discover.test.ts::"root barrel imports no node:* modules"`
---
### Requirement: Co-located docs and 100% coverage
Every non-barrel, non-test, non-types `.ts` file under `src/` SHALL have a
sibling `.md` documentation file matching the required-section template. The
package SHALL meet 100% statement, branch, function, and line coverage under
Istanbul.
#### Scenario: docs:check passes
- **WHEN** `bun run docs:check --filter=@suaveplan/overview` runs
- **THEN** the exit code is 0
#### Scenario: coverage gate
- **WHEN** `bunx turbo test:coverage --filter=@suaveplan/overview` runs
- **THEN** the Istanbul report shows 100/100/100/100
**Verified by:** `bunx turbo test:coverage --filter=@suaveplan/overview` AND `bun run docs:check --filter=@suaveplan/overview`

View File

@@ -0,0 +1,83 @@
# Tasks — enterprise-overview
Numbered checklist of the discrete units of work to ship `@suaveplan/overview`.
## 1. Skeleton
- [x] Create `packages/devtools/tooling/overview/` with `package.json`,
`tsconfig.lib.json`, `vite.config.ts`, `vitest.config.ts`,
`README.md`, and `tests/setup/polyfills.ts`.
- [x] Wire `package.json` exports for `.` and `./discover`.
## 2. Types
- [x] `src/types/types.ts` — `Tier`, `PackageRecord`, `PluginSummary`,
`SuavePlanManifest`, `WorkspaceGraph`. Sibling `types.md`.
## 3. Errors
- [x] `src/errors/errors.ts` — `defineCodes("OVERVIEW", [...])`, `OverviewError`
subclass, code uniqueness test, sibling `.md`.
## 4. Schemas
- [x] `src/schemas/schemas.ts` — Zod schemas for `Tier`, `PackageRecord`,
`PluginSummary`, `SuavePlanManifest`. Sibling `.md` and tests.
## 5. Tier inference
- [x] `src/tier/tier.ts` — `inferTier(short, pkgJson, hints?)`, exported
`SERVER_DEP_HINTS`. Sibling `.md` and tests.
## 6. Discovery (server sub-path)
- [x] `src/discover/discover.ts` — `discoverPackages(options)`, async
`discoverPackagesIter` with `AbortSignal`. Real-fs test fixture under
`tests/setup/fixtures/`. Sibling `.md`.
## 7. Graph utilities
- [x] `src/graph/graph.ts` — `buildGraph`, `topologicalOrder`, `detectCycles`,
`transitiveDependencies`, `transitiveDependents`, `leafPackages`,
`rootPackages`. Sibling `.md` and tests including `fast-check`
property-based cases.
## 8. Roll-ups
- [x] `src/rollups/rollups.ts` — `byPlugin`, `byCategory`, `byTier`. Sibling
`.md` and tests.
## 9. Telemetry
- [x] `src/telemetry/telemetry.ts` — meter init, counter + histogram exports.
Sibling `.md` and tests using in-memory metric reader.
## 10. Root barrel
- [x] `src/index.ts` — explicit named re-exports (no `export *`). README at
package root documenting the API surface.
## 11. Gate
- [x] `bunx turbo lint typecheck test build --filter=@suaveplan/overview`
green.
- [x] `bunx turbo test:coverage --filter=@suaveplan/overview` reports
100/100/100/100.
## 12. Manifest refresh
- [x] Run `bun scripts/folder-reorg/generate-manifest.ts` so `MANIFEST.md`
lists the new package.
## 13. STATUS flip
- [x] In `STATUS.md`, change the `@suaveplan/overview` row from `–` to `✅`
and update its info column to reflect the migrated surface.
- [x] Update the Counts table (+1 migrated, -1 pending).
## 14. Fold + archive
- [x] Fold `openspec/changes/enterprise-overview/specs/overview/spec.md` into
`openspec/specs/overview/spec.md` (canonical).
- [x] Move `openspec/changes/enterprise-overview/` to
`openspec/archive/2026-05-25-enterprise-overview/`.