You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 51dcab8
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: scripts/docs-audit/README.md
+72-4Lines changed: 72 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,7 +48,7 @@ Three anchor kinds, each exact:
48
48
49
49
| anchor | what it is | how it is derived |
50
50
|:--|:--|:--|
51
-
|`symbol`| a documentable declaration the diff touched | the top-level declaration, or a member of a top-level **container** (class / interface / type / enum / schema object), enclosing each changed line — on **both** sides of the diff, so a removed export still anchors the pages naming it |
51
+
|`symbol`| a documentable declaration the diff touched | the top-level declaration, or a member of a top-level **container** (class / interface / type / enum / schema object), enclosing each changed line — on **both** sides of the diff, so a removed export still anchors the pages naming it. A member that is a **data property** is additionally qualified by its declaring container against the authorable surface (see below)|
52
52
|`route`| a wire path the change touched | a path literal on a changed line, plus every route whose **registrar handler** references a changed symbol |
53
53
|`sdk`| the client method bound to an anchor route | the declared `route` ⟷ `client` rows in the repo's route ledgers |
54
54
@@ -104,12 +104,80 @@ maintainer's decision of 2026-08-31 took this (option C) and ruled OUT filtering
104
104
rows. A false positive costs a reader a minute; a false negative ships a falsified page.
105
105
So no guard, no threshold and no bridge hop reads `from` — `--self-test` pins that the
106
106
provenance key set is exactly the anchor set, in both directions, so a future change
107
-
cannot start deciding with it without going red. Container-qualified *discrimination*
108
-
lives on #13712 (the spec half) and #13713 (the docs-audit half), and needs a TS-name →
109
-
spec-name mapping this does not have.
107
+
cannot start deciding with it without going red. Container-qualified *discrimination* is
108
+
the separate, later step below (option D), and it decides from the declarations directly,
109
+
never by parsing this clause back out.
110
+
111
+
### A data property is qualified by its declaring container (#13713)
112
+
113
+
Option D of the same ruling, and the half that *does* move rows. It landed once the spec
114
+
side (#13712) published the mapping it needs: `packages/spec/declaration-map/*.json` maps a
115
+
**TS declaration name** to a **spec type name** (`ObjectSchemaBase` → `data/Object`), and
116
+
the authorable surface is keyed as `container:property` (`data/Object:userActions`). All of
117
+
it is generated and covered by `check:generated`; this script only ever reads it, and ⛔
118
+
never carries a local mapping table of its own — a container the map lacks is a spec-lane
119
+
card, not a local fix.
120
+
121
+
⚠️ The authorable surface is read as the **union** of `packages/spec/authorable-surface/`
122
+
(the live per-category ratchet, read as one set) and
123
+
`packages/spec/authorable-surface.base.json` (the artifact #12824 names). The second is an
124
+
**anchor**, pinned at a fixed `baseRev` for the deletion gate — measured on this tree it
125
+
lagged the ratchet by 532 keys, including `data/Object:editMode` and every key of
126
+
`security/OrgScopingEntitlement` and `api/ProvenanceWaiver`. Reading the anchor alone would
127
+
suppress anchors on genuinely authorable keys, and that class grows with every key added
128
+
after `baseRev`. A union can only ever keep an anchor one source vouches for, never drop
129
+
one more. `[RETIRED]` is stripped for the same reason: a tombstoned key still rejects with
130
+
an upgrade prescription, so it is still surface a page documents.
131
+
132
+
For a data property `prop` (`name:` / `name?:` / `name =`) whose most specific enclosing
133
+
declaration is the container `C`:
134
+
135
+
||`C` resolves to |`C:prop` authorable | verdict |
136
+
|:--|:--|:--|:--|
137
+
| (a) |`cat/T`| yes |**mint** — today's behaviour, now justified. The row also says so: `a field of const object ObjectSchemaBase, an authorable key of data/Object`|
138
+
| (b) |`cat/T`| no |**drop** the property anchor and fall through to the container branch that already existed — no new fallback |
139
+
| (c) | nothing, or two different types | — |**mint, unchanged**|
140
+
141
+
⛔ **(c) must never become "drop".** That is option **B** (blanket prefer-container) by
142
+
another name, and it is vetoed on two rounds of measurement: its "zero recall loss" was
143
+
measured against a ground truth of 10 of 46 pages, most of which were never in this tool's
144
+
corpus at all (the real recall is 48.8%, re-derived), and the rows it drops are the most
145
+
valuable ones the tool mints. **Fail toward noise, never toward silence.** A method, a
146
+
nested interface, a namespaced type — anything whose winning declaration is not a data
147
+
property — is outside the rule entirely.
148
+
149
+
Two consequences worth stating plainly, because both are easy to mistake for bugs:
150
+
151
+
-**Both ruled true positives survive, and they survive by different routes.**
152
+
`userActions` is a key of `ObjectSchemaBase`, which the map carries, so it is kept by
153
+
(a) — `data-modeling/objects.mdx` is still listed and the row now names the spec key.
154
+
`schemaMode` is declared on `DatasourceDef`, an **objectql-local** interface the
155
+
generated map does **not** carry, so it is kept by (c) — the unmapped keep, not the
156
+
authorable lookup. `--self-test` pins that absence as a fact rather than papering over
157
+
it; the day the map carries `DatasourceDef`, `data/Datasource:schemaMode` is already an
158
+
authorable key and the row survives via (a) instead.
159
+
-**The realised reduction is far smaller than the −17.4% the projection quoted**, and for
160
+
the same reason: the projection hand-classified the 20 dropping containers, and 18 of
161
+
them are internal implementation types (`MetaOverlayCacheKey`, `LocalizationCacheEntry`,
162
+
`AUTH_MODEL_TO_PROTOCOL`, …) that the generated map does not carry either. Under the
163
+
ruled rule those are case (c) and they **keep**. Only containers the map resolves can
164
+
drop. Widening the drop set to reach the projected number would be option B; the number
165
+
moves when the *map's coverage* grows, which is spec-lane work.
166
+
167
+
Every drop is published in `containerQualifiedDrops`, naming the property, its container
168
+
and the spec key that failed to be authorable — the same discipline as the two guards
169
+
below. A deliberate false negative that no field names is one no reviewer can audit.
170
+
171
+
If either artifact is unreadable (this script runs in contexts where `packages/spec` may be
172
+
absent) every container reads as unmapped, the run behaves exactly as it did before this
173
+
existed, and one note goes to stderr. `--self-test` pins that degradation too.
110
174
111
175
### Two guards, and both publish what they removed
112
176
177
+
(Three narrowings publish now — the container qualification above reports
178
+
`containerQualifiedDrops` on the same terms. These two are the ones that run over the
179
+
whole anchor set, in every kind, after it is derived.)
180
+
113
181
The first build of this derivation was, on some PRs, *noisier* than the proxy it replaced
114
182
(134 rows where the old tool gave 26). Two guards fixed that, and both run **before** the
115
183
route bridge — a name left in the set does not merely add a noisy row, it mints noisy route
0 commit comments