Canonical component paths vs platform/components/

Status: decided (Workstream 1 / roadmap unit 1) Date: 2026-07-18 Related: adr/007-canonical-component-paths.md, ../plans/autonomy-implementation-roadmap.md, ../../platform/docs/SUBACTOR_MULTI_REPO_MIGRATION.md

Decision

RolePathNature
Canonical sourceSibling repos: core/, connectors/, agents/, … (remotes github.com/subactor/<name>)Edit and commit here (or in an equivalent clone of the same remote)
Deploy pinplatform/components/<name>/Git submodules of those remotes — not vendors, not generated mirrors, not independent copies
Runtime build contextplatform/docker-compose.ymldockerfile: components/...Images are built from the submodule pin, not from umbrella sibling checkouts

platform/components/* are recorded in platform/.gitmodules. Docker Compose and Dockerfiles under platform/ always reference components/….

Edit rule

  1. Change code in the component repository (umbrella core/ / connectors/ / … or the submodule working tree — same remote).
  2. Push the component commit to origin.
  3. Update the platform submodule pointer (git -C platform add components/<name> + commit) so deploy matches.
  4. Do not maintain long-lived divergent patches only in one checkout.

Umbrella siblings (/home/tom/github/subactor/core) and submodule checkouts (platform/components/core) may both exist for convenience. Content for service trees should match; tooling-only files (.koru, .planfile, local koru.yaml) may differ and are ignored by drift checks.

What runs in production / local compose

ConcernCanonical edit locationWhat compose runs
Control / LLM routes (llm.mjs, *-sync-intent.mjs)coreplatform/components/core (pinned)
Connectors / Plesk bridgeconnectorsplatform/components/connectors (pinned)
Intent pack dataplatform/config/intent-packs/Mounted as /app/config (platform-owned)

Intent pack JSON lives only under platform/config/ (assembly SSOT). Resolvers that consume packs live in component code (core, optionally agents adapters).

Drift detection

# from platform/
node scripts/check-component-drift.mjs          # core + connectors (default gate)
node scripts/check-component-drift.mjs --all    # every submodule
make check-component-drift

The script:

SHA inequality alone is a warning (parallel commits with identical trees are possible); file content drift is the hard failure.

Default scope is core + connectors (LLM routes + bridge). --all also reports known historical drift in other components (e.g. agents phrase files present only in the umbrella sibling) without blocking the default gate until those are reconciled.

Out of scope