Record module-boundary rule: root module vs. nested modules #2

Closed
opened 2026-10-23 15:59:37 -07:00 by end · 1 comment
Owner

Decision to record

The repository is one root module today, so a plain vX.Y.Z tag versions every package at once and also publishes a docs binary release. That is intended: one version stream, one changelog per tag. Pre-1.0 breaking changes ride minor bumps, and module graph pruning keeps consumers from compiling dependencies of packages they don't import.

The expensive operation is carving a package out into its own nested module after it has shipped inside the root module. The package then exists in two modules, which takes coordinated releases to resolve and can produce "ambiguous import" errors for consumers on older root versions. Creating a module nested from its first commit is free.

Rule

  • Root module, plain v* tags: lifecycle, lifecycle/cli, migrate, page, cmd/docs. These are light-dependency, core pieces.
  • Nested module from the first commit, prefixed tags (gql/v0.1.0): gql, connect, and any future package that brings heavy dependencies (gqlgen, protobuf, …) or is likely to need independent versioning.
  • cmd/docs stays in the root module, so release.yml's v* trigger and goreleaser only ever release the root-module CLI. Prefixed library tags never publish binaries.

Action

Once corestack/go has been scaffolded from corestack/standards and before work on page, gql or connect starts, record this as an ADR (docs new adr) and reference it from AGENTS.md, so implementation agents apply it without being told.

## Decision to record The repository is one root module today, so a plain `vX.Y.Z` tag versions every package at once and also publishes a `docs` binary release. That is intended: one version stream, one changelog per tag. Pre-1.0 breaking changes ride minor bumps, and module graph pruning keeps consumers from compiling dependencies of packages they don't import. The expensive operation is **carving a package out into its own nested module after it has shipped inside the root module**. The package then exists in two modules, which takes coordinated releases to resolve and can produce "ambiguous import" errors for consumers on older root versions. Creating a module nested from its first commit is free. ## Rule - **Root module, plain `v*` tags:** `lifecycle`, `lifecycle/cli`, `migrate`, `page`, `cmd/docs`. These are light-dependency, core pieces. - **Nested module from the first commit, prefixed tags (`gql/v0.1.0`):** `gql`, `connect`, and any future package that brings heavy dependencies (gqlgen, protobuf, …) or is likely to need independent versioning. - `cmd/docs` stays in the root module, so `release.yml`'s `v*` trigger and goreleaser only ever release the root-module CLI. Prefixed library tags never publish binaries. ## Action Once corestack/go has been scaffolded from corestack/standards and before work on `page`, `gql` or `connect` starts, record this as an ADR (`docs new adr`) and reference it from AGENTS.md, so implementation agents apply it without being told.
Author
Owner

Carried over from the review of #3 (adopt Corestack project standards): fix this in the same PR as this ADR.

AGENTS.md:33 still reads:

Dependencies are limited to go.yaml.in/yaml/v3 and github.com/yuin/goldmark.

That was true while the repo only held the docs checker. Left in place, it would block (or be silently broken by) the page and migrate work, which needs Bob and Goose.

Replace it with a pointer to this ADR. Suggested wording: "Add dependencies only to the module that needs them; heavy dependencies go in nested modules (see the module-boundary ADR)." This must land before work on page, gql, connect or migrate starts.

Carried over from the review of #3 (adopt Corestack project standards): fix this in the same PR as this ADR. `AGENTS.md:33` still reads: > Dependencies are limited to `go.yaml.in/yaml/v3` and `github.com/yuin/goldmark`. That was true while the repo only held the docs checker. Left in place, it would block (or be silently broken by) the `page` and `migrate` work, which needs Bob and Goose. Replace it with a pointer to this ADR. Suggested wording: "Add dependencies only to the module that needs them; heavy dependencies go in nested modules (see the module-boundary ADR)." This must land before work on `page`, `gql`, `connect` or `migrate` starts.
end closed this issue 2026-10-26 21:45:07 -07:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: corestack/go#2