Skip to content

Commit c236c8e

Browse files
brabojclaude
andauthored
docs(decisions): what stays upstream, and what each fork carries (#1919) (#1939)
ADR-050 records the v3.0 boundary: upstream keeps rules that hold for any team and asks the governance questions; forks carry the answers, the workflow, the stacks and platforms. Git policy splits into history safety upstream and naming and release form in forks; decision records stay upstream. Supersedes ADR-005. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 99afa65 commit c236c8e

4 files changed

Lines changed: 178 additions & 3 deletions

File tree

‎docs/decisions/005-base-reorganization.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
id: "005"
3-
status: Accepted
4-
date: 2026-05-04
3+
status: Superseded
4+
date: 2026-10-16
55
category: templates
66
supersedes: []
7-
superseded_by: []
7+
superseded_by: ["050"]
88
---
99

1010
# ADR-005: Apply Miller's law to repository structure
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
id: "050"
3+
status: Accepted
4+
date: 2026-10-16
5+
category: composition
6+
supersedes: ["005"]
7+
superseded_by: []
8+
---
9+
10+
# ADR-050: What stays upstream, and what each fork carries
11+
12+
## Context
13+
14+
The fork model leaves one question open: which template, and which part of
15+
a template, stays upstream. An audit of every core and workflow section,
16+
measured on 2026-09-03 (#1480), found:
17+
18+
| Verdict | Share of the core and workflow bytes |
19+
| ------- | ------------------------------------ |
20+
| Policy that holds for any team | 38.4 % |
21+
| One team's process | 49.3 % |
22+
| Stack or platform content | 11.1 % |
23+
| Language content | 1.1 % |
24+
25+
The forces:
26+
27+
- Different teams: teams run trunk-based, gitflow, review-required or solo
28+
models. Upstream's answers to how work flows make the file wrong for every
29+
team that works otherwise.
30+
- Mixed files: `git.md`, `docs.md` and `quality-gates.md` hold policy and
31+
process side by side, so a whole-file split cannot separate them.
32+
- Layout: `templates/base/` no longer says who owns what, now that backend
33+
and frontend are abstractions too (#1504).
34+
- Stable references: forks and projects extend upstream sections by ID, so
35+
a move that renames an ID breaks them.
36+
37+
## Decision
38+
39+
Upstream keeps the rules that hold whatever a team's stack, platform or way
40+
of working, and asks the questions a project must answer about how it works;
41+
every answer to those questions moves to forks.
42+
43+
## Rationale
44+
45+
- The waist test from the audit decides each rule by one question, so the
46+
boundary does not rest on taste.
47+
- A team's governance is right for that team only; asking the question keeps
48+
upstream right for all of them, and each fork supplies its own answer.
49+
- History-safety rules in git hold for every team; branch prefixes and title
50+
forms are one team's choice.
51+
- Recording decisions is documentation practice any team benefits from; only
52+
a project's categories are its own.
53+
54+
## Design
55+
56+
![Upstream keeps the engine, shared policy, idioms as checks and the questions; each fork carries stacks, platforms, workflow, process and the answers; git.md, docs.md and quality-gates.md split between the two](../diagrams/template-boundary.png)
57+
58+
| # | Rule | In practice |
59+
| - | ---- | ----------- |
60+
| 1 | The waist test | A rule stays upstream only if changing the stack, the platform or the team's way of working would not change it |
61+
| 2 | Engine upstream | The manifest schema, IDs, EXTEND and OVERRIDE, the resolver, `tools/`, `tests/`, and a fixture stack and platform as test input |
62+
| 3 | Shared policy upstream | `core/`: config, oop, quality, testing, readme, the review checklists, and `agents.md` as the output contract; `security/`, `data/`, `infra/`, `backend/` and `frontend/` |
63+
| 4 | Language idioms as checks | Each idiom becomes the language-specific check beside its generic rule in `core/`, and `language/` leaves upstream (#1926) |
64+
| 5 | Governance asks, forks answer | Upstream asks who approves a change, how work is tracked and what a release is, and answers none of them. Labels, milestones, merge and review policy, the journal, wrap-up and the release cut move to forks |
65+
| 6 | Git splits | Upstream keeps never force-push, never rebase a pushed branch, one concern per pull request, committer identity, submodules, off-limits paths and `.gitignore`. Branch prefixes, commit and title form, squash policy, versioning and the release process move |
66+
| 7 | Decision records stay upstream | The ADR threshold, the record layout, the immutability rules and the schema and layout checks; a fork sets only its categories and the record its layout binds from |
67+
| 8 | Workflow moves | All of `workflow/` moves, `release.md` included. From `quality-gates.md`, how a check is built stays; when gates run moves: the three-layer gate model, thresholds and periodic audits |
68+
| 9 | Ends move | `stack/`, `platform/`, `INTERVIEW.md`, `examples/`, `generated/`, `backend/templating.md`, the `language/` Tooling sections, `go.md`, `c.md`, and `core/` cli, skills and examples |
69+
| 10 | Concern directories | Upstream drops `base/`: `core/`, `security/`, `data/` and `infra/` sit beside `backend/` and `frontend/` under `templates/` (#1504) |
70+
| 11 | IDs never change | A file or section keeps its ID when it moves or splits, so every EXTEND and OVERRIDE still resolves; a split file's moved sections go to a fork-owned file |
71+
| 12 | The audit is the starting list | Each section not named above is placed by rule 1; the audit's per-section verdicts are the starting list, checked against the test as the path move lands (#1480) |
72+
73+
| Rule | Promise or mechanism | Enforced by |
74+
| ---- | -------------------- | ----------- |
75+
| 1, 12 | Mechanism | Review of the path-move pull request (#1504) |
76+
| 2, 3, 6, 7 | Promise to projects and forks | Review of the split commit; the ownership check then keeps forks from editing these keys (#1923) |
77+
| 4 | Promise to projects | The idioms fold (#1926) |
78+
| 5, 8, 9 | Promise to forks | The split commit and the migration guide (#1292) |
79+
| 10, 11 | Promise to projects and forks | The path move: every root resolves the same ordered ID list before and after (#1504) |
80+
81+
### The questions upstream asks
82+
83+
Upstream ships each question with no answer, and a generated context file
84+
leaves it for the project or its fork to fill in:
85+
86+
| Question | An answer a fork might give |
87+
| -------- | --------------------------- |
88+
| Who approves a change? | One approving review from a code owner |
89+
| How is work tracked? | GitHub issues, one type and one priority label each |
90+
| What is a release? | A SemVer tag cut from `main` per milestone |
91+
92+
## Alternatives considered
93+
94+
| Alternative | Why not |
95+
| ----------- | ------- |
96+
| Keep the 2026-09-12 map, with the release rules and gate model upstream | The release cut and the gate schedule are one team's answers, and they would keep the file wrong for teams that work otherwise. |
97+
| Keep governance upstream and let forks OVERRIDE it | Every fork inherits answers it must find and undo, and a missed one silently governs its projects. |
98+
| Move the whole git policy to forks | The history-safety rules hold for every team, and a project with no fork would lose them. |
99+
| Move decision records to forks | Every fork would rebuild the same threshold, layout and check. |
100+
| Split by whole file | Three files mix policy and process, so either half would land on the wrong side. |
101+
102+
## Consequences
103+
104+
| Consequence | Effect |
105+
| ----------- | ------ |
106+
| Path move | Moves the concern directories out of `base/` with IDs unchanged (#1504) |
107+
| Split commit | Removes rules 5, 8 and 9's content upstream and adds the question skeleton |
108+
| Fork files | Imbra's fork receives the moved sections in fork-owned files, under their old IDs |
109+
| `frontend-content` extraction | Unaffected: `frontend/` stays upstream, so the extraction stays an upstream task (#492) |
110+
| The audit | Closes on this record (#1480) |
111+
112+
## Compatibility
113+
114+
- Until v3.0 nothing changes, and `v2.90.0` stays the pin.
115+
- From v3.0, every upstream path under `base/` moves. A reference or hybrid
116+
context file, or a vendored copy, that names an old path must be updated;
117+
the migration guide maps each old path to its new one (#1292).
118+
- IDs do not change, so a project's EXTEND and OVERRIDE directives resolve
119+
without edits, provided its chain still reaches the section, upstream or
120+
in its fork.
121+
- A project that consumes upstream alone loses the process rules: labels,
122+
journal, wrap-up and release cut. It answers the questions itself or takes
123+
a fork that does.
124+
125+
## Security
126+
127+
- `security/` stays upstream whole, and no security rule moves to a fork.
128+
- The history-safety rules stay upstream, so every chain still forbids
129+
force-pushing and rebasing a pushed branch.
130+
- Review policy moves to forks. A project with neither a fork nor its own
131+
answer has no stated rule for who approves a change; the question upstream
132+
asks is the only prompt that it is missing.
133+
- No credentials or secrets are involved.
134+
135+
## Related
136+
137+
- ADR-005 - the `base/` layout this record supersedes.
138+
- ADR-049 - the fork model this record completes.
139+
- solid-ai-dev/solid-ai-templates#1480 - the audit and its waist test.
140+
- solid-ai-dev/solid-ai-templates#1504 - the path move.

0 commit comments

Comments
 (0)