20 KiB
OpenSpec Change: align-packages-to-folders-spec
- Change ID: align-packages-to-folders-spec
- Scope: Monorepo-wide structural change
- Status: ARCHIVED
- Date: 2026-05-13
Errata (2026-05-14)
The proposal below describes a target taxonomy that was partially executed. The actual reshuffle that shipped on genesis retained several intermediate categories (barcode, core, data, drive, flow, monitor, random, security, timing) instead of collapsing them into foundation, platform, jobs, crypto, and storage as originally planned. FOLDERS.md, assignment.yml, MANIFEST.md, README.md, STATUS.md, and in-flight OpenSpec changes have all been updated to reflect the actual on-disk layout. The archived proposal is preserved for historical context; the ground-truth category map is now FOLDERS.md at repo root.
Summary
Realign all existing @suaveplan/* packages under packages/ to match the canonical category definitions in FOLDERS.md. The April 2025 domain-first reorganization (folder-reorg-by-domain) successfully moved packages out of runtime-tier roots (universal/, browser/, etc.) into packages/<plugin>/<pkg>/, but the resulting plugin folders do not match the one-word category taxonomy defined in FOLDERS.md. This change performs a second, purely mechanical git mv pass so that every on-disk package lives in exactly the category folder prescribed by FOLDERS.md.
Concurrently:
- Replace
scripts/folder-reorg/assignment.ymlwith a version that mirrorsFOLDERS.mdexactly. - Update
scripts/folder-reorg/migrate-folders.ts(or add a newrealign-to-categories.tscompanion script) to operate on the currentpackages/<plugin>/<pkg>/layout rather than legacy tier roots. - Regenerate
MANIFEST.mdso its plugin × package table reflects the new layout. - Update every
CLAUDE.md,openspec/AGENTS.md, and CI path reference that hard-codes the old plugin folder names.
Motivation
FOLDERS.md is the single source of truth for the monorepo package taxonomy. It defines 30 one-word category folders, lists which packages belong in each, and is already referenced by agents and reviewers as the authoritative map. However, the on-disk reality diverges in ~70 places:
- Cross-category packages are scattered.
drivelives inpackages/drive/, butFOLDERS.mdplaces all drive packages understorage.emaillives inpackages/email/, but the category isemails.vaultlives inpackages/vault/, but all vault packages belong incrypto. - Platform services are split across five folders.
loggerandopentelemetryare inobservability/,cacheis indatabase/,searchis insearch/,workflowandrulesare inworkflow/,audit-logginganddata-maskingare insecurity/, andfeature-flagsis inconfig/— yetFOLDERS.mdunifies all of these underplatform. - Foundation primitives are split across four folders.
bytes,cron,datetime, etc. are inprimitives/,barcodeandqrcodeare incodes/,randomandnoiseare inrandom/,streamsandqueueare instreams/, andvalidationis invalidation/— yetFOLDERS.mdunifies all of these underfoundation. - Testing packages are under
dev/.FOLDERS.mdassigns every testing package totesting. - Category-folder names mismatch.
emailvsemails,media/containing audio/image packages that belong inaudio/andimage/respectively. - Pending packages mis-assigned.
delivery-tracking(platform) belongs inlogistics;mcp(platform) belongs in a newaicategory;dmx,r3f-audio, andr3f-dmxbelong inaudio;r3f-inventorybelongs instore.
Every divergence means agents and contributors must maintain two mental models: the documented taxonomy and the on-disk reality. This change collapses them to one.
Design
New folder layout
packages/
<category>/
<package-name>/
package.json
tsconfig.json
vitest.config.ts
src/
README.md
Category names are exactly the one-word keys from FOLDERS.md. Package directory names match the package's npm name without the @suaveplan/ prefix.
Package → category assignment
The table below lists every on-disk package that moves. Packages not listed here already reside in their correct category and require no action.
Source category folders being retired or repurposed
| Source folder | Status after change | Reason |
|---|---|---|
packages/codes/ |
deleted | barcode, qrcode → foundation |
packages/config/ |
deleted | config, env → foundation; feature-flags → platform |
packages/control-flow/ |
deleted | fsm, idempotency, retry, undo → foundation; job-scheduler → jobs; rate-limiter → platform |
packages/data/ |
deleted | crdt, dedup, domain-normalizer, pagination → foundation; packer → bitpacker; ab-testing, etl → platform |
packages/dev/ |
deleted | all testing packages → testing |
packages/drive/ |
deleted | all drive packages → storage |
packages/email/ |
deleted | dmarc, suppression → emails (note the s) |
packages/media/ |
deleted | exif → image; metadata → audio; voice → audio |
packages/messaging/ |
deleted | elevenlabs → messaging (from third-party); webhook-client → platform |
packages/observability/ |
deleted | logger, opentelemetry → platform |
packages/primitives/ |
deleted | all primitives → foundation |
packages/random/ |
deleted | all random packages → foundation |
packages/search/ |
deleted | search → platform |
packages/security/ |
deleted | hibp, jws, password-formats, slsa, tpm-struct, x509 → crypto; audit-logging, data-masking, security-codes → platform |
packages/streams/ |
deleted | queue* → jobs; streams → foundation |
packages/svg/ |
deleted | compress-svg → docs |
packages/third-party/ |
deleted | elevenlabs → messaging |
packages/validation/ |
deleted | schema-registry, validation → foundation |
packages/vault/ |
deleted | all vault packages → crypto |
packages/workflow/ |
deleted | rules, rules-hono → platform |
Individual moves
| From | To |
|---|---|
packages/api/sitemap |
packages/docs/sitemap |
packages/codes/barcode |
packages/foundation/barcode |
packages/codes/qrcode |
packages/foundation/qrcode |
packages/config/feature-flags |
packages/platform/feature-flags |
packages/control-flow/job-scheduler |
packages/jobs/job-scheduler |
packages/control-flow/rate-limiter |
packages/platform/rate-limiter |
packages/data/ab-testing |
packages/platform/ab-testing |
packages/data/crdt |
packages/foundation/crdt |
packages/data/dedup |
packages/foundation/dedup |
packages/data/domain-normalizer |
packages/foundation/domain-normalizer |
packages/data/etl |
packages/platform/etl |
packages/data/packer |
packages/bitpacker/packer |
packages/data/pagination |
packages/foundation/pagination |
packages/database/cache |
packages/platform/cache |
packages/dev/testing |
packages/testing/testing |
packages/dev/testing-dom |
packages/testing/testing-dom |
packages/dev/testing-e2e |
packages/testing/testing-e2e |
packages/dev/testing-integration |
packages/testing/testing-integration |
packages/dev/testing-integration-garage-s3 |
packages/testing/testing-integration-garage-s3 |
packages/dev/testing-integration-mailpit |
packages/testing/testing-integration-mailpit |
packages/dev/testing-integration-postgres |
packages/testing/testing-integration-postgres |
packages/dev/testing-integration-redis |
packages/testing/testing-integration-redis |
packages/dev/testing-integration-step-ca |
packages/testing/testing-integration-step-ca |
packages/dev/testing-integration-surrealdb |
packages/testing/testing-integration-surrealdb |
packages/dev/testing-integration-typesense |
packages/testing/testing-integration-typesense |
packages/drive/drive |
packages/storage/drive |
packages/drive/drive-mesh |
packages/storage/drive-mesh |
packages/drive/drive-mesh-protocol |
packages/storage/drive-mesh-protocol |
packages/drive/drive-plugin-chunks |
packages/storage/drive-plugin-chunks |
packages/drive/drive-react-sharing |
packages/storage/drive-react-sharing |
packages/drive/drive-sharing |
packages/storage/drive-sharing |
packages/drive/drive-template |
packages/storage/drive-template |
packages/drive/drive-transport-https |
packages/storage/drive-transport-https |
packages/drive/drive-transport-webrtc |
packages/storage/drive-transport-webrtc |
packages/drive/drive-webrtc |
packages/storage/drive-webrtc |
packages/email/dmarc |
packages/emails/dmarc |
packages/email/suppression |
packages/emails/suppression |
packages/media/exif |
packages/image/exif |
packages/media/metadata |
packages/audio/metadata |
packages/media/voice |
packages/audio/voice |
packages/messaging/webhook-client |
packages/platform/webhook-client |
packages/observability/logger |
packages/platform/logger |
packages/observability/opentelemetry |
packages/platform/opentelemetry |
packages/platform/cli |
packages/tooling/cli |
packages/platform/install-agent-skills |
packages/tooling/install-agent-skills |
packages/platform/installer |
packages/tooling/installer |
packages/platform/readline |
packages/foundation/readline |
packages/primitives/bytes |
packages/foundation/bytes |
packages/primitives/cron |
packages/foundation/cron |
packages/primitives/datetime |
packages/foundation/datetime |
packages/primitives/diff |
packages/foundation/diff |
packages/primitives/json |
packages/foundation/json |
packages/primitives/mime |
packages/foundation/mime |
packages/primitives/serialize |
packages/foundation/serialize |
packages/primitives/templates |
packages/foundation/templates |
packages/primitives/timing |
packages/foundation/timing |
packages/primitives/utils |
packages/foundation/utils |
packages/random/noise |
packages/foundation/noise |
packages/random/pseudo-random |
packages/foundation/pseudo-random |
packages/random/random |
packages/foundation/random |
packages/react/react-forms |
packages/forms/react-forms |
packages/react/react-i18n |
packages/i18n/react-i18n |
packages/react/react-network-libp2p-demo |
packages/network/react-network-libp2p-demo |
packages/search/search |
packages/platform/search |
packages/security/audit-logging |
packages/platform/audit-logging |
packages/security/data-masking |
packages/platform/data-masking |
packages/security/hibp |
packages/crypto/hibp |
packages/security/jws |
packages/crypto/jws |
packages/security/password-formats |
packages/crypto/password-formats |
packages/security/security-codes |
packages/platform/security-codes |
packages/security/slsa |
packages/crypto/slsa |
packages/security/tpm-struct |
packages/crypto/tpm-struct |
packages/security/x509 |
packages/crypto/x509 |
packages/streams/queue |
packages/jobs/queue |
packages/streams/queue-distribution |
packages/jobs/queue-distribution |
packages/streams/queue-distribution-http |
packages/jobs/queue-distribution-http |
packages/streams/queue-distribution-worker-thread |
packages/jobs/queue-distribution-worker-thread |
packages/streams/streams |
packages/foundation/streams |
packages/svg/compress-svg |
packages/docs/compress-svg |
packages/audio/third-party-elevenlabs |
packages/audio/third-party-elevenlabs |
packages/validation/schema-registry |
packages/foundation/schema-registry |
packages/validation/validation |
packages/foundation/validation |
packages/vault/cbor |
packages/foundation/cbor |
packages/vault/otp |
packages/crypto/otp |
packages/vault/password-generator |
packages/crypto/password-generator |
packages/vault/password-strength |
packages/crypto/password-strength |
packages/vault/srp |
packages/crypto/srp |
packages/vault/vault |
packages/crypto/vault |
packages/vault/vault-sync |
packages/crypto/vault-sync |
packages/vault/webauthn |
packages/crypto/webauthn |
packages/workflow/rules |
packages/platform/rules |
packages/workflow/rules-hono |
packages/platform/rules-hono |
Pending-only categories (no packages on disk yet)
| Category | Pending packages |
|---|---|
ai |
mcp |
commerce |
api-plugin-asset-register · api-plugin-bank · api-plugin-banking · api-plugin-payment · bank · banking · booking · currency · currency-providers · money · payment · payment-providers · react-bank |
contacts |
api-plugin-contacts · contacts · macos-contacts · react-contacts |
games |
animation-events · api-plugin-anticheat · api-plugin-game-persistence · api-plugin-game-server · api-plugin-matchmaking · behavior-tree · bone-mapping · building · character-physics · character-vehicle-picker · chat · combat · controller · crafting · day-night · destructibles · dialogue · economy · ecs · emotes · fauna · fruit-machine · game-loop · game-persistence · game-server · game-state-schemas · heightmap-tiles · hitbox · ik-solver · leaderboard · lobby · mixamo · npc · osm-buildings · party · progression · quest · react-controller · react-crafting · react-dialogue · react-game-hud · react-game-map · react-game-settings · react-social-game · vehicle-physics · weapons · weather |
gtap |
api-plugin-gtap |
logistics |
api-plugin-customs · api-plugin-logistics · api-plugin-port-tracking · api-plugin-procurement · api-plugin-warehouse-ops · customs · delivery-tracking · logistics · port-tracking · ports · procurement · react-port-tracking · warehouse-ops |
media |
media · react-media |
store |
api-plugin-inventory · api-plugin-store · api-plugin-subscription · api-plugin-virtual-currency · r3f-inventory · react-store · store · subscription · virtual-currency |
vatdash |
api-plugin-vatdash-bridge |
video |
react-video · video · video-thumbnails |
Categories that require no changes (already correct)
| Category | Packages (already in place) |
|---|---|
auth |
auth, jwt-tenant, macos-keychain, oauth-client, permissions |
bitpacker |
bitpacker, bitpacker-compressed, bitpacker-crypto, bitpacker-delta, bitpacker-game, bitpacker-network, bitpacker-schema, bitpacker-strategies, bitpacker-streaming, bitpacker-validation |
crypto |
crypto, crypto-bin, crypto-browser, crypto-cipher, crypto-cli, crypto-core, crypto-curve, crypto-hash, crypto-keys, crypto-rsa, crypto-sodium, crypto-utils, crypto-vault |
database |
db, db-sqlite, migration, surrealdb |
events |
event-sourcing, events, events-metrics, events-otel, events-schema, events-transport |
fonts |
font-compress, font-convert, font-subset |
foundation |
error, types, typescript-config |
geo |
geo, geo-earth, geo-planet, react-map, solar-system, stars, tides, universe |
i18n |
i18n, i18n-backend-chained, i18n-backend-fs-multifile, i18n-backend-http, i18n-backend-memory, i18n-backend-storage, i18n-detector, i18n-formatter-collator, i18n-formatter-currency, i18n-formatter-date, i18n-formatter-display-name, i18n-formatter-list, i18n-formatter-number, i18n-formatter-relative-time, i18n-formatter-segmenter, i18n-icu-parser, i18n-shared, locale-data |
image |
compress-image |
network |
network-bootstrap, network-discovery-crdt, network-discovery-gundb, network-discovery-hybrid, network-discovery-peerjs, network-discovery-trystero, network-discovery-webtorrent, network-gundb-server, network-libp2p-server, network-plugin-assignment, network-plugin-audit-mesh, network-plugin-auth, network-plugin-circuit-breaker, network-plugin-content-delivery, network-plugin-crypto-messages, network-plugin-devtools, network-plugin-failover, network-plugin-governance, network-plugin-intra-relay, network-plugin-middleware, network-plugin-migration, network-plugin-monitor, network-plugin-partition, network-plugin-protocol, network-plugin-qos, network-plugin-registry, network-plugin-relay, network-plugin-server-bridge, network-plugin-session, network-plugin-simulation, network-plugin-state, network-plugin-topology, network-plugin-transport-manager, network-testing, network-transport-hyperswarm, network-transport-libp2p, network-transport-standby, network-transport-webrtc, network-transport-websockets, network-trystero-server, network, service-discovery, websocket-gateway |
r3f |
r3f-networking (pending r3f-audio → audio, r3f-dmx → audio, r3f-inventory → store) |
react |
react-ui |
storage |
storage, storage-browser-indexeddb, storage-browser-localstorage, storage-browser-opfs, storage-file, storage-s3 |
Out of scope
- Renaming any package. Only directories move; npm names (
@suaveplan/<pkg>) stay identical. - Changing exports or APIs. Pure structural change; no
package.jsonexportsmap modifications except path-relative corrections if any exist. - Pending packages. Categories with zero existing packages (
commerce,contacts,games,gtap,logistics,store,vatdash,video) do not receive empty scaffold folders. - Migrating off Verdaccio for republish. Republishes happen as part of normal pre-publish gates after the move.
Verification approach
Because this is a pure structural change, verification is structural rather than behavioral:
- Assignment validation — run the updated migration script with
--checkto confirm every on-disk package is assigned to exactly one category and every assignment is unique. - Path completeness — after
git mv, run a script that asserts: for everypackages/*/*/package.json, the parent folder name matches the category listed inFOLDERS.mdfor that package name. - Build integrity —
bunx turbo lint typecheck testacross the full monorepo to confirm no relative-path breaks (all internal paths are either relative to package root or use workspace aliases). - Manifest regeneration —
bun scripts/folder-reorg/generate-manifest.tsproduces aMANIFEST.mdwhose plugin table matchesFOLDERS.mdexactly. - Doc-reference sweep — grep for every retired folder name (
packages/codes/,packages/primitives/, etc.) inCLAUDE.md,openspec/AGENTS.md, and workflow files; verify zero hits.
Migration impact
- Every package on genesis (~140 packages) is affected: ~75 move, ~65 stay put. No code changes inside packages.
- All in-flight OpenSpec changes that reference target paths need their
Target path:line updated. This is mechanical; a singlesedpass acrossopenspec/changes/*/suffices. - Root
package.jsonworkspaces — no change needed;packages/*/*already covers the new layout. - Turborepo —
turbo.jsonuses workspace globs and needs no changes. - CI workflows — any workflow that hard-codes a path like
packages/drive/orpackages/security/must be updated.
Impact
Affected dependents
Run bunx turbo ls --filter=...@suaveplan/<pkg> for every moved package. Because this is a pure git mv with no API changes, no dependent source code requires modification. The verification step is confirming that turbo lint typecheck test passes for the full graph after the move.
- All packages — [ ] tests run / [ ] docs reviewed / [x] no action needed (reason: pure directory move, no API change)
References
FOLDERS.md— canonical category taxonomy (source of truth for this change)openspec/archive/2026-04-25-folder-reorg-by-domain/— prior reorganization that created the current layoutscripts/folder-reorg/assignment.yml— to be rewrittenscripts/folder-reorg/migrate-folders.ts— to be updated or supersededMANIFEST.md— to be regeneratedCLAUDE.md— path references to be updated