Skip to content

Commit ffa4e01

Browse files
hotlongclaude
andauthored
docs(adr),chore(devx): tombstone ADR-0001 — retire the number, empty the citation allowlist (#7866) (#7960)
ADR-0001 sat on the weaker of two remedies: an `UNRESOLVED_ADR_CITATIONS` entry in `check-adr-anchors.mjs`, which says "this citation resolves to nothing, and that is knowingly tolerated". The gate's own prose prefers a tombstone record, and since #6676 there is a working template for one. This lands that upgrade, and with it the allowlist becomes empty. Both halves are in one commit because the gate refuses either order: * tombstone first, entry kept -> red, "the UNRESOLVED_ADR_CITATIONS entry for 0001 is stale — docs/adr/ now HAS a record" * entry removed, no tombstone -> red, "ADR-0001 is cited by 3 file(s) but names no record under docs/adr/" Both measured on this branch before writing the final state. The record that held the number was `0001-metadata-service-architecture.md`, merged 2026-02-10 (`908d95c82`) and deleted 2026-02-11 (`9da8e3e72`). The deletion was NOT a withdrawal on the merits, which is the substantive difference from ADR-0107: it was collateral in a 37-path documentation sweep that removed the whole `docs/adr/` registry, README and all, under a subject about permission-protocol analysis, with an empty body and no mention of any ADR. The tombstone reconstructs that from the tree rather than quoting a withdrawal that was never written. The record must not be resurrected either way: its selected option was a hybrid dual-provider architecture in which ObjectQL registers `metadata` as a fallback, and the code has since gone single-provider — the one `registerService('metadata', ...)` in the tree is in `packages/metadata/src/plugin.ts`, while `packages/objectql/src/plugin.ts` registers `objectql`, `data`, `manifest` and `lifecycle` only. Corrects a claim the removed allowlist entry carried. It said the number was "cited as history by ADR-0002". ADR-0002 does cite `ADR-0001`, but for "one global DB + tenant column ... already discarded in v3.4's ADR-0001" — a tenancy decision, not the metadata-service one this number held, and not a document that ever existed in this repository. Verified against full history with the clone unshallowed: nothing matching `*0001-*` was ever added under any path, on any branch, other than the record above. The tombstone dissects the discrepancy; ADR-0002's own wording is left alone, being an accepted record. `--self-test` gains the live-tree pin the card asks for, mirroring #7838's 0107 pin: 0001 must land in both `records` (citations resolve) and `nonDecisions` (anchors refused). Pinned by name for 0001 and 0107, plus a structural sweep so a future `NNNN-withdrawn-*.md` inherits the rule without editing the gate, and a non-empty guard so that sweep cannot pass by reading nothing. 70 -> 74 assertions. Co-authored-by: Claude <noreply@anthropic.com>
1 parent fc71b84 commit ffa4e01

2 files changed

Lines changed: 248 additions & 49 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# ADR-0001: Withdrawn — this number is retired and must not be reused
2+
3+
**Status**: **Withdrawn (2026-02-11)**. This file is a *tombstone*, not a decision: nothing in it is in force, and the number must never be reassigned.
4+
**Deciders**: ObjectStack Protocol Architects (recorded retroactively — see [How this differs from ADR-0107](#how-this-differs-from-adr-0107))
5+
**The record that held this number**: *"Metadata Service Architecture"*`docs/adr/0001-metadata-service-architecture.md`, Status *Accepted (2026-02-10)*
6+
**Landed by**: `908d95c82`, 2026-02-10 09:14 UTC
7+
**Deleted by**: `9da8e3e72`, 2026-02-11 23:35 +0800, about thirty hours later — a 37-path documentation sweep, not an ADR decision
8+
**Tracking**: [#7329](https://github.com/objectstack-ai/objectstack/issues/7329) (the citation-resolution work that named this case), [#7866](https://github.com/objectstack-ai/objectstack/issues/7866) (this tombstone), [#6634](https://github.com/objectstack-ai/objectstack/issues/6634) (the squat failure mode both are written against)
9+
**Consumers**: none. No code is governed by this number, and none may be — see [Do not anchor to this number](#do-not-anchor-to-this-number).
10+
11+
---
12+
13+
## TL;DR
14+
15+
A real record occupied ADR-0001 on `main` for about thirty hours in February 2026 and
16+
was then deleted. Unlike [ADR-0107](./0107-withdrawn-hook-body-write-set-static-gap.md),
17+
it was **not withdrawn on the merits** — it was swept away as collateral in a bulk
18+
documentation cleanup that took the entire `docs/adr/` registry with it, including its
19+
`README.md` and the ADR-0002 of that era.
20+
21+
This file exists so the number resolves to that explanation instead of to nothing, and so
22+
it is never handed to an unrelated decision. Reassigning it would retroactively re-point
23+
every historical "ADR-0001" at a document its author never meant — the squat failure mode
24+
[#6634](https://github.com/objectstack-ai/objectstack/issues/6634) was filed for, where
25+
one number had silently accumulated 77 citations it did not resolve.
26+
27+
**A new record takes the next free number. Not this one.**
28+
29+
## What happened
30+
31+
| When | What | Evidence |
32+
|---|---|---|
33+
| 2026-02-10 09:14 UTC | `docs/adr/0001-metadata-service-architecture.md` written and merged, Status *Accepted*, authored by an automated agent | `908d95c82` |
34+
| 2026-02-11 23:35 +0800 | Deleted, together with `docs/adr/0002-database-driven-metadata-storage.md` and `docs/adr/README.md`, inside a 37-path docs sweep | `9da8e3e72` |
35+
| 2026-08-08 | The bare number is grandfathered onto `check-adr-anchors`'s citation allowlist, pending this tombstone | [#6634](https://github.com/objectstack-ai/objectstack/issues/6634) |
36+
| 2026-08-11 | [PR #7838](https://github.com/objectstack-ai/objectstack/pull/7838) makes a tombstone refuse *anchors* while still resolving *citations*, and leaves this number open because it needs a file under `docs/adr/` | [#7329](https://github.com/objectstack-ai/objectstack/issues/7329) |
37+
38+
The deleting commit's subject is *"feat(docs): add comprehensive analysis of Permission
39+
Protocol with AI-enhanced security controls and RLS implementation"*; its body is empty
40+
and it names no ADR. Alongside the registry it removed the whole `docs/METADATA_*`
41+
documentation family and the `examples/metadata-objectql` package. **No reasoning for
42+
retiring the decision was recorded anywhere**, which is the substantive difference from
43+
ADR-0107 and the reason this tombstone reconstructs the record from the tree rather than
44+
quoting a withdrawal.
45+
46+
## Do not resurrect it
47+
48+
Independently of how it was deleted, the record's substance is now **contradicted by
49+
shipped code**, so restoring the text would plant a false statement in the decision log.
50+
51+
Its selected option was a **hybrid dual-provider** architecture: *both* `@objectstack/objectql`
52+
and `@objectstack/metadata` may provide the `metadata` service, MetadataPlugin taking
53+
precedence when loaded and **ObjectQL registering itself as the fallback provider** when
54+
it is not. That fallback is exactly what the code stopped doing:
55+
56+
- **MetadataPlugin is the sole provider** of the `metadata` service — the one
57+
`registerService('metadata', …)` in the tree is
58+
[`packages/metadata/src/plugin.ts`](../../packages/metadata/src/plugin.ts).
59+
- **ObjectQL is a consumer, never a provider.**
60+
[`packages/objectql/src/plugin.ts`](../../packages/objectql/src/plugin.ts) registers
61+
`objectql`, `data`, `manifest` and `lifecycle` — and no longer `metadata`. It reads the
62+
`metadata` service and degrades to its own internal registry when none is present,
63+
which is not the same thing as claiming the slot.
64+
- **The shared-interface principle survived, as a spec contract**: `IMetadataService` in
65+
[`packages/spec/src/contracts/metadata-service.ts`](../../packages/spec/src/contracts/metadata-service.ts).
66+
67+
The live account of that surface is the "Metadata service architecture" section of
68+
[`ARCHITECTURE.md`](../../ARCHITECTURE.md). Read that, never this file, for what is true
69+
today. The withdrawn text is recoverable in full at
70+
`git show 908d95c82:docs/adr/0001-metadata-service-architecture.md` and is deliberately
71+
kept in history rather than reprinted here — a withdrawn record reprinted inside its own
72+
tombstone reads as a record.
73+
74+
Note that the single-provider architecture which replaced it **has no ADR record of its
75+
own**. That gap is real and is not closed by this file; re-homing it is a maintainer call.
76+
77+
## What ADR-0002 actually cites
78+
79+
Recorded because it is the first thing a reader arriving from ADR-0002 will want, and
80+
because it was mis-stated in `check-adr-anchors.mjs` until this tombstone was written.
81+
82+
[`0002-environment-database-isolation.md`](./0002-environment-database-isolation.md) says,
83+
of a rejected alternative: *"One global DB + tenant column. Was never on the table —
84+
already discarded in v3.4's ADR-0001."* That is **not** a reference to the record above.
85+
The record that held this number decided how the `metadata` *service* is registered and
86+
says nothing about tenancy or database topology.
87+
88+
Two distinct things carry the string "ADR-0001" in this repository's past, and only one
89+
of them was ever a file here:
90+
91+
- **The v3.4-era "ADR-0001" ADR-0002 is pointing at.** Nothing matching `*0001-*` was ever
92+
added under any path, on any branch, other than the metadata-service record — see
93+
[Archaeology](#archaeology). Today's ADR-0002 is itself dated 2026-04-19 and supersedes
94+
the v3.4/v4.0 per-organization database model, so its "v3.4's ADR-0001" is a reference to
95+
a pre-registry document that this repository has never contained.
96+
- **`docs/adr/0001-metadata-service-architecture.md`**, the record this tombstone retires.
97+
98+
The citation is therefore historical narration rather than a pointer into `docs/adr/`, and
99+
this file is what it now resolves to. Correcting ADR-0002's wording is an edit to an
100+
accepted record and is deliberately not made here.
101+
102+
## Do not anchor to this number
103+
104+
`scripts/check-adr-anchors.mjs` requires every `ADR-NNNN` cited in a tracked file to name a
105+
record under `docs/adr/`. This tombstone satisfies that check — deliberately, because the
106+
citations below are legitimate references to a deleted record. It is **not** a licence to
107+
cite ADR-0001 as governing anything: an anchor entry must state the invariant its ADR
108+
decided, and this number decides nothing today.
109+
110+
The citations that exist are all discussion of the deletion itself:
111+
112+
- [`ARCHITECTURE.md`](../../ARCHITECTURE.md) — names the deleted path as plain text and
113+
states the current single-provider architecture in its place;
114+
- [`0002-environment-database-isolation.md`](./0002-environment-database-isolation.md)
115+
the v3.4 reference dissected above;
116+
- `scripts/check-adr-anchors.mjs` — the gate, describing this case.
117+
118+
## Archaeology
119+
120+
Recorded so the next reader does not repeat it. Run against full history with the clone
121+
**unshallowed** — a shallow clone silently answers "never existed", and the default clone
122+
in this project's agent containers is 50 commits deep:
123+
124+
```bash
125+
git fetch --unshallow
126+
git log --all --diff-filter=AD -- 'docs/adr/0001*' # -> exactly 2 commits, both above
127+
git log --all --diff-filter=AD -- '*0001-*' # -> the same 2 commits, any path
128+
git log --all --oneline -S'ADR-0001' # -> 10 commits, all accounted for
129+
```
130+
131+
**Nothing else ever claimed this number**, on any branch, at any time: the second query
132+
widens the first from `docs/adr/` to the whole tree and returns the same two commits, so
133+
there is no second era of "ADR-0001" as a file and no lost content beyond the record named
134+
above.
135+
136+
## How this differs from ADR-0107
137+
138+
Both are tombstones and both are unreusable, but the two cases are not the same and the
139+
distinction is worth keeping:
140+
141+
| | ADR-0107 | ADR-0001 |
142+
|---|---|---|
143+
| Why it left | Owner decision, reasoning stated in the withdrawing commit | Collateral in an unrelated 37-path docs sweep; no reasoning recorded |
144+
| Lifetime | Nine hours | About thirty hours |
145+
| Deciders line | The withdrawal was itself the decision | Reconstructed from the tree in 2026-08; nobody decided the number should retire at the time |
146+
| Why not resurrect | Substance reversed by later shipped code | Same — the fallback-provider half is contradicted by the code today |
147+
148+
The shared conclusion is the one that matters: an ADR number that has ever named a record
149+
does not become free again by that record's removal, however the removal happened.

0 commit comments

Comments
 (0)