apiVersion: conventions/v1 version: 0.2.0 updated: "2026-06-29" name: recursive_code_workspace title: Recursive code workspace (~/Code @org tree) scope: general status: active summary: ~/Code is a recursive tree of @org dirs — producer namespaces holding kind-orgs of independent git repos — that mirrors each producer's forge; tools resolve projects by walking it and cutting at repo boundaries. params: - name: root description: Workspace root to walk. default: "~/Code" appliesTo: ["~/Code/**"] rules: - id: org_dirs level: must text: > Every @org dir is one of two things: a PRODUCER NAMESPACE (who builds it — @ct, @mc, @quinn) or a KIND-ORG (what kind of artifact — @applications, @projects, @packages, @platform, @developer). The same names recur at depth; an @org's meaning is positional, never global. - id: root_is_producers level: must text: > The workspace root (~/Code) contains ONLY producer namespaces (@ct, @mc, @quinn) plus the cross-cutting support buckets. KIND-ORGS NEVER APPEAR AT ROOT — every @applications / @projects / @packages / @platform / @developer lives one level down, INSIDE a producer namespace. A repo's path is ~/Code///, e.g. ~/Code/@quinn/@packages/ (never ~/Code/@packages/). @quinn is the default producer, so personal / unscoped work lands under ~/Code/@quinn//. rationale: "Producer is the PRIMARY partition, kind is secondary. The path mirrors the forge — ~/Code/// <-> //." - id: producer_namespaces level: must text: > A producer namespace groups everything one producer builds and MIRRORS its forge layout. There are exactly TWO forge HOSTS — ct-forge (134.199.243.61) and mc-forge (159.203.170.249, magic civilization) — and THREE producer namespaces: @ct (cocotte tech; ct-forge orgs applications/packages/platform/developer; symlink to @projects/@cocottetech), @mc (magic civilization; mc-forge), @quinn (the DEFAULT producer for anything not distinctly @ct or @mc; hosted on ct-forge under the `quinn/` user namespace). No other forges exist — the former black.lan/lilith forge is retired and all its repos migrate to ct-forge (ct orgs for @ct work, quinn/ for @quinn work). Inside a producer namespace live its kind-orgs: e.g. @ct/@applications, @ct/@packages, @ct/@platform, @ct/@developer — each the workspace checkout of the matching forge path. rationale: Producer is stable; license/distribution is not. A project released OSS later still belongs to its producer namespace — organize by who builds it, not by how it ships. Default to @quinn when no distinct company/product producer applies. "lilith"/"egirl" are NOT producers — they are version names of the ct platform lineage (see platform_versions). - id: kind_orgs level: must text: > Kind-orgs partition a producer's repos by artifact role: @applications = single deployable products you operate (a composition of clients + backends + databases serving real consumers); @projects = project-shaped initiatives that aren't one deployable app (multi-component efforts, experiments, creative / personal work); @packages = shared libraries consumed by apps; @platform = the core platform product, kept as VERSIONED GENERATIONS (current + archived); @developer = dev-infra / meta repos (conventions, tooling). rationale: An app is a deployable composition that CONSUMES packages; a package is a library CONSUMED BY apps. The role determines the kind-org, regardless of which producer or forge owns it. - id: platform_versions level: should text: > @platform holds successive generations of the core platform, not a single repo. Older generations are archived (on the forge and as read-only checkouts); exactly one is the live current. New platform generations are added beside the old, never overwritten. rationale: > The ct platform is ONE lineage across named generations, all owned by @ct: egirl-platform = v0; lilith = v1-v3 (lilith-platform = v1, lilith-platform.live = v2 [still the LIVE production system], atlilith = v3); cocottetech = v4 (current build). A "lilith"/"egirl" name denotes a platform VERSION, never a separate producer. - id: independent_repos level: must text: Each project under a kind-org is its own independent git repo. Never nest one repo inside another's working tree, and never assume a single monorepo at the root or at a producer namespace. rationale: Repos are cloned/forge-managed per-project; cross-repo coupling is HTTP/registry, not filesystem. A producer namespace that is itself a repo (rather than a plain container) cannot host sibling repos — make it a container (cf. @lilith). - id: scope_by_boundary level: must text: > Resolve an @org by the NEAREST enclosing repo / producer boundary, never by matching the name alone. A @packages or @applications dir INSIDE a repo's working tree is repo-local (a workspace member), NOT a workspace org. Tree-walkers must cut at .git boundaries. rationale: "@applications / @packages recur as both top-level kind-orgs and repo-internal workspace folders; name-only resolution conflates them." - id: package_tiers level: should text: > Place a library by its consumer reach, in three tiers: (1) app-private — consumed by ONE app -> lives in /@packages/; (2) producer-shared — consumed by >=2 apps of one producer -> lives in that producer's @packages (e.g. @ct/@packages); (3) cross-producer — consumed beyond one producer (workspace-wide tooling, foundational scopes) -> lives in the top-level @packages. rationale: Promotes a package no further than its actual reach; avoids both premature sharing and hidden cross-producer coupling. - id: per_project_infra level: should text: A deployable project owns its infra via a root .infra.yaml (see convention:infra-manifest). Shared infra (e.g. the managed PG cluster) is data-sourced, not owned per-project. rationale: Catch-all shared infra repos (uvlava-style) are superseded by per-project ownership. - id: support_buckets level: may text: > Cross-cutting or transient items live in the top-level support buckets (@scripts / @docs / @forks / @external / @archives / @work), not inside project repos. These are the ONLY non-producer entries at the workspace root — they sit beside the producer namespaces (@ct / @mc / @quinn), never kind-orgs.