Files
2026-05-27 23:29:53 +01:00

20 KiB
Raw Permalink Blame History

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:

  1. Replace scripts/folder-reorg/assignment.yml with a version that mirrors FOLDERS.md exactly.
  2. Update scripts/folder-reorg/migrate-folders.ts (or add a new realign-to-categories.ts companion script) to operate on the current packages/<plugin>/<pkg>/ layout rather than legacy tier roots.
  3. Regenerate MANIFEST.md so its plugin × package table reflects the new layout.
  4. 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. drive lives in packages/drive/, but FOLDERS.md places all drive packages under storage. email lives in packages/email/, but the category is emails. vault lives in packages/vault/, but all vault packages belong in crypto.
  • Platform services are split across five folders. logger and opentelemetry are in observability/, cache is in database/, search is in search/, workflow and rules are in workflow/, audit-logging and data-masking are in security/, and feature-flags is in config/ — yet FOLDERS.md unifies all of these under platform.
  • Foundation primitives are split across four folders. bytes, cron, datetime, etc. are in primitives/, barcode and qrcode are in codes/, random and noise are in random/, streams and queue are in streams/, and validation is in validation/ — yet FOLDERS.md unifies all of these under foundation.
  • Testing packages are under dev/. FOLDERS.md assigns every testing package to testing.
  • Category-folder names mismatch. email vs emails, media/ containing audio/image packages that belong in audio/ and image/ respectively.
  • Pending packages mis-assigned. delivery-tracking (platform) belongs in logistics; mcp (platform) belongs in a new ai category; dmx, r3f-audio, and r3f-dmx belong in audio; r3f-inventory belongs in store.

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.json exports map 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:

  1. Assignment validation — run the updated migration script with --check to confirm every on-disk package is assigned to exactly one category and every assignment is unique.
  2. Path completeness — after git mv, run a script that asserts: for every packages/*/*/package.json, the parent folder name matches the category listed in FOLDERS.md for that package name.
  3. Build integrity — bunx turbo lint typecheck test across the full monorepo to confirm no relative-path breaks (all internal paths are either relative to package root or use workspace aliases).
  4. Manifest regeneration — bun scripts/folder-reorg/generate-manifest.ts produces a MANIFEST.md whose plugin table matches FOLDERS.md exactly.
  5. Doc-reference sweep — grep for every retired folder name (packages/codes/, packages/primitives/, etc.) in CLAUDE.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 single sed pass across openspec/changes/*/ suffices.
  • Root package.json workspaces — no change needed; packages/*/* already covers the new layout.
  • Turborepo — turbo.json uses workspace globs and needs no changes.
  • CI workflows — any workflow that hard-codes a path like packages/drive/ or packages/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 layout
  • scripts/folder-reorg/assignment.yml — to be rewritten
  • scripts/folder-reorg/migrate-folders.ts — to be updated or superseded
  • MANIFEST.md — to be regenerated
  • CLAUDE.md — path references to be updated