From d9954a55d19c987ebc7bb1a57620a8a21140fa24 Mon Sep 17 00:00:00 2001 From: os-warren Date: Sun, 6 Sep 2026 08:42:54 +0000 Subject: [PATCH 1/3] =?UTF-8?q?docs(adr):=20ADR-0133=20=E2=80=94=20organiz?= =?UTF-8?q?ation=20management=20open=20basics,=20mirroring=20cloud=20ADR-0?= =?UTF-8?q?081=20D1/D3/D4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records, in the repository whose code enforces them, the open-mechanism half of cloud ADR-0081 (Accepted 2026-07-09): D1 teammate-add stays open and always goes through better-auth invitations, D3 the in-shell surface is the organization record page reached by a templated nav deep-link, D4 control-plane roster reads are organization-scoped. Decides nothing. D2, the non-goals and the commercial consequences stay in cloud and are cited as `cloud ADR-0081`. Where a local record already decides a point it is cited rather than duplicated: ADR-0093 (membership lifecycle, D9's active- organization resolution), ADR-0105 D12 (the multi-org entitlement anchor), and ADR-0131 D1/D7/D9 (total organization ownership), whose C6 census (#15207) — not this file — answers whether sys_member keeps its organization column. Every code anchor was re-located on origin/main at 77781151d and is written as a symbol anchor, since check:adr-symbol-anchors makes a line number a hard finding. The objectui rendering half is cited as a cross-repo anchor and is explicitly not claimed as this repository's contract. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y --- docs/adr/0133-org-management-open-basics.md | 267 ++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 docs/adr/0133-org-management-open-basics.md diff --git a/docs/adr/0133-org-management-open-basics.md b/docs/adr/0133-org-management-open-basics.md new file mode 100644 index 0000000000..51db9a6092 --- /dev/null +++ b/docs/adr/0133-org-management-open-basics.md @@ -0,0 +1,267 @@ +# ADR-0133: Organization management — the open basics; a mirror of cloud ADR-0081 D1/D3/D4 in the repository whose code enforces them + +- **Status**: Proposed (2026-09-06) — awaiting the maintainer's hand-merge, which is the acceptance act for a governed surface (Prime Directive #14). ⛔ Nothing in this file is a new decision; see [Provenance](#provenance--read-this-before-citing-this-file). +- **Mirrors**: `objectstack-ai/cloud` **ADR-0081** (Status: Accepted, founder-decided in session, 2026-07-09) — **D1, D3 and D4 only**, the half whose mechanism is open code in this repository. +- **Deliberately not mirrored**: cloud ADR-0081 **D2**, its non-goals, and its commercial consequences. Those govern a packaging choice, stay in cloud, and are cited as `cloud ADR-0081` — never restated here. See [Relationship to the D2 reversal](#relationship-to-the-d2-reversal-16215). +- **Cross-checked against** (cite, do not duplicate): [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md) (tenancy mode; the membership lifecycle; D9 already anchors the active-organization resolution), [ADR-0105](./0105-group-tenancy-posture-and-first-class-org-scope.md) (group tenancy posture; D12 anchors the multi-org entitlement), [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) (total organization ownership; D1/D7/D9) +- **Filed by**: [#14508](https://github.com/objectstack-ai/objectstack/issues/14508), a sub-issue of [#14496](https://github.com/objectstack-ai/objectstack/issues/14496) (maintainer ruling 2026-09-02, option 2: mirror the open half, do not move files) +- **Consumers**: `@objectstack/platform-objects` (the identity surface and the Setup navigation contributions), `@objectstack/plugin-auth` (better-auth's organization plugin and the default-organization bootstrap), `@objectstack/spec` (the public auth-feature roster), and the objectui console that renders the surface + +--- + +## Provenance — read this before citing this file + +**The decisions restated below were taken in the sibling `objectstack-ai/cloud` +repository, as cloud ADR-0081, on 2026-07-09.** They were founder-decided in +session and accepted there. This file decides nothing. It is a mirror, written +on 2026-09-06 from the cloud record plus the code in this repository that +implements it. + +Three facts make that disclosure load-bearing rather than decorative: + +1. **Only the mechanism half is here.** Cloud ADR-0081 covers both what the + platform does and what a subscription buys. A decision about commercial + packaging belongs in the commercial repository; a decision about open code + belongs where the code is (Prime Directive #13). This file therefore carries + **D1, D3 and D4** and stops. Where this document and the cloud record + disagree, **the cloud record is the decision and this file is the bug** — + file an issue and this file gets corrected. + +2. ⚠️ **`ADR-0081` written bare resolves to the wrong document in this + repository.** This repo's [ADR-0081](./0081-trusted-react-page-tier.md) is + the trusted `kind:'react'` page tier, an unrelated record whose Decision + section is not even D-numbered. Every reference to the organization- + management record must be spelled `cloud ADR-0081`. This is the third local + record to say so — ADR-0093 D9 and ADR-0105's citation note say it for the + labels `ADR-0081 D1` and `ADR-0081 D2` respectively — and it is repeated + here because this file is the one a reader following those citations now + lands on. + +3. **The code still carries the pre-repo labels.** Several files in + `packages/platform-objects` and `packages/plugins/plugin-auth` cite + `ADR-0081 D1` in comments today. Re-pointing those citations is + [#14361](https://github.com/objectstack-ai/objectstack/issues/14361)'s work + and is ⛔ **not** done by the change that lands this file — so until that + card lands, a reader may arrive here from a citation that names a different + number. + +**What is restated vs. what is measured.** Every clause under +[Decision](#decision) is either a restatement of the cloud record or a fact +measured on this repository's `origin/main` at `77781151d` and cited by symbol +anchor. Where the two disagree, or where the cloud record is silent about +something this repo's code decides, it is recorded under +[What this record does not decide](#what-this-record-does-not-decide) rather +than resolved. + +--- + +## Relationship to the D2 reversal (#16215) + +**A separate local record — "The multi-organization runtime is open core" — +reverses cloud ADR-0081 D2.** It is open as a draft PR +([#16215](https://github.com/objectstack-ai/objectstack/pull/16215)) and is not +yet on `main`. + +⛔ **It is referenced here by PR number and never by its ADR number, and that is +a gate requirement rather than a style choice.** `pnpm check:adr-anchors` fails +any citation of an ADR number that names no record under `docs/adr/`: an +unmerged number is a squat, and every citation of it is retroactively falsified +if the record lands under a different number. A PR reference cannot rot that +way. **When #16215 merges, its number becomes citable and this file should be +updated to use it** — that edit is cheap, mechanical, and owed to whichever of +the two records lands second. + +The division of labour between the two records is exact and neither restates +the other: + +| cloud ADR-0081 | who carries it locally | +|---|---| +| **D1** — the "add a teammate" basics stay open | **this record** | +| **D2** — the multi-organization machinery is enterprise | the record proposed in **#16215**, which reverses it. ⛔ Not re-derived, restated or evaluated here | +| **D3** — the in-shell organization surface | **this record** | +| **D4** — org-scoped roster reads | **this record** | +| the non-goals and the commercial consequences | stay in cloud, cited as `cloud ADR-0081` | + +⚠️ **A note for the hand-merge, stated rather than decided.** #16215's record +says in its own "What this record does not decide" section that D1/D3/D4 "are +mirrored into this repository by #14508", and asks that writer to cite its +decisions rather than open a *competing* record — which this file does: it +decides nothing that record decides. A later comment on #14508 goes further and +proposes folding D1/D3/D4 into that file instead of writing a second one. That +option was not available to this change: the file does not exist on `main`, so +"extending" it would mean building on an unmerged governed PR and coupling two +hand-merges into one. **If the maintainer prefers one combined record, that is a +merge-time call** — the two files are disjoint, so folding them is a move, not a +rewrite. + +--- + +## Context + +The open framework has always shipped member-management basics: better-auth's +organization plugin mounted in `plugin-auth`, the organization and invitation +objects in `platform-objects`, and the Setup surface over them. What was +enterprise was the *multi-organization runtime*, not the ability to add a +colleague to the organization you already have. + +That boundary is easy to get wrong in exactly one direction — quietly treating +"organization" as an enterprise word and gating a basic affordance on the +multi-org service. Cloud ADR-0081 D1 is the decision that forbids it, and the +code says so at each gate: the invite affordance is gated on the org +**capability**, never on multi-org. This record exists so that gate has a local +number to cite. + +--- + +## Decision + +⛔ **Nothing here is decided by this file.** The D-numbers are cloud ADR-0081's +own, deliberately **not** renumbered: a mirror that renumbers is a mirror a +reader cannot check against its original. D2 is absent for the reason given +above, so the sequence reads D1, D3, D4. + +### D1 — Adding a teammate is open, and always goes through better-auth invitations + +Basic member management is not an entitlement. The better-auth organization +plugin is mounted unconditionally +(`packages/plugins/plugin-auth/src/auth-schema-config.ts#buildOrganizationPluginSchema`), +and single-organization deployments get a Default Organization from the +bootstrap helper +(`packages/plugins/plugin-auth/src/ensure-default-organization.ts#ensureDefaultOrganization`, +`#isDefaultOrganizationBootstrapTrigger`) so that the endpoint's active-organization +resolution has something to resolve. + +Two consequences this repository enforces: + +- **The gate is the organization capability, never multi-org.** The invite + action declares `requiresFeature: 'organization'` + (`packages/platform-objects/src/identity/sys-user.object.ts#requiresFeature`), + and the spec's public roster keeps the two features apart: the member-management + inputs sit under the organization capability while organization *lifecycle* + actions sit under `packages/spec/src/kernel/public-auth-features.ts#multiOrgEnabled` + (`#gatedInputs`). ADR-0093 D8 already records that this split is deliberate; + it is cited, not re-argued. +- **Every add flows through an invitation.** There is no bespoke user-CRUD path + into membership. `invite_user` targets better-auth's invite-member endpoint and + is declared on three objects, so it is reachable from wherever an admin + happens to be looking: + `packages/platform-objects/src/identity/sys-user.object.ts#invite_user`, + `packages/platform-objects/src/identity/sys-invitation.object.ts#invite_user`, + and `packages/platform-objects/src/identity/sys-member.object.ts#invite_user`. + The three copies are held equal to each other — not to hand-copied literals — + by `packages/platform-objects/src/identity/invite-entry-toolbar.test.ts#INVITE_ENDPOINT` + and `#OBJECTS_BY_NAME`. + +⚠️ Membership rows are **read-only over the API**: `sys_member` declares +`packages/platform-objects/src/identity/sys-member.object.ts#apiMethods` as reads +only, and writes are owned by better-auth behind the identity write guard +(ADR-0092 D2). "Open" here means *the affordance is not gated*, not *the table +is writable*. + +### D3 — The in-shell surface is the organization RECORD page, reached by a templated nav deep-link + +What **this repository declares** is a navigation contribution: an `object`-typed +Setup entry naming `sys_organization` with a templated `recordId` of +`{current_org_id}`, in the People & Org group +(`packages/platform-objects/src/apps/setup-nav.contributions.ts#nav_organization`). +Its siblings — `#nav_teams`, `#nav_invitations` — carry **no** service gate, while +the organization *list* keeps one (`#nav_organizations`, `requiresService: 'org-scoping'`): +browsing organizations is meaningful only when more than one can exist. That +asymmetry is D1 expressed in navigation. + +**The rendering half is objectui's, and this repository does not enforce it.** +The console pinned by `.objectui-sha` substitutes the token and, when it cannot +resolve, falls through to the list view rather than emitting a dead link +(`objectui:packages/layout/src/NavigationRenderer.tsx#applyNavTemplate`, +`#NavTemplateContext`, `#resolveHref`); related-list toolbars are bridged in +declaration order by +`objectui:packages/app-shell/src/views/RelatedRecordActionsBridge.tsx#deriveActions`. +Those are objectui's behaviours, cited here so a reader can find them — ⛔ this +record does not make them contracts of this repository, and a change to them is +not a violation of this record. + +⚠️ **The tab set and its ordering are NOT declared by this repository, and this +record does not decide them.** See +[What this record does not decide](#what-this-record-does-not-decide). + +### D4 — Control-plane roster reads are organization-scoped + +`sys_member` is organization-scoped: it carries +`packages/platform-objects/src/identity/sys-member.object.ts#organization_id` as a +lookup to `sys_organization`, is uniquely indexed on the organization/user pair +(`#indexes`), and pairs that column with `#user_id` and `#role`. The +organization-capability gate on the identity surface is the same one D1 names. + +⛔ **This record does not restate what "org-scoped" now means — ADR-0131 owns it.** +Since cloud ADR-0081 was accepted, [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) +(merged 2026-09-04) decided organization ownership for every row in the system, +and it supersedes any reading of D4 as an opt-in property: + +- **D1/D9** — a row with an organization column was written by an organization, + the column is `NOT NULL`, and a missing stamp is a refused write in every + posture. Org-scoping is the default; the exception is a table with **no** + column. +- **D7** — whether a given object *keeps* the column at all is a **writer-facts** + question decided per object by the C7 inventory, not by the object's name. + +⚠️ Consequently, **whether `sys_member` keeps its column is not decided here.** +Today the field is declared optional and its own comment describes a null +organization under single-tenancy — a reading ADR-0131 D1 does not permit going +forward. That reconciliation belongs to ADR-0131's C6 census +([#15207](https://github.com/objectstack-ai/objectstack/issues/15207)), and this +record cites it rather than pre-empting it, exactly as it cites ADR-0093 rather +than restating the membership lifecycle. + +--- + +## What this record does not decide + +This section is the honest residue: places where the cloud record is silent, or +where this repository's code and its own comments do not agree. ⛔ None of it is +resolved here. + +1. ⭐ **"Opens on tab-0 Members" is asserted in this repository's comments but + declared by none of its metadata.** Two source comments and a QA checklist + item describe the organization record page as opening on a Members tab with + Invitations and Teams beside it. Measured on `origin/main` at `77781151d`, + **no object in `packages/platform-objects/src/identity/` declares the + `relatedList` prominence key** (`packages/spec/src/data/field.zod.ts#relatedList`) + — the key objectui reads to promote a child list to its own tab — and no + `relatedLayout` override exists anywhere in this repository. Under the + documented default, with no primary list declared, related lists collapse + into a single stacked tab. So the tab ordering is either an emergent property + of the renderer or a claim that has gone stale; **this record states the + deep-link contract, which is declared, and does not assert a tab order, which + is not.** Filed separately rather than repaired here. + +2. **Whether `sys_member` keeps `organization_id`** — ADR-0131 D7's writer-facts + question, answered by the C6 census (#15207). See D4. + +3. **The reconciliation of the optional column with ADR-0131 D1.** The field is + declared optional today and ADR-0131 D1 says no nullable tenant column exists + anywhere. That is a migration question on ADR-0131's own v18 line (its D10 + and D14), not a mirror's to settle. + +4. **What an enterprise subscription buys, and where the multi-organization + machinery lives.** Cloud ADR-0081 D2 and the record proposed in #16215, + respectively. ⛔ Not evaluated here. + +--- + +## Consequences + +**Good.** The three local records that already carry pieces of this decision — +ADR-0093 D9, ADR-0105 D12, ADR-0131 D1/D7/D9 — stop being the only local anchors +for a decision none of them owns. A reader who follows an `ADR-0081 D1` citation +out of the identity surface can now be sent somewhere that answers, which is the +precondition for #14361's re-pointing work. + +**Costs, stated plainly.** One decision is now recorded in two repositories, and +mirrors drift: this file has to be corrected when cloud ADR-0081 changes, and +nothing mechanical will notice. The mitigation is the Provenance section's +precedence rule (the cloud record decides) rather than a gate. The cloud record +also owes a one-line pointer back to this number; that edit belongs to the cloud +repository and is not made by the change that lands this file. + +**Reversibility.** Total — this file decides nothing, so deleting it costs only +the citations that point at it. From d2c2579b032d93ceb4df1f8358ba9cd227c44345 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 06:37:59 +0000 Subject: [PATCH 2/3] docs(adr): ADR-0133 cites the landed ADR-0132 for the D2 reversal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The record that reverses cloud ADR-0081 D2 has landed on `main` as ADR-0132, so this file's account of it is stale: it described that record as an open draft PR, cited it by PR number because an unmerged ADR number was a squat, and still said D2's packaging decision "stays in cloud". - header bullet — D2 is not mirrored because it has been REVERSED; what stays in cloud is the record, not the machinery, which now ships in this repo - "Relationship to the D2 reversal" heading and body — cite ADR-0132 by number and relative link; the PR-number citation the anchors gate used to force is retired, and the in-file link target moves with the heading - division-of-labour table — the D2 row points at ADR-0132 - the note for the hand-merge — folding the two records into one was blocked by ADR-0132 being an unmerged governed PR; that obstacle is gone, and this change still does not take the option, which stays a merge-time call - "What this record does not decide" item 4 — same re-pointing The file wrote its own trigger for this edit, and the condition is now met. Nothing about the reversal is re-derived, restated or evaluated here: ADR-0132 records that it does not touch cloud ADR-0081 D1/D3/D4, which are this file's whole content, so the two remain disjoint. `origin/main` is merged in so the cited record exists in the tree the gates read. Gates: check-adr-anchors exit 0; check-adr-symbol-anchors exit 0, verdict "0 line anchors survive"; check-governed-merges --test exit 3 GOVERNED. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y --- docs/adr/0133-org-management-open-basics.md | 58 +++++++++++---------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/docs/adr/0133-org-management-open-basics.md b/docs/adr/0133-org-management-open-basics.md index 51db9a6092..13fedf9eaf 100644 --- a/docs/adr/0133-org-management-open-basics.md +++ b/docs/adr/0133-org-management-open-basics.md @@ -2,7 +2,7 @@ - **Status**: Proposed (2026-09-06) — awaiting the maintainer's hand-merge, which is the acceptance act for a governed surface (Prime Directive #14). ⛔ Nothing in this file is a new decision; see [Provenance](#provenance--read-this-before-citing-this-file). - **Mirrors**: `objectstack-ai/cloud` **ADR-0081** (Status: Accepted, founder-decided in session, 2026-07-09) — **D1, D3 and D4 only**, the half whose mechanism is open code in this repository. -- **Deliberately not mirrored**: cloud ADR-0081 **D2**, its non-goals, and its commercial consequences. Those govern a packaging choice, stay in cloud, and are cited as `cloud ADR-0081` — never restated here. See [Relationship to the D2 reversal](#relationship-to-the-d2-reversal-16215). +- **Deliberately not mirrored**: cloud ADR-0081 **D2**, its non-goals, and its commercial consequences — cited as `cloud ADR-0081`, never restated here. ⚠️ D2 is absent for a stronger reason than the other two: it has been **reversed** by [ADR-0132](./0132-multi-organization-runtime-is-open-core.md), and the multi-organization machinery it packaged now ships in this repository (`packages/plugins/organizations`). What stays in cloud is that *record* — together with the non-goals and the commercial consequences, which the reversal leaves untouched. See [Relationship to the D2 reversal](#relationship-to-the-d2-reversal-adr-0132). - **Cross-checked against** (cite, do not duplicate): [ADR-0093](./0093-tenancy-mode-and-membership-lifecycle.md) (tenancy mode; the membership lifecycle; D9 already anchors the active-organization resolution), [ADR-0105](./0105-group-tenancy-posture-and-first-class-org-scope.md) (group tenancy posture; D12 anchors the multi-org entitlement), [ADR-0131](./0131-total-organization-ownership-no-null-organization-id.md) (total organization ownership; D1/D7/D9) - **Filed by**: [#14508](https://github.com/objectstack-ai/objectstack/issues/14508), a sub-issue of [#14496](https://github.com/objectstack-ai/objectstack/issues/14496) (maintainer ruling 2026-09-02, option 2: mirror the open half, do not move files) - **Consumers**: `@objectstack/platform-objects` (the identity surface and the Setup navigation contributions), `@objectstack/plugin-auth` (better-auth's organization plugin and the default-organization bootstrap), `@objectstack/spec` (the public auth-feature roster), and the objectui console that renders the surface @@ -55,21 +55,21 @@ than resolved. --- -## Relationship to the D2 reversal (#16215) +## Relationship to the D2 reversal (ADR-0132) **A separate local record — "The multi-organization runtime is open core" — -reverses cloud ADR-0081 D2.** It is open as a draft PR -([#16215](https://github.com/objectstack-ai/objectstack/pull/16215)) and is not -yet on `main`. - -⛔ **It is referenced here by PR number and never by its ADR number, and that is -a gate requirement rather than a style choice.** `pnpm check:adr-anchors` fails -any citation of an ADR number that names no record under `docs/adr/`: an -unmerged number is a squat, and every citation of it is retroactively falsified -if the record lands under a different number. A PR reference cannot rot that -way. **When #16215 merges, its number becomes citable and this file should be -updated to use it** — that edit is cheap, mechanical, and owed to whichever of -the two records lands second. +reverses cloud ADR-0081 D2.** It is +[ADR-0132](./0132-multi-organization-runtime-is-open-core.md), and it is **on +`main`** (landed 2026-09-07): a record, not a proposal. + +⛔ **It is cited here by ADR number and relative link, and nothing about that +reversal is re-derived, restated or evaluated below.** This file previously +cited it by PR number, which was a gate requirement rather than a style choice: +`pnpm check:adr-anchors` fails any citation of an ADR number that names no +record under `docs/adr/`, so while the record was unmerged its number was a +squat and a citation of it would have been retroactively falsified had it landed +under a different number. That constraint is discharged — the number resolves, +so it is the citable form and the PR reference is retired from this file. The division of labour between the two records is exact and neither restates the other: @@ -77,22 +77,23 @@ the other: | cloud ADR-0081 | who carries it locally | |---|---| | **D1** — the "add a teammate" basics stay open | **this record** | -| **D2** — the multi-organization machinery is enterprise | the record proposed in **#16215**, which reverses it. ⛔ Not re-derived, restated or evaluated here | +| **D2** — the multi-organization machinery is enterprise | **reversed** by [ADR-0132](./0132-multi-organization-runtime-is-open-core.md), which is on `main`. ⛔ Not re-derived, restated or evaluated here | | **D3** — the in-shell organization surface | **this record** | | **D4** — org-scoped roster reads | **this record** | | the non-goals and the commercial consequences | stay in cloud, cited as `cloud ADR-0081` | -⚠️ **A note for the hand-merge, stated rather than decided.** #16215's record -says in its own "What this record does not decide" section that D1/D3/D4 "are -mirrored into this repository by #14508", and asks that writer to cite its -decisions rather than open a *competing* record — which this file does: it -decides nothing that record decides. A later comment on #14508 goes further and -proposes folding D1/D3/D4 into that file instead of writing a second one. That -option was not available to this change: the file does not exist on `main`, so -"extending" it would mean building on an unmerged governed PR and coupling two -hand-merges into one. **If the maintainer prefers one combined record, that is a -merge-time call** — the two files are disjoint, so folding them is a move, not a -rewrite. +⚠️ **A note for the hand-merge, stated rather than decided.** ADR-0132 says in +its own "What this record does not decide" section that D1/D3/D4 "are mirrored +into this repository by #14508", and asks that writer to cite its decisions +rather than open a *competing* record — which this file does: it decides nothing +that record decides. A later comment on #14508 goes further and proposes folding +D1/D3/D4 into that file instead of writing a second one. When this file was +drafted that option was not available: ADR-0132 did not exist on `main`, so +"extending" it would have meant building on an unmerged governed PR and coupling +two hand-merges into one. That obstacle is gone — the record has landed — so the +choice now stands on its merits alone. This change does not take it. **If the +maintainer prefers one combined record, that is still a merge-time call** — the +two files are disjoint, so folding them is a move, not a rewrite. --- @@ -243,8 +244,9 @@ resolved here. and D14), not a mirror's to settle. 4. **What an enterprise subscription buys, and where the multi-organization - machinery lives.** Cloud ADR-0081 D2 and the record proposed in #16215, - respectively. ⛔ Not evaluated here. + machinery lives.** Cloud ADR-0081 D2 and + [ADR-0132](./0132-multi-organization-runtime-is-open-core.md), respectively. + ⛔ Not evaluated here. --- From 01b450d40c57a5758dee95163068e802e1e85314 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 06:55:10 +0000 Subject: [PATCH 3/3] docs(adr): name the obstacle to folding that survived ADR-0132's merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hand-merge note said the only thing blocking a single combined record was ADR-0132 being unmerged, and that with it landed the choice "stands on its merits alone". True, but it leaves the reader to rediscover the merit that matters: that record carries its own D1 through D6, which are different decisions from cloud ADR-0081's D1/D3/D4, so folding this mirror into it puts two unrelated D1s in one document — exactly the property the deliberately unrenumbered mirror exists to keep checkable. Stated, not decided: the disposition is still the maintainer's merge-time call, and this change takes the option neither way. Gates re-run on this tree: check-adr-anchors exit 0, check-adr-symbol-anchors exit 0 with "0 line anchors survive", check-adr-links exit 0, check-nul-bytes exit 0, check-doc-authoring exit 0, check-governed-merges --test exit 3 GOVERNED. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y --- docs/adr/0133-org-management-open-basics.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/adr/0133-org-management-open-basics.md b/docs/adr/0133-org-management-open-basics.md index 13fedf9eaf..0f4ae268e6 100644 --- a/docs/adr/0133-org-management-open-basics.md +++ b/docs/adr/0133-org-management-open-basics.md @@ -91,9 +91,13 @@ D1/D3/D4 into that file instead of writing a second one. When this file was drafted that option was not available: ADR-0132 did not exist on `main`, so "extending" it would have meant building on an unmerged governed PR and coupling two hand-merges into one. That obstacle is gone — the record has landed — so the -choice now stands on its merits alone. This change does not take it. **If the -maintainer prefers one combined record, that is still a merge-time call** — the -two files are disjoint, so folding them is a move, not a rewrite. +choice now stands on its merits alone. ⚠️ One of those merits is structural and +survived the merge: that record carries **its own D1 through D6**, which are +different decisions from cloud ADR-0081's D1/D3/D4, so folding this file into it +would put two unrelated `D1`s in one document — the property the unrenumbered +mirror above exists to keep checkable. This change takes the option neither way. +**If the maintainer prefers one combined record, that is still a merge-time +call** — the two files are disjoint, so folding them is a move, not a rewrite. ---