6.1 KiB
Change: enterprise-docs
- Package:
@suaveplan/docs - Status: PROPOSED
- Design: ./design.md
- Spec delta: ./specs/docs/spec.md
- Upstream:
../suaveplan/packages/universal/docs(1.0.3) - Enterprise audit:
../suaveplan/enterprise/docs.md
Why
Genesis is migrating @suaveplan/docs from the legacy packages/universal/docs/
checkout into the canonical packages/devtools/docs/docs/ location at enterprise
quality. The upstream shipped a working markdown discovery + graph + hierarchy +
search toolkit (~430 LOC of source plus tests), but the enterprise audit flagged
gaps that block production use:
- Hand-crafted
Errorpaths with no@suaveplan/errorintegration, no stable error-code registry, and nocodefield for programmatic discrimination. - No OpenTelemetry instrumentation — operators cannot measure discovery / graph-build / search latency, doc-count volume, or error rate.
- No Zod validation at the
DiscoverOptionsboundary; bad arguments fail withglob's native error message rather than a typedDocsError. - Silent failure mode in
discoverDocs: unreadable files are swallowed with a barecatch {}— there is no way for operators to observe a permission / IO error rate. - The
parseDocimplementation casts toany(node as any) to navigate the mdast tree, defeating type-safety. - No
AbortSignalpropagation throughdiscoverDocs(the only long-running async entrypoint), so callers cannot cancel a sweep of a large monorepo. - The
DocCategoryunion is closed to the upstream six-categorypackages/<tier>/layout. Genesis has the eighteen-categorypackages/<category>/<plugin>/<pkg>/layout, so the upstream derivation produces"root"for every genesis package.
The greenfield rewrite addresses every gap while preserving the upstream public
surface (discoverDocs, buildGraph, findOrphans, buildHierarchy,
parseDoc, searchDocs, DiscoverOptions, DocCategory, DocFile,
DocGraph, DocLink, DocNode, SearchResult, OrphanInfo, DocHierarchy)
so downstream consumers continue to compile against the same import paths.
What changes
- Add:
@suaveplan/docsat version0.1.0underpackages/devtools/docs/docs/with full enterprise surface — typed errors via@suaveplan/error, OTel counters + histograms, Zod-validatedDiscoverOptions,AbortSignalpropagation, typed mdast traversal via@types/mdast, eighteen-category genesisDocCategoryunion, IO-error surfacing indiscoverDocs, and per-feature subpath exports. - Add: error-code namespace
DOCS.*with eight stable codes viadefineCodes("DOCS", [...] as const):INVALID_OPTIONS,READ_FAILED,PARSE_FAILED,GLOB_FAILED,ABORTED,LINK_RESOLUTION_FAILED,HIERARCHY_CYCLE_LIMIT,SEARCH_INVALID_QUERY. - Add: OTel instruments — counters
docs_discovered_total,docs_parse_error_total,docs_io_error_total,docs_search_totaland histogramsdocs_discover_duration_ms,docs_parse_duration_ms,docs_graph_build_duration_ms,docs_search_duration_ms. - Add: subpath exports per feature module (
./discovery/discover,./parser/parse,./graph/build-graph,./graph/find-orphans,./hierarchy/build-hierarchy,./search/search,./errors/errors,./observability/observability,./types).
Impact
Affected dependents
Run bunx turbo ls --filter=...@suaveplan/docs to enumerate.
- No dependents (verified by
bunx turbo ls --filter=...@suaveplan/docs).
Future doc-site consumers (api-docs, react-docs) will adopt this package
via follow-up changes once they migrate; no work is required in this proposal.
Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
discoverDocs(options) |
✅ | ⬆️ | Now Zod-validates options; surfaces IO errors via DOCS.READ_FAILED counter; honours AbortSignal; emits docs_discover_duration_ms. |
parseDoc(absPath, relPath, raw) |
✅ | ⬆️ | Now uses typed mdast Heading/Link nodes via @types/mdast; no as any; emits docs_parse_duration_ms histogram; counter docs_parse_error_total on frontmatter failure. |
buildGraph(docs) |
✅ | ⬆️ | Same shape; emits docs_graph_build_duration_ms. Genesis category awareness in orphan filter (root-tier docs still exempt). |
findOrphans(graph) |
✅ | ✅ | Same shape; sort key unchanged. |
buildHierarchy(graph, options?) |
✅ | ⬆️ | Same shape; cycle limit now configurable via maxDepth option (default 8 preserved). |
searchDocs(docs, query, limit?) |
✅ | ⬆️ | Same shape; emits docs_search_total + docs_search_duration_ms. |
DocFile, DocLink, DocGraph, DocNode, DocHierarchy, DiscoverOptions, SearchResult, OrphanInfo |
✅ | ✅ | Re-exported from ./types. |
DocCategory union |
✅ | ⬆️ | Extended from six (upstream tiers) to the eighteen-category genesis vocabulary so genesis packages classify correctly. |
Typed errors with DOCS.* codes |
🚫 | ⬆️ | NEW — DocsError extends SuaveplanError<DocsErrorCode>; all error paths use codes; error-code registry exported. |
| OTel counters + histograms | 🚫 | ⬆️ | NEW — eight instruments wired into every public method. |
| Zod-validated options | 🚫 | ⬆️ | NEW — DiscoverOptionsSchema enforces rootDir: string, ignore: string[]?, includeApps: boolean?, signal: AbortSignal?. |
AbortSignal propagation |
🚫 | ⬆️ | NEW — discoverDocs checks signal.aborted between glob and parse, and surfaces DOCS.ABORTED. |
| Genesis 18-category awareness | 🚫 | ⬆️ | NEW — deriveCategory recognises every category in scripts/folder-reorg/assignment.yml. |
Migration
This is a 0.1.0 first landing — no prior genesis consumers. Downstream waves
that adopted the upstream surface from ../suaveplan/packages/universal/docs
should:
- Update imports from
@suaveplan/docs(path stays the same). - Treat
DocsErroras the canonical thrown type; switch onerror.codeagainstDOCS_CODES.*rather than parsingerror.message. - Adopt
AbortSignalondiscoverDocsfor cancellable scans of large monorepos.