FactoryWager Wiki

Tenant: monorepo-workspaces (hybrid catalog)

Tenant hybrid Bun monorepo install graph
Gate bun run validate:workspaces · install policy docs/UNIFIED.md
Layout STRUCTURE.md · packages map docs/packages/
Health sibling monorepo-health.md · bun run monorepo:health
Tag v5.2.2-monorepo-workspaces-catalog (milestone: catalog SSOT + homebase gate + package exports)

Model (one paragraph)

FactoryWager is a hybrid monorepo: product/ops live at the root (relative lib/** imports + root scripts). A small set of @factorywager/* packages plus sports-terminal-os are Bun workspace members for linking, catalogs, and --filter. Nested trees under projects/** are separate install roots unless listed in root workspaces.packages.

factorywager-enterprise (root)
├── lib/**          relative imports — primary product surface
├── tools/, tests/  root scripts (ops:*, harness:*, portal:*)
├── packages/*      @factorywager/* workspace packages
├── lib/shared      @factorywager/shared (lib/* glob)
├── sports-terminal-os   workspace app member
└── projects/**     nested monorepos / archive (not root workspaces)

Bun canonical references

Resolve offline with:

bun tools/bun-docs-catalog.ts get workspaces
bun tools/bun-doc-refs.ts suggest "workspaces"
bun tools/bun-doc-refs.ts suggest "--filter"
bun tools/bun-doc-refs.ts suggest "overrides"
bun tools/bun-doc-refs.ts suggest "bun patch"
Topic Canonical URL Use for
Workspaces + workspace: https://bun.com/docs/pm/workspaces Globs, linking, publish rewrite
Catalogs + catalog: https://bun.com/docs/pm/catalogs Shared version SSOT
--filter / scripts https://bun.com/docs/pm/filter Name vs ./path, install/outdated/scripts — see § bun –filter
Parallel / sequential https://bun.com/docs/pm/filter#parallel-and-sequential-mode bun run --parallelbun test --parallel
Dependency order https://bun.com/docs/pm/filter#dependency-order Filtered scripts wait on workspace deps
Install CLI https://bun.com/docs/pm/cli/install Frozen lockfile, peers, filters
Outdated https://bun.com/docs/pm/cli/outdated --filter restricts packages
Isolated installs https://bun.com/docs/pm/isolated-installs configVersion: 1 default
Overrides https://bun.com/docs/pm/overrides Root-only metadeps
Patch https://bun.com/docs/pm/cli/patch patchedDependencies
bunfig install https://bun.com/docs/runtime/bunfig exact · frozen · scopes (TOML)
bun pm https://bun.com/docs/pm/cli/pm ls · why · pkg
Trusted lifecycle https://bun.com/docs/pm/lifecycle#trusteddependencies Allow list replaces defaults

Related catalog pages (from bun tools/bun-docs-catalog.ts get workspaces): workspaces · catalogs · install · outdated · update · filter · isolated-installs · bunfig.

bun –filter (canonical)

SSOT page: pm/filter · offline: bun tools/bun-doc-refs.ts suggest "--filter"
https://bun.com/docs/pm/filter#package-name-filter-pattern

--filter / -F selects workspace packages by pattern. It is supported by:

  1. bun install — install deps for a subset of workspaces
  2. bun outdated — report outdated deps for a subset
  3. Script runsbun run --filter <pattern> <script> (or bun --filter …)

Filters respect root workspaces: only listed members match. Nested monorepos under projects/** are invisible to root --filter.

Matching

Kind Pattern Selects
Package name --filter '@factorywager/*' · --filter sports-terminal-os · --filter '*' package.json "name" (glob)
Package path --filter './packages/*' · --filter './packages/guards' Dirs under workspace root; must start with ./
Negation --filter '!pkg-c' · --filter '!./' Exclude name or path (e.g. exclude root package)
Root only --filter './' Root package.json only (useful for outdated)

install / outdated

# All homebase packages under packages/ (not STO unless path matches)
bun install --filter './packages/*'

# Exclude root package.json from install selection
bun install --filter '!./' --filter './packages/*'

# Outdated pins for @factorywager scope names
bun outdated --filter '@factorywager/*'

# Root package.json only
bun outdated --filter './'

With root frozenLockfile = true, intentional filtered installs still need the usual unlock → install → freeze cycle when the lockfile would change (UNIFIED).

Scripts (parallel / sequential / if-present)

# Concurrent package scripts (Foreman-style prefixes: pkg:script | …)
bun run --parallel --filter '*' --if-present test
bun run --parallel --filter '*' "build:*"
bun run --parallel --no-exit-on-error --filter '*' test

# All workspace packages, one after another
bun run --sequential --workspaces --if-present typecheck

# Named package from anywhere in the monorepo (no cd)
bun run --filter @factorywager/registry-client build
bun run --filter sports-terminal-os typecheck

# Multiple scripts per package where present
bun run --parallel --filter '*' --if-present build test
Flag Role
--parallel Concurrent package scripts (≠ bun test --parallel)
--sequential One package at a time
--workspaces All workspace packages
--if-present Skip packages missing the script (almost always required here — most packages have few scripts)
--no-exit-on-error Keep fan-out running after a package fails

Dependency order: if workspace package foo depends on bar and both have build, bun --filter '*' build starts foo only after bar finishes (dependency order).

Docs UI pitfall: ?search=type:toml

URLs like
https://bun.com/docs/pm/filter?search=type%3Atoml
append a Mintlify docs-site search facet (type:toml = “show TOML code samples”). That is not a Bun CLI filter and not a workspace selector.

FactoryWager cheatsheet

# Package tests / typecheck
bun run --parallel --filter '*' --if-present test
bun run --filter @factorywager/registry-client build
bun run --filter sports-terminal-os typecheck
bun run --filter './packages/*' --if-present test

# Root product (never --filter these script names)
bun run ops:limits:check
bun run portal:snapshot:once
bun test tests/limits-e2e.test.ts
bun test tests/portal-snapshot-cron.test.ts

Root workspaces SSOT

From root package.json (do not invent globs in prose):

"workspaces": {
  "packages": [
    "packages/*",
    "projects/active/sports-terminal-os",
    "lib/*"
  ]
}
Member class Examples
Root workspace:* deps (spine imports) docs-tools, guards, registry-client, rip
Workspace-only (filter/discovery) business, p2p, @factorywager/shared, sports-terminal-os
Archived (out of install graph) projects/archive/factorywager-packages/{ab-testing,versioning}

Gate: scripts/validate-workspaces.tshomebase only (does not require experimental/archive package.json files to be root members).

Catalog SSOT

Root catalog pins shared third-party versions (exact; matches install.exact):

Key Role
typescript Toolchain (root + packages via catalog:)
@types/bun / bun-types Types pin (may lag runtime 1.4.0)
zod, react, react-dom, @types/react* Shared app stack

Consumers must use "pkg": "catalog:" (or catalog:<name>). Do not re-float cataloged names with ^ / latest.

Intentional exception: sports-terminal-os pins typescript at 5.9.3 until TS 6 typecheck cleanup; zod/react/bun-types still use catalog:. See Open debt: STO TypeScript 6.

Policy table + anti-patterns: UNIFIED § Catalogs and workspace protocols.

Open debt: STO TypeScript 6

   
Current sports-terminal-os pins typescript 5.9.3 intentionally; root catalog is 6.0.3.
Why On catalog TS 6, STO tsc surfaces path imports into monorepo lib/, baseUrl/rootDir layout, Response body types, and related strictness — not ready to force the pin.
Exit STO bun run typecheck green on catalog typescript → switch STO package.json to "typescript": "catalog:" → drop the UNIFIED catalog exception.
Owner platform / STO maintainers

TypeScript 6+ types discovery

TS 6 defaults compilerOptions.types to [] (no auto @types/*). Monorepo apps/scripts need "types": ["bun"] so editors and tsc see Bun globals. Public packages that emit clean .d.ts may keep "types": [] intentionally (e.g. packages/registry-client).

Surface Role
tsconfig.base.json SSOT "types": ["bun"] for extenders
bun run check:tsconfig-types Walk all tsconfig*.json; JSONC-aware extends resolution
--strict / CI / GITHUB_ACTIONS Exit 1 when monorepo-owned configs omit bun after extends walk
Pre-commit Staged spine tsconfigs / audit tool → check:tsconfig-types --strict (SKIP_TSCONFIG_TYPES=1)
CI typescript-checks.yml step before type-check scopes
bun run check:tsconfig-types
bun run check:tsconfig-types -- --strict
bun test tests/tsconfig-bun-types.test.ts

@see https://bun.com/docs/typescript-6 · tool tools/tsconfig-types-audit.ts

Commands cheatsheet

# Integrity
bun run validate:workspaces
bun run validate:workspaces --verbose
bun pm ls
bun install --dry-run          # must succeed with frozenLockfile=true
bun run check:tsconfig-types -- --strict   # TS6 types: monorepo_risk=0

# Package scripts — full filter semantics: § bun --filter above
bun run --parallel --filter '*' --if-present test
bun run --filter @factorywager/registry-client build
bun run --filter sports-terminal-os typecheck
bun run --sequential --workspaces --if-present typecheck

# Root product / ops (never --filter these names)
bun run ops:limits:check
bun run portal:snapshot:once
bun test tests/limits-e2e.test.ts

# Dep edits (UNIFIED)
# 1) frozenLockfile=false temporarily
# 2) bun add / bun update / catalog edit
# 3) frozenLockfile=true + commit bun.lock

Portal snapshot cron (workspace-adjacent)

Scope-aware data-plane captures (not registry bake). Operator SSOT: portal-snapshot-cron.md · bun run docs:tenant-portal-snapshot.

Anti-patterns

Wrong Right
bun run --filter '*' ops:limits:check bun run ops:limits:check
Docs listing registry/packages/* as root workspaces Nested monorepo under projects/active/factorywager/registry
bun-types: "latest" in a workspace package catalog: after pinning in root catalog
Partial trustedDependencies: ["one-pkg"] Full list (replaces Bun defaults)
Expecting --filter to select test files Path globs / bun test patterns
Treating docs ?search=type:toml as a CLI flag Docs UI facet only; real filter is name/./path (pm/filter)
bun run --parallel vs bun test --parallel confusion Foreman workspace scripts vs test workers (day-loop)
bun run --workspaces test without --if-present Most packages lack test — always pair --if-present here
Doc / tool Role
monorepo-health.md Score · cycles · large files
IMPORT_BOUNDARIES.md Package import allowlists
bun run audit:packages Packages graph bake
bun run packages:list Registry table refresh

Milestone commits

Commit Note
205a04d45 homebase gate · package exports · archive · portal snapshot cron
5245a7aca trim root workspace deps · STO typecheck · stable chart snaps
623e7ac44 catalog SSOT · lockfile ghost · UNIFIED catalog section

Tag: v5.2.2-monorepo-workspaces-catalog