27 KiB
Suaveplan Monorepo — Genesis
Bottom-up rebuild at enterprise quality. Branch genesis starts empty; packages land in dependency-order waves at 0.1.0 until graduation to 1.0.0.
Main branch (/mnt/s/web/suaveplan) is reference-only for design intent (enterprise/*.md) and historical audit data. Do not pull code from main into genesis — every package is rewritten fresh.
Change workflow
All non-trivial changes go through OpenSpec. Before coding:
- Read
openspec/project.mdandopenspec/AGENTS.md. - Create
openspec/changes/<change-id>/withproposal.md,tasks.md, and spec deltas underspecs/<capability>/spec.md(## ADDED/## MODIFIED/## REMOVED Requirements). - On ship: fold the delta into
openspec/specs/<capability>/spec.mdand move the folder toopenspec/archive/<yyyy-mm-dd>-<change-id>/.
Stack
- Turborepo + Bun monorepo at
/mnt/s/web/genesis - Biome (lint/format), Vitest (tests), Playwright (E2E), TypeScript
- Use
bunx turbofor turbo commands - Private registry: Verdaccio at
https://npmjs.fq.io/(auth viaNPM_TOKEN)
Packages
Layout (packages/<category>/<plugin>/<pkg>/)
Domain-first 3-level layout: every package lives at packages/<category>/<plugin>/<pkg>/ where <category> is one of the 18 canonical super-categories — foundation, persistence, networking, communication, api-stack, identity, security-stack, observability, media, ui, threejs, localization, geospatial, money, commerce, testkit, devtools, gaming — and <plugin> matches a plugin in suaveplan-skills. Tier (universal / browser / react / r3f / server / python) is per-package via package.json ("browser" field, peer deps, engines), not encoded in the path. Full category → plugin → package map in scripts/folder-reorg/assignment.yml; summarised in MANIFEST.md at repo root. The super-category vocabulary is closed — adding/removing a category requires an OpenSpec change.
Add new packages, then run bun scripts/folder-reorg/generate-manifest.ts to refresh MANIFEST.md (dep graph auto-derived from workspace: ranges).
Note: Detailed package descriptions live in each package's
README.mdand co-located.mdfiles. This file describes foundational packages widely depended on; everything else is listed by name only — seeMANIFEST.mdand the package sources for details.
Foundation (zero or near-zero deps, widely consumed)
- types — types-only foundation:
Clock,IdGenerator,Rng,MessageResolver,EventBusLike,LoggerLike,StorageLike,DatabaseLike,HashLike,TimersLike, shared option bundles + cross-package crypto contract (Authority,KeySlotPublic/Private,SlotId,DomainTag,AuthorityVerifier,AeadOps,AeadAlgorithm). Zero runtime, zero deps. Permitted as testing-infra dev dep (rule 8 exception). - error —
SuaveplanErrorbase, stable code registry viadefineCodes, cause-chain traversal, Zod-validated wire format, redaction, OTel span-event adapter, i18n resolver hook. Deps:tslib,zod. - events — typed event bus: pub/sub FIFO, interceptors, bounded-queue backpressure, idempotent listeners. Deps:
error,types. - env — type-safe env loading with schema validation, dotenv + object loaders,
maskSensitive,createEnv. Deps:error,types,zod. - config — layered config (5 layers: defaults/file/object/env/CLI), Zod validation, dot-path get/has, hot reload, EventBus watch. Deps:
error,types,events,env,zod. - logger — structured logger: level filtering, OTel trace enrichment, sampling, redaction, pluggable sinks. Deps:
error,types. - opentelemetry — OTel SDK utilities:
NoopSdk,SdkFactory, W3C propagation, span/metrics utilities, resource builder. - typescript-config — shared TSConfig presets. No runtime.
- overview — machine-readable monorepo manifest with Zod schemas + graph utilities. Leaf.
- api-schemas — shared Zod request/response schemas. Leaf.
Testing infrastructure (no @suaveplan/* runtime deps; rule 8)
- testing — runner-agnostic utilities (FakeClock, Factory, FixtureManager, MemoryStore, builders). Owns the
./runnerconditional-export wrapper resolving tovitest(default) orbun:test(underbuncondition) — see rule 11. - testing-dom, testing-e2e, testing-integration — DOM helpers + dual-runner adapters; Playwright config factory;
ServiceFixture/TestEnvironment/HealthPoller. - testing-integration-{surrealdb, redis, postgres, mailpit, typesense, garage-s3, step-ca} — real-service fixtures via testcontainers; each provides env-bridge + health probe + injectable container/exec/fetch factories.
Crypto family
Foundation (widely consumed):
- crypto-utils — hex/base64/base58, byte helpers, constant-time equality, random bytes, zeroize, Merkle, KAT/fuzz harnesses,
PrimitiveIdregistry. - crypto-hash — sha256/384/512, hmac, hkdf, pbkdf2, argon2id. Noble + native, build-time selection.
- crypto-curve — secp256k1, ed25519, x25519, p256, p384, p521. Noble + native.
- crypto-cipher — aes-256-gcm, chacha20-poly1305, xchacha20-poly1305. Nonce caller-supplied.
- crypto — multi-algorithm façade over the four primitive packages. Engine-pluggable.
- crypto-rsa — RFC 8017 PKCS#1 v2.2: PKCS1v15+PSS sign/verify, OAEP, all 8 key formats, FIPS 186-5 keygen, RFC 7638 thumbprints, blinding-by-default, pluggable engine, HSM bridge. Gates
x509/jws/webauthn.
Specialty: crypto-core, crypto-sodium, crypto-browser, crypto-cli (keychain binary), crypto-bin (suaveplan-hash-password), crypto-vault (BIP39 + Argon2id + 2SKD + HKDF + SRP-6a + SecureBuffer; gates vault).
Drive (file VFS)
- drive — modular file-VFS core. Consumes
AbstractStoragedirectly via structuralDriveStorageview. Plugin slot + middleware chain. Template hydration (hydrateFrom/getKeyStatus/presence). 11DRIVE_*codes. - drive-template — server-signed dehydrated descriptor for lazy hydration. 8-step validation pipeline, Ed25519 over canonical bytes,
TemplateNonceLru, CDN URL builder, upload-token signing, retroactive key-grant validation. 10DTP_*codes. - drive-mesh-protocol — wire protocol for chunk discovery/request/delivery.
ChunkRequestunion (whole/specific/bitset),GenerationTracker,AdvertiseThrottle,TrustMapwith sample-verify. 10DMP_*codes. - drive-plugin-chunks — chunk addressing: 164-byte fixed-width header, XChaCha20-Poly1305 streaming AEAD, Ed25519 inline-hint signing, sparse-file + chunk-keys layouts, server-signed manifest. 12
CHUNKS_*codes.
Consumers: drive-sharing, drive-transport-https, drive-transport-webrtc, drive-webrtc (browser-tier P2P mesh plugin), drive-mesh (P2P orchestrator: PeerRegistry, GossipEngine, ParallelPuller, ServerFallback), drive-react-sharing (React 19 hooks + accessible components).
Vault
- vault — orchestration:
open/unlock/lockFSM, encrypted single-blob container viaDriveLike, items/attachments/shares/sync,OpaqueKeyHandle, forward-only migrations, bitpacked manifest, 25+ error codes. - vault-sync — sync + conflict resolution: 3 merge strategies (lww/append/atomic) with vector clocks, RFC 6902 diff/patch,
SyncEngine/SyncQueue, payload encryption with AAD + 10 MiB cap. 10 error codes.
Network
- network — plugin-based core.
NetworkPluginlifecycle,NetworkNode,MessageEnvelopeZod schema,MessageRouter(unicast/broadcast/fan-out),PluginManager,NetworkBus,VersionInfo/VersionManager/VersionNegotiator,NetworkTimestamp,NetworkEventsregistry, 5NET_*codes. Concrete transports/governance/registry/failover/topology all live in siblingnetwork-plugin-*packages.
i18n family
- i18n — slim integration core (post-Wave-6 split). Owns
MessageCatalog,createI18n/I18nInstance, locale negotiation, server middleware,defaultFormatBridge. Re-exports siblings for back-compat. - i18n-shared — universal-tier shared atoms: locale constants,
LOCALE_BCP47_MAP,RTL_LOCALES,I18N_CODES(18),I18nError,./testingrunBackendConformanceharness. - i18n-icu-parser — ICU MessageFormat parser (tokenizer + AST + CLDR plurals).
- i18n-detector — 9-detector chain (querystring, userPreference, cookie, localStorage, htmlLang, acceptLanguage, navigator, cloudflareIpGeo, fallback) +
bcp47Negotiate+ RTL helpers. - i18n-backend-{memory, http, storage, chained, fs-multifile} — translation backends; all conform to
runBackendConformanceharness.fs-multifileis server-tier. - i18n-formatter-{number, currency, date, relative-time, list, display-name, collator, segmenter} —
Intl.*adapters plugged intodefaultFormatBridge.
Time, sequencing, validation, control flow
- datetime, timing, cron (gates
job-scheduler), job-scheduler (consumescron+retry), validation, retry, idempotency, fsm, schema-registry, feature-flags, workflow (universal-tier pipeline orchestration: fluent builder, sequential / parallel / conditional steps, saga compensation, retry middleware, hook registry, transition-data pipeline, Zod-validatedWorkflowConfig, injectableClock, sixWORKFLOW.*codes, OTel counters + histogram). See per-package READMEs.
Rules
- rules — universal-tier rule engine + validators + actions + hooks + serializer + optimizer. 24 codes. Discriminated
Ruleunion,RuleBuilder, 33 built-in operators. - rules-hono — Hono middleware suite (6 factories: rule, validation, accessControl, responseValidation, rateLimit, combine). Hono peer dep.
Security / vault leaves
- slsa, security-codes, data-masking, suppression, macos-keychain, hibp, password-generator, password-strength, x509, jws, tpm-struct, cbor, otp, srp, webauthn — see per-package READMEs.
webauthnconsumes cbor/x509/jws/tpm-struct/crypto-{rsa,curve}; covers all 7 attestation formats.
Serialization / data shape
- serialize, diff, pagination, mime, templates, bitpacker, bitpacker-compressed, packer, packer-browser (browser-tier runtime for packer archives: SW interceptor +
PackedResourceManager+ Ed25519 signature verification; no React dep), react-packer (React 19 companion:usePackedResource/usePackedImage/usePackedAudio/usePackedVideo/usePackedFonthooks +PackedResourceProvidercontext; consumes@suaveplan/packer-browser; React peer-dep only).
File / media / domain utilities (mostly leaves)
- metadata, exif, dmarc, sitemap, domain-normalizer, dedup, password-formats, barcode, qrcode, compress-image, font-subset, font-convert, font-compress (bin:
suaveplan-font-compress— TTF/OTF/WOFF/WOFF2 → BTF pipeline).
Geo / astronomy / tides
- geo, geo-planet, geo-earth, solar-system, stars, tides, universe — abstract spherical geometry → planet config → Earth specifics → injectable astronomy/star/tidal providers aggregated through
universe.
Network clients / IO / DB / installer
- oauth-client, webhook-client, readline, cli.
- db (adapter foundation), db-sqlite (universal:
bun:sqliteon Bun,@sqlite.org/sqlite-wasmin browser). - installer (plugin host, bin
suaveplan-install), install-agent-skills (skill bundle installer).
Games (universal-tier)
- ecs — archetype-based Entity Component System:
Uint32ArrayBitSet, column-oriented archetype storage with O(1) swap-remove, phase+prioritySystemScheduler(preUpdate→update→postUpdate→render), entity-ID recycling with generation counters, Zod-validated component schemas,EventBus<WorldEventMap>entity lifecycle events, OTel counter (ecs.entity.lifecycle_total) + histogram (ecs.world.execute_duration_ms),WorldSnapshotround-trip. 7ECS.*codes. Deps:@suaveplan/error,@suaveplan/types,@suaveplan/events,@suaveplan/opentelemetry,tslib,zod.
Contacts
- contacts — universal-tier contact and group management: hierarchical n-level groups (adjacency + materialised path), channel-agnostic contacts with dedup, many-to-many memberships with ancestor count propagation, audience resolution with descendant walk + dedup + filters, contact merger, CSV/JSON import-export, injectable
Clock+IdGenerator, Zod input boundaries, six OTel counters + three histograms, typedContactsErrorhierarchy with stableCONTACTS.*code registry. - macos-contacts — macOS Contacts.app bridge: AppleScript reader,
Contact↔ macOSPersonmapping, deduplication via@suaveplan/contacts/dedup, push/pull/sync, vCard import-export. - api-sandbox-vm —
vm.Context-based sandbox host (Stage 8.2). Builds a Proxy-guardedvm.Contextwith frozen-globals allowlist (URL/URLSearchParams/TextEncoder/TextDecoder/structuredClone+ logger-routedconsole+ trimmedcrypto),vm.SourceTextModuleplugin loader with refuse-everything linker (rejectsnode:*, bare specifiers, parent traversal),eval/Functiontraps, host-proxied fs/fetch with permission gating, consolidated__suaveplancapability receiver, in-packagePermissionCheckerdefault fromPermissionsManifest, idempotentdispose(), OTelsandbox_vm.{boot_duration_ms,eval_rejected_total,module_import_rejected_total}+ sharedplugin.permission_denied_total, 5-codeSAND_VM.*registry,./testing/runVmSandboxConformanceharness. Requires Node ≥ 20 with--experimental-vm-modules. - api-plugin-contacts — Contacts + groups HTTP plugin for
@suaveplan/api. Mounts/contactsand/groups(with/groups/:id/members,/groups/:id/tree,/groups/:id/move,/groups/:id/resolve) on a HonoOpenAPIHonobacked by SurrealDB implementations of the@suaveplan/contactsContactStore/GroupStore/MembershipStoreinterfaces. Bulk-import with per-row error reporting, repository-levelmaxGroupDepthenforcement, six OTel instruments (4 counters + 2 histograms), typed HonoContextVariableMap+ServiceRegistryaugmentations, and the 12-codeCONTACTS_API.*error namespace.
API sandboxing
- api-sandbox-wasm — Stage-8 WebAssembly sandbox host for sandboxed-tier plugins. Instantiates a guest WASM module against a
wasi_snapshot_preview1snapshot built from the plugin'sPermissionPolicy: read-only WASI preopens frompermissions.fs[](withrw:opt-in), outbound socket allowlist frompermissions.fetch[](sock_connectgate raisesSAND_WASM.OUTBOUND_DENIEDBEFORE any OS socket), and capability host imports undersuaveplan_capspermission-gated per call (denied →WASI_ERRNO.ACCES+plugin.permission_denied_total{plugin,capability,reason}). Owns a 4-codeSAND_WASM.*registry, arunWasmSandboxConformanceharness on./testing, and a hand-encoded fixture WASM builder so the test suite needs nowabtbuild step.WasmSandboxHandle.dispose()idempotent.
Rules
Critical (never compromise)
- NEVER run
tscdirectly — use Vite/tsup viabunx turbo build. Bun runs.tsnatively. - NEVER use mocks — real services only (no
vi.mock/jest.mockunless absolutely necessary). - Bun
overrideswith exact versions. - NEVER re-export external deps for convenience — import directly from source.
- NEVER auto-commit/push without user approval — never use
--no-verify. - Always use absolute paths in tool calls.
- Read files before editing — understand context first.
- Testing-infrastructure packages (
testing,testing-dom,testing-e2e) must not depend on any@suaveplan/*runtime package — external catalog deps only. Sole exception:@suaveplan/types(types-only, byte-size-test guarded). - NEVER write
// biome-ignore(or any static-analysis suppression comment) in migrated/new code. Stale rule names → hard parse-error fails; right names that no longer match →Suppression comment has no effectwarnings. Both block CI. To exercise a deliberate violation, use a coding pattern biome cannot statically reject. Full rule:openspec/AGENTS.md §2a. - NEVER write
export *in any non-root barrel. Feature-module barrels MUST use explicit named re-exports. Exempt: generated*.select/index.tsforwarders, single-line*.native//*.noble/impl-variant forwarders, namespace re-exports. Package roots MAY currently useexport *but new ones SHOULD prefer namespace exports. Migrateexport *→ named exports as part of the migration commit, not a follow-up. Full rule:openspec/AGENTS.md §6a. - NEVER import test-runner primitives directly from
vitestorbun:testin non-exempt packages. Test files MUST import from@suaveplan/testing/runner. Exempt allowlist (5):testing,testing-dom,testing-e2e,testing-integration,testing-integration-step-ca. CI gate:bun scripts/lint/check-test-runner-imports.ts. Verification:grep -rnE "from ['\"](vitest|bun:test)['\"]" packages/<category>/<plugin>/<pkg>/src/→ zero output. Full rule:openspec/AGENTS.md §7.
Git safety (non-negotiable — code has been lost twice on main)
Before ANY git operation: run git status in every worktree (git worktree list) and confirm each is clean or its state is understood.
NEVER run these without explicit per-use user approval:
git filter-repo/git filter-branch— rewrites history, destroys staged + working tree.git push --force/--force-with-lease— only after user explicitly says "force push".git reset --hard,git clean -f[d],git rebase,git stash drop/clear,git gc/prune,git checkout -- <file>.
Large-file push errors: stop, do NOT rewrite history. Run git status/git stash list in all worktrees first, then ask the user (.gitignore + new commit, Git LFS, or manual removal).
Staged changes are irreplaceable — treat them as more precious than committed history.
Worktree discipline — long-lived worktrees are never the answer.
- Before opening a worktree or dispatching a parallel agent:
git worktree listandgit statusin each existing one. Account for every entry: active agent, work-pending-merge, or stale-and-prune. - After a worktree-based agent ships (commit on a
feat/*branch), remove the worktree (git worktree remove) so the count returns to baseline. The branch + commit survive; the directory does not need to. - The baseline is one worktree (the main checkout). Anything beyond that is an open ticket waiting to be closed.
- Run
bun scripts/worktree-prune.tsto audit + prune in one command. It's idempotent and refuses to remove worktrees whose HEAD commit isn't reachable from any branch ref (so it never loses work).
Worktree-isolated agents: never edit the main checkout. When dispatched into an isolated worktree at .claude/worktrees/agent-<id>/, every file operation MUST target that worktree path, never /home/paul/web/genesis/. The hazards are real and observed:
- First action in every agent session:
pwd && git worktree listto confirm you're in the right tree. Ifpwdshows/home/paul/web/genesisinstead of a.claude/worktrees/agent-*path, STOP and report — you are not in an isolated worktree. - Use relative paths (
packages/...,openspec/...) for every read/edit/write. Avoid absolute paths in tool calls unless reading reference material from outside the worktree (e.g. main-branch source at/mnt/s/web/suaveplan/...). - Never
cdto/home/paul/web/genesis/from a worktree. The Read/Edit/Write tools resolve relative paths against the working directory of the bash session, which starts in the worktree. - Before committing:
git rev-parse HEADandgit rev-parse --show-toplevelmust show your worktree's branch + path, not main's. If either is wrong, your work landed in the wrong place — recover withgit statusin BOTH locations, then move the changes back via patch (git diff > /tmp/work.patch,cd $WORKTREE,git apply /tmp/work.patch).
Cross-worktree leakage has been the failure mode in three recent agent sessions — wasted ~1 hour each time. This rule is the prevention.
§0a Sync — worktrees fork from a stale base. Empirically the harness's isolation: "worktree" may fork from an earlier session-stable ref rather than current genesis HEAD. This bit Wave B (5 agents all forked from a pre-Wave-A commit). Prevention: every parallel-dispatch prompt MUST include a §0a Sync block that fast-forwards the worktree to a known base SHA before any work begins:
EXPECTED_BASE=<orchestrator-supplied-sha>
if ! git merge-base --is-ancestor "$EXPECTED_BASE" HEAD; then
git fetch /home/paul/web/genesis genesis
git merge FETCH_HEAD --no-edit
fi
git merge-base --is-ancestor "$EXPECTED_BASE" HEAD || { echo "STILL OUT OF DATE"; exit 1; }
The orchestrator passes the expected SHA at dispatch time. Agents that can't reach it STOP and report rather than proceeding Wave-N-blind. Without this gate, agents re-invent interfaces from earlier merges and produce work that doesn't integrate.
Workflow
- TaskCreate for multi-step tasks (>3 steps).
- Complete all implementations — no stubs, no placeholders, no TODOs, no mocks in production. Missing dep? Add it and wire the real implementation.
- Build feature-rich, production-grade packages — comprehensive enterprise-level over minimal MVP.
- Professional honesty — no marketing language or fake metrics.
- Preserve full public surface during rewrites. Trim ONLY when duplicated in-repo or replaceable by an existing
@suaveplan/*library.
Web App & Page Verification
When generating client-side pages/web apps, verification is NOT optional and a 200 response is NOT proof of correctness:
- Docker staging environment — mirror production before declaring done.
- Full Playwright E2E sweep — every page, every component, every navigation.
- Never trust HTTP 200 alone — verify rendered DOM contains expected content.
- Inspect browser console — any unexpected error or warning fails the check.
- Inspect network activity — failed requests, missing assets, CORS, mixed content.
- Zero-defect push to live — fix root cause first.
Package Lifecycle
- New packages: add to listing, then
bun scripts/folder-reorg/generate-manifest.ts. - Editing: every package starts at
0.1.0; bump only at1.0.0graduation. - Pre-publish gate (non-negotiable):
bunx turbo lint typecheck test --filter=@suaveplan/<pkg>MUST be green ANDbunx turbo test:coverage --filter=@suaveplan/<pkg>must meet 100% on touched modules. Full-packageturbo testrequired — single-filevitest runis not a substitute. - After verification passes:
bun scripts/publish.ts --package @suaveplan/<pkg>.
Package Structure (library packages)
Five files per feature module, co-located:
src/category/
feature-name/
index.ts # Barrel — explicit named re-exports (rule 10)
feature-name.ts # Implementation
feature-name.test.ts # Vitest tests
feature-name.types.ts # Type definitions (no .md required)
feature-name.md # Co-located docs (required)
Special: types/ (shared types, flat), utils/ (utilities, flat with tests + .md), constants/index.ts (simple exports, no tests/docs).
No flat modules at src/ root. Every implementation file paired with a .test.ts MUST live in a src/<feature>/ folder, not flat at src/ root. The only flat entries permitted at src/ root are index.ts (package barrel) and the three exempt directories above. This includes error-codes, telemetry, schemas, and similar "single-concept" modules — they get their own folder + index.ts barrel just like any other feature. Empirically this gets cut by agents shortcutting "atomic" modules to flat siblings of index.ts; lint+typecheck+coverage all accept it. CI gate: bun scripts/lint/check-feature-layout.ts (wired into bunx turbo lint).
Subpath exports in package.json for tree-shaking: ./category/feature/feature.
README layout: one README.md at package root only. No category-level READMEs inside src/<category>/.
Quality
- 100% test coverage —
bun run test:coverage --filter=@suaveplan/<pkg>(provider: 'istanbul'). - 100% docs coverage —
bun run docs:check --filter=@suaveplan/<pkg>. - ~250 lines soft / 300 lines hard limit per code file, 500 lines max per test file.
.test.tsfor Vitest,.spec.tsfor Playwright E2E.- Always add
{ timeout: 5000 }(30000 for async) toit()/test(). - Root cause analysis — never skip/disable tests.
- Every React component needs
.stories.tsx(default + playground + variants).
Documentation (co-authored .md per implementation file)
Every .ts/.tsx MUST have a sibling .md. Exclusions: .test.ts, .test.tsx, .spec.ts, .types.ts (inside a feature dir), .stories.tsx, barrel index.ts, constants/index.ts.
Required sections: Purpose (≥2 sentences), Features, Usage: Basic, Usage: Advanced, API Reference, Implementation Notes.
Hard constraints: ≥200 words excl. code; both simple AND advanced examples mandatory; code must compile with real imports; no marketing/placeholder text; update docs when code changes.
Vitest / WSL2
- Use
createTestConfig()from@suaveplan/testing/configfor vitest configs. For configs needing aliases/plugins, write standalone withpool: 'forks'+setupFiles: ['@suaveplan/testing/polyfills']. - NEVER
mergeConfigwithbaseVitestConfig— missing polyfills causecrypto is not defined. vmThreadsandthreadspools both fail in Bun on WSL2 — use defaultforks.fileParallelism: falserequired for browser tests.- SurrealDB: check
error?.code === 'ConnectionRefused' || error?.message?.includes('Unable to connect').
Code Organization
- Universal: ZERO browser/React deps | Browser: React/DOM ok | Server: Node.js ok.
- Co-locate tests with source,
.mddocs per implementation file.
Dependencies
workspace:^for internal deps, Bun catalogs for external."sideEffects": falseon all pure library packages.
Quick Commands
bunx turbo test --filter=@suaveplan/<pkg> # Test one package
bunx turbo test:coverage --filter=@suaveplan/<pkg> # Coverage for one package
bunx turbo lint --filter=@suaveplan/<pkg> # Lint one package
bunx turbo typecheck --filter=@suaveplan/<pkg> # Type check one package
bunx turbo lint typecheck test --filter=@suaveplan/<pkg> # Pre-publish gate
bunx turbo test # All tests (no DB)
bunx turbo lint typecheck # All lint+types