158 lines
12 KiB
Markdown
158 lines
12 KiB
Markdown
# Suaveplan Genesis — Project Conventions
|
|
|
|
Authoritative project-wide context for all OpenSpec changes on the `genesis` branch. Every proposal inherits these rules.
|
|
|
|
## Mission
|
|
|
|
Suaveplan is a monorepo of composable `@suaveplan/*` packages. The `genesis` branch is a bottom-up rebuild: every package lands fresh at enterprise quality, starting from the leaves. Designs are informed by the matching `enterprise/*.md` specification in the `main` worktree (`/mnt/s/web/suaveplan/enterprise/`). Packages start at version `0.1.0`; the Verdaccio private registry is wiped and repopulated from genesis output.
|
|
|
|
No package on genesis is "enterprise-ready" until its acceptance criteria (coverage, docs, structured errors, Zod schemas, observability, property tests, benchmarks, security review, full export surface) are all green.
|
|
|
|
## Stack
|
|
|
|
| Area | Technology |
|
|
|------|------------|
|
|
| Runtime | Bun ≥ 1.3.0 (TypeScript native, ESM-first) |
|
|
| Monorepo | Turborepo + Bun workspaces (`<category>/<domain>/<pkg>`), catalogs, overrides |
|
|
| Registry | Verdaccio at `https://npmjs.fq.io/` (auth via `NPM_TOKEN` env var) |
|
|
| Lint/Format | Biome (strict base; no per-package overrides unless justified) |
|
|
| Unit/Integration Tests | Vitest (istanbul coverage) |
|
|
| E2E Tests | Playwright |
|
|
| Bundling | Vite, tsup, `Bun.build` — **never `tsc` directly** |
|
|
| Property tests | fast-check |
|
|
| Benchmarks | mitata |
|
|
| Runtime validation | Zod (external catalog dep, not via `@suaveplan/schema-registry`) |
|
|
| Observability | `@opentelemetry/api` (external) until `@suaveplan/opentelemetry` ships |
|
|
|
|
## Package taxonomy
|
|
|
|
Genesis starts empty. Packages land under `packages/<category>/<plugin>/<name>`, where `<category>` is one of 18 super-categories (foundation, persistence, networking, communication, api-stack, identity, security-stack, observability, media, ui, threejs, localization, geospatial, money, commerce, testkit, devtools, gaming) and `<plugin>` is a domain folder defined in [`FOLDERS.md`](./FOLDERS.md). Tier (universal / browser / react / r3f / server / python) is inferred per-package from `package.json` — it is never encoded in the directory path.
|
|
|
|
Packages live at `packages/<category>/<plugin>/<pkg>` (e.g. `packages/security-stack/crypto/crypto`, `packages/foundation/core/error`). Workspace glob: `packages/*/*/*`. Category → plugin → package map lives in `scripts/folder-reorg/assignment.yml` and is summarised in `MANIFEST.md` at the repo root. Run `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md` after any package add, remove, or category move.
|
|
|
|
## Dependency-layer order
|
|
|
|
Build packages in dependency-order waves. A package cannot land until every `@suaveplan/*` workspace dep it needs is already enterprise on genesis:
|
|
|
|
1. **Layer 0** — testing-infrastructure packages (`@suaveplan/testing`, `testing-dom`, `testing-e2e`). These are forbidden from depending on ANY `@suaveplan/*` package — see "Non-negotiable rules" below.
|
|
2. **Layer 1** — true leaves with no workspace deps (`error`, `datetime`, candidate `opentelemetry` adapter).
|
|
3. **Layer 2+** — packages that depend on Layer 1 (`schema-registry`, `utils`, etc.).
|
|
|
|
## Non-negotiable rules
|
|
|
|
1. **Never run `tsc` directly.** Use Vite/tsup via `bunx turbo build`. Bun runs `.ts` natively.
|
|
2. **No mocks.** Real services only. `vi.mock` is unreliable in Bun ESM — use dependency injection. No `vi.mock` / `jest.mock` in production tests.
|
|
3. **Bun `overrides` with exact versions.** Catalogs for external deps (`catalog:<key>`), `workspace:^` for internal. **Never use bare version strings** (e.g. `"^1.2.3"`) in `package.json` — always reference a catalog entry. If a catalog key does not exist for a dep, add it to the root `package.json` `catalog` block first. Note: some Suaveplan skills say `workspace:*` — genesis uses `workspace:^` exclusively.
|
|
4. **Never re-export external deps** for convenience — import directly from source.
|
|
5. **Never auto-commit or push** without user approval. Never `--no-verify`.
|
|
6. **Always use absolute paths** in tool calls. Read files before editing.
|
|
7. **No stubs, no TODOs, no placeholder implementations** in shipped code. Enterprise-grade only.
|
|
8. **Professional honesty** — no marketing language, no fabricated metrics.
|
|
9. **Testing-infrastructure packages** (`@suaveplan/testing`, `testing-dom`, `testing-e2e`) MUST NOT depend on any `@suaveplan/*` workspace package. External catalog deps only. Circular-use-of-testing otherwise.
|
|
10. **Preserve the full public surface during rewrites.** Trimming is allowed only when code is duplicated elsewhere in-repo or can be replaced by an existing `@suaveplan/*` library. Never trim on "probably unused" grounds.
|
|
11. **Subpath exports per feature module.** Every feature directory under `src/` must have its own entry in the `exports` map in `package.json` (e.g. `"./retry/retry"`, `"./circuit-breaker/circuit-breaker"`). A single `"."` barrel export is not sufficient — tree-shaking requires granular subpaths.
|
|
12. **`@vitest/coverage-istanbul` must be in `devDependencies`.** Use `catalog:testing` or equivalent. The `provider: 'istanbul'` setting silently falls back to v8 if the package is missing.
|
|
13. **Clean workspace on task completion.** Remove any scratch files, temporary outputs, or debugging artifacts before declaring a task done.
|
|
|
|
## Pre-publish gate (non-negotiable)
|
|
|
|
Before any `bun scripts/publish.ts --package @suaveplan/<pkg>`:
|
|
|
|
- `bunx turbo lint typecheck test --filter=@suaveplan/<pkg>` MUST be green.
|
|
- `bunx turbo test:coverage --filter=@suaveplan/<pkg>` MUST meet the coverage threshold for the package layer (see Quality gates below).
|
|
- A full-package `turbo test` run is required — a single-file `vitest run` is not a substitute.
|
|
|
|
Never publish on red.
|
|
|
|
## Quality gates (per package)
|
|
|
|
| Gate | Threshold |
|
|
|------|-----------|
|
|
| Test coverage — every package, no exceptions | **100%** statement + branch + function + line (istanbul). No "foundation only" carve-out, no degraded-situation floor. Pre-publish gate hard-fails below 100%. |
|
|
| Docs coverage | ≥ 90% (every public export has a sibling `.md`) |
|
|
| Code file size | ~250 lines soft / 300 lines hard |
|
|
| Test file size | 500 lines max |
|
|
| Test extension | `.test.ts` (Vitest) / `.spec.ts` (Playwright E2E) |
|
|
| `it()` / `test()` timeout | `{ timeout: 5000 }` sync, 30000 async |
|
|
| Vitest coverage provider | `istanbul` — requires `@vitest/coverage-istanbul` in `devDependencies` |
|
|
| React component | Every component has `.stories.tsx` (default + playground + variants) |
|
|
| Public types | Modeled by Zod schemas exported from `*.schemas.ts` |
|
|
| Error shape | Extends a structured error class with `{ code, cause, context }` |
|
|
| Subpath exports | One `exports` entry per feature module for tree-shaking |
|
|
| `sideEffects` | `false` (or explicit array); entry points must not import with side effects |
|
|
|
|
## Package enterprise checklist
|
|
|
|
Every package is "enterprise-done" only when:
|
|
|
|
- [ ] `README.md` exists at the package root (not inside `src/`) — one-paragraph description, install, quick-start, **Modules** section linking to every co-located `.md` in `src/`
|
|
- [ ] Every `.ts` / `.tsx` implementation file has a sibling `.md` (≥200 words, simple + advanced examples, API reference, implementation notes) — excludes `.test.ts`, `.spec.ts`, `.types.ts` inside feature dirs, `.stories.tsx`, barrel `index.ts`, `constants/index.ts`
|
|
- [ ] Every public function has Zod input/output schemas in a sibling `*.schemas.ts`
|
|
- [ ] Every thrown error extends the package's structured error class with a stable `UTILS.<DOMAIN>.<REASON>`-style code (or equivalent namespace) and `{ cause, context }` fields
|
|
- [ ] Every function reading time / randomness / iterating accepts an optional `{ clock?, rng?, signal? }` options parameter; zero-config defaults preserved
|
|
- [ ] `AbortSignal` checks on every iterative helper at bounded intervals (≤ 256 items or ≤ 1 KB)
|
|
- [ ] OTEL instrumentation via `@opentelemetry/api` — counters, histograms, spans on public entrypoints (no-op when no exporter registered)
|
|
- [ ] fast-check property tests for pure functions covering round-trip, idempotency, associativity, boundary invariants
|
|
- [ ] mitata benchmarks with baseline + CI regression gate (>10% fails)
|
|
- [ ] Full public surface preserved relative to the design spec
|
|
- [ ] Zero `any`, `ts-ignore`, `ts-expect-error`, `TODO`, `FIXME`, `@deprecated`, `.skip`, `.only` in `src/`
|
|
- [ ] `sideEffects: false` holds; entry point imports verified to have no side effects; tree-shake test included
|
|
- [ ] Subpath exports: one `exports` entry per feature module in `package.json`
|
|
- [ ] `@vitest/coverage-istanbul` in `devDependencies` (catalog ref, not bare version)
|
|
- [ ] React version conflict (if browser/react package): verify single React version with `find . -path "*/node_modules/react/package.json"` — use exact overrides if multiple found
|
|
- [ ] Workspace clean: no scratch files, temp outputs, or debug artifacts remain
|
|
- [ ] OpenSpec change validates and is archived to `openspec/archive/<yyyy-mm-dd>-<change-id>/`
|
|
|
|
## Repo ↔ enterprise spec mapping
|
|
|
|
Every enterprise-level package rewrite starts by:
|
|
|
|
1. Reading the matching `enterprise/<package>.md` on the main branch (`/mnt/s/web/suaveplan/enterprise/<pkg>.md`).
|
|
2. Reading the current implementation on the main branch for shape-preservation (export inventory).
|
|
3. Creating `openspec/changes/enterprise-<pkg>/` with `proposal.md`, `design.md`, `specs/<capability>/spec.md`, and `tasks.md` — **adapting** each enterprise-doc clause to the constraints above (especially rule #9: no `@suaveplan/*` workspace deps in testing-infrastructure packages).
|
|
|
|
## Vitest / WSL2 quirks
|
|
|
|
- Use `createTestConfig()` from `@suaveplan/testing/config` once `@suaveplan/testing` lands.
|
|
- **Use `forks` pool.** `vmThreads` and `threads` both fail in Bun on WSL2.
|
|
- **`fileParallelism: false`** required for large browser test suites.
|
|
- SurrealDB connection errors use `'ConnectionRefused'` (not `'ECONNREFUSED'`).
|
|
|
|
## Package lifecycle
|
|
|
|
- **New package:** land via an `enterprise-<pkg>` OpenSpec change. Package starts at version `0.1.0`.
|
|
- **Edit:** no version bump during genesis; version stays `0.1.0` until graduation.
|
|
- **Publish:** `bun scripts/publish.ts --package @suaveplan/<pkg>` after pre-publish gate passes.
|
|
- **Wipe + republish:** Verdaccio is wiped once genesis is sufficiently complete; republish happens as part of the cutover.
|
|
|
|
## Commonly-used commands
|
|
|
|
```bash
|
|
# Single package
|
|
bunx turbo test --filter=@suaveplan/<pkg>
|
|
bunx turbo test:coverage --filter=@suaveplan/<pkg>
|
|
bunx turbo lint typecheck test --filter=@suaveplan/<pkg> # pre-publish gate
|
|
|
|
# Workspace-wide
|
|
bunx turbo lint typecheck
|
|
bun run gate # all packages pre-publish gate
|
|
|
|
# Turborepo advanced filtering
|
|
bunx turbo test --filter=@suaveplan/<pkg>... # pkg + everything it depends on
|
|
bunx turbo test --filter=...@suaveplan/<pkg> # pkg + everything that depends on it
|
|
bunx turbo test --filter=...[main] # packages changed since main branch
|
|
bunx turbo test --filter=...[HEAD^1] # packages changed in last commit
|
|
bunx turbo test --filter=@suaveplan/{pkg-a,pkg-b} # multiple packages (OR)
|
|
bunx turbo test --filter=!@suaveplan/<pkg> # exclude one package
|
|
|
|
# Publish
|
|
bun scripts/publish.ts --package @suaveplan/<pkg> # publish one package
|
|
|
|
# Dependency management — nuclear clean install (use after overrides changes)
|
|
rm -rf node_modules bun.lockb && find . -type d -name "node_modules" -exec rm -rf {} + && bun install --force
|
|
|
|
# Profiling (Bun ≥ 1.3.7 — outputs Markdown for LLM analysis)
|
|
bun --cpu-prof-md run <script>
|
|
bun --heap-prof-md run <script>
|
|
```
|