diff --git a/.changeset/7175-downstream-consumer-census.md b/.changeset/7175-downstream-consumer-census.md
new file mode 100644
index 0000000000..329ae19621
--- /dev/null
+++ b/.changeset/7175-downstream-consumer-census.md
@@ -0,0 +1,16 @@
+---
+---
+
+Docs-only: records the downstream-consumer census for
+`@object-ui/plugin-detail`'s `PointInTimeRestore` as
+`docs/audits/2026-09-plugin-detail-downstream-consumer-census.md` (objectui#7175).
+
+objectui#7163 measured that the component has zero *in-repo* consumers. That is not the
+same statement as zero consumers, because it is barrel-exported public API, so this audit
+reads the downstream populations instead: `hotcrm` measured at `a6be39a3d` (zero on every
+spelling, against a positive control of 104 `plugin-detail` node references in the same
+repo on the same instrument), and `cloud` reported as **NOT MEASURED** — refused on three
+independent channels, two of them beside a live control.
+
+No source, behaviour, or public-surface change; the audit records evidence so the
+ADR-0049 enforce-or-remove question can be decided later. It deliberately retires nothing.
diff --git a/docs/audits/2026-09-plugin-detail-downstream-consumer-census.md b/docs/audits/2026-09-plugin-detail-downstream-consumer-census.md
new file mode 100644
index 0000000000..e6f9973762
--- /dev/null
+++ b/docs/audits/2026-09-plugin-detail-downstream-consumer-census.md
@@ -0,0 +1,194 @@
+# Audit: downstream consumer census — `PointInTimeRestore` and the `plugin-detail` barrel (2026-09)
+
+**Question** (objectui#7175): does anything *outside this repo* render
+`@object-ui/plugin-detail`'s `PointInTimeRestore`?
+
+**Why it exists**: objectui#7163 / PR #7172 measured that `PointInTimeRestore` has **zero
+in-repo consumers** — barrel-exported only, no mount point anywhere in `objectui`. That
+measurement was correct but it is *not* the question ADR-0049 enforce-or-remove needs
+answered, because **"zero in-repo consumers" is not "zero consumers."** The component is
+published public API; a downstream application may render it. This audit takes the
+reading the in-repo one could not.
+
+**Populations**: `objectstack-ai/hotcrm`, `objectstack-ai/cloud`.
+
+⛔ **This audit does not retire anything.** Retiring a published component is
+ADR-0049 / ADR-0087 (objectstack) and narrows public surface. This is the measurement that
+makes that decision *possible*, not the decision.
+
+---
+
+## Summary
+
+| Population | Channel | Positive control | `PointInTimeRestore` | Verdict |
+| --- | --- | --- | --- | --- |
+| `objectui` (in-repo, re-confirmed) | local worktree @ `899730e0a` | `RecordComments` mounted 2x in `DetailView.tsx` | 0 mounts | unrendered here (confirms #7163) |
+| `hotcrm` @ `a6be39a3d` | anonymous shallow git clone | **HIT** — 104 `plugin-detail` node references | **0 on every spelling** | **zero — measured** |
+| `cloud` | none reachable | n/a | n/a | ⚠️ **NOT MEASURED** |
+
+**Headline**: no measured consumer, anywhere, renders `PointInTimeRestore` — and in
+`hotcrm` it is not merely absent, it is **structurally unreachable** (see below). One
+population, `cloud`, could not be read at all and is reported as its own category.
+
+⚠️ **NOT MEASURED is not zero and not green.** `cloud` is unread, not clean.
+
+---
+
+## Channel evidence
+
+Each clone's exit code was captured **before any pipe**, beside a same-shape control.
+
+| Command | Exit | Reading |
+| --- | --- | --- |
+| `git clone --depth 1 .../hotcrm.git` | **0** | 828 tracked files at `a6be39a3d` |
+| `git clone --depth 1 .../objectui.git` (control) | **0** | 6039 tracked files at `899730e0a` |
+| `git clone --depth 1 .../cloud.git` | **128** | `could not read Username` — auth wall |
+| `git ls-remote .../cloud.git` | **128** | same wall, second command shape |
+| `git ls-remote .../hotcrm.git` (control) | **0** | refs listed |
+| session repo-attach for `cloud` | error | `you don't have access to objectstack-ai/cloud` |
+
+`cloud` was refused on **three independent channels**, two of which returned a live
+control in the same breath. It is unreadable from this seat, not empty.
+
+---
+
+## The reachability argument — stronger than the grep
+
+`hotcrm` is a **metadata application**. It declares UI as JSON-ish metadata rendered by
+objectui; it does **not** import objectui as a library:
+
+- `@object-ui/*` appears in exactly **3** `hotcrm` files, and all three are **prose
+ comments** (`crm.app.ts:169`, `account_detail.page.ts:32`,
+ `scripts/analytics-reconcile/macros.ts:5`).
+- Real imports of any `@object-ui` package: **0**. `hotcrm`'s `package.json` depends on
+ `@objectstack/*` only.
+
+So the only channel by which `hotcrm` can reach an objectui component is a **registered
+component type string** in metadata. And:
+
+> `PointInTimeRestore` is **never** passed to `ComponentRegistry.register`. `plugin-detail`
+> makes 16 registrations; none of them is this component. There is no auto-registration —
+> no `Object.entries(...)`/`forEach(register)` pattern exists in the barrel (0 hits).
+
+⇒ `PointInTimeRestore` **has no type string**, so a metadata app cannot name it. The zero
+below is therefore not a lucky grep; it is what the architecture requires.
+
+---
+
+## The `hotcrm` reading
+
+**Positive control — same repo, same instrument, same channel** (`plugin-detail`
+components that `hotcrm` actually mounts):
+
+| Node type | References in `hotcrm` |
+| --- | --- |
+| `record:details` | 31 |
+| `record:related_list` | 21 |
+| `record:highlights` | 17 |
+| `record:activity` | 16 |
+| `record:path` | 12 |
+| `record:chatter` | 4 |
+| `record:history` | 3 |
+| **total** | **104** |
+
+The instrument resolves 104 references to *this very package* in *this very repo*. It is
+productive here, so a zero from it is a reading.
+
+**Target — every spelling, all zero:**
+
+| Spelling probed | Hits in `hotcrm` | Same probe in `objectui` (control) |
+| --- | --- | --- |
+| `point[-_ ]?in[-_ ]?time[-_ ]?restore`, case-insensitive | **0** | 26 |
+| `PointInTimeRestore` exact identifier | **0** | 26 |
+| `PointInTimeRestoreProps` | **0** | 3 |
+| `RevisionEntry` (the co-exported type) | **0** | 5 |
+| loose `point[-_ ]?in[-_ ]?time` | **0** | 30 |
+| `import(...PointInTime...)` lazy form | **0** | 0 |
+| `plugin-detail` package specifier | **0** | 870 |
+
+The separator/case-insensitive pattern covers named import, namespace member, re-export,
+kebab (`point-in-time-restore`), snake (`point_in_time_restore`) and camel spellings in
+one shot. **The identical pattern set returns 26 hits in `objectui`** — the probes fire.
+
+**Every semantic near-miss attributed.** One hit for `snapshot.*restore`:
+`test/forecast-manual-override.test.ts:279` — *"deleting the manual row restores automated
+snapshotting"*. Forecast snapshots, unrelated to revision history. Not a render.
+
+Non-zero hits for sibling *identifiers* (`DetailSection` 4, `CommentInput` 3, and so on)
+were each read: all are prose comments, test docstrings, or `@objectstack/spec/ui` type
+names such as `RecordRelatedListProps`. Since `hotcrm` has zero objectui imports, none can
+be a render.
+
+---
+
+## Bonus: `PointInTimeRestore` is not an isolate
+
+Once the instrument answers "is X reachable", it answers it for X's siblings for free. Of
+`plugin-detail`'s **29** component-shaped barrel exports, **7** are neither registered
+(no metadata type string) nor mounted anywhere in this repo:
+
+| Unregistered **and** unmounted | Registered? | In-repo mounts |
+| --- | --- | --- |
+| `CommentInput` | no | 0 |
+| `DiffView` | no | 0 |
+| `InlineCreateRelated` | no | 0 |
+| `MentionAutocomplete` | no | 0 |
+| **`PointInTimeRestore`** | no | 0 |
+| `RecordNavigationEnhanced` | no | 0 |
+| `RelationshipGraph` | no | 0 |
+
+None of the seven has a dynamic reference either (`React.lazy`, `createElement`, or a
+string literal of its own name): 0 for all seven.
+
+⇒ `PointInTimeRestore` is the **visible instance of a seven-member class**, not a one-off.
+That is the difference between one retirement card and an enforce-or-remove ledger. This
+audit does not act on the other six; it records them.
+
+⚠️ Unmounted is **not** the same as unreachable-and-dead. `RecordComments` is also
+unregistered, yet `DetailView` mounts it directly at `:1479` and `:1705` — a component can
+be perfectly live through a sibling's JSX without ever having a type string. The class
+above is specifically *both* doors closed.
+
+---
+
+## Method — re-runnable, and its one recorded failure
+
+Deliberately **not committed as a test**: it clones external repositories, so it cannot
+run in CI, and a committed test that cannot run renders as coverage while measuring
+nothing (objectui#7183). It is recorded here instead, to be re-run by hand.
+
+```bash
+git clone --depth 1 https://github.com/objectstack-ai/hotcrm.git /tmp/hotcrm # exit BEFORE any pipe
+# controls first, target second; every count printed as an integer, never blank
+grep -rIF --exclude-dir=.git 'record:details' /tmp/hotcrm | wc -l # expect > 0
+grep -rIE --exclude-dir=.git -i 'point[-_ ]?in[-_ ]?time[-_ ]?restore' /tmp/hotcrm | wc -l
+```
+
+⚠️ **Two instrument traps, both hit during this audit.**
+
+1. `git grep -c` prints **nothing**, not `0`, on no match. Every count above is piped
+ through `wc -l` so a zero is always a printed integer.
+2. The in-repo mount probe first used `]` and reported **0 mounts for
+ `RecordComments`** — a component known to be mounted twice. Cause: grep is
+ line-oriented and these JSX tags end the line (`])`, which returns the expected 2. **The whole sibling table was
+ re-derived after the fix and gated on that control passing.** A probe that cannot see
+ its own known-positive is not measuring.
+
+Counts are from `main` at audit time — a baseline, not a frozen census.
+
+---
+
+## What this audit does NOT claim
+
+- ⛔ Not that `PointInTimeRestore` should be retired. That is ADR-0049 / ADR-0087, it
+ narrows public surface, and it is a decision this audit only makes *possible*.
+- ⛔ Not that `cloud` is clean. `cloud` is **unread**.
+- ⛔ Not that the other six unmounted exports are dead. They are unmounted and
+ unregistered *here*; they have had no downstream census of their own.
+- ⛔ Not that PR #7172's i18n sweep was wrong. It was reviewed and upheld.
+
+Refs: objectui#7175 (this census) · objectui#7163 / PR #7172 (the in-repo measurement and
+the sweep) · objectui#7183 (why this is not a committed test) · objectstack ADR-0049,
+ADR-0087.