Commit eea8787
feat(spec)!: retire the flattened view overlay's owner and hidden keys (ADR-0049) (#20286)
Fixes #20230
Clause-②: no (narrowing)
## What this does
Retires the flattened view overlay's `owner` and `hidden` keys under
ADR-0049 enforce-or-remove. Triage direction on the card (comment
5856621469), verbatim: 「follow #20085's disposition for the same key
pair」. PR #20227 retired the same pair on the view item record; this PR
retires it on the other door, with the same prescription texts.
The overlay door is the lean `PUT /api/v1/meta/view/:name` body with no
`config`: members 3 and 4 of the `view` union
(`VIEW_METADATA_MEMBERS.listOverlay` / `.formOverlay`), built from
`flattenedViewOverlayFields()` in `packages/spec/src/ui/view.zod.ts`. It
declared both keys, the write door accepted them, and `saveMetaItem`
stored them verbatim. Nothing read either one. After this PR, every door
that parses an overlay refuses both keys with the prescription. A stored
overlay row that holds either one is stripped on read:
- a row with other view keys is valid again and re-saves;
- a hide-only row (`{ object, viewKind, hidden: true }`) is left
identity-only, which the door refuses. It is badged invalid, refused on
a whole-row re-save, and reported `failed` by `os migrate meta --stored
--apply` until it is deleted or given the setting its author meant.
The D2 docblock, the D3 entry and the changeset all state this, and it
is pinned.
## Stop valve: the writer census, taken first
Taken before any edit, each reading with a lit control on the same ref.
No real writer was found, so the retirement proceeds.
| where | ref | writers of overlay `owner` / `hidden` | lit control |
|---|---|---|---|
| objectui at the `.objectui-sha` pin | `f8a9d0fb` | 0. All 12 view
write call sites were read one by one (the `persistViewPatch` toolbar
path, `updateView` / `updateViewConfig` / `createView` in the data
adapter, `viewEnvelope` saves, and the two `PublicFormsPage` saves).
None writes either key. The toolbar's overlay keys are
`VIEW_OVERLAY_OWNED_KEYS` = `rowHeight`, `sort`, `hiddenFields`,
`columnState`, `inlineEdit`. The switcher writes `label` and `isPinned`.
| 8 `persistViewPatch` call sites writing the owned keys; 2 `updateView`
row-key writes |
| objectui `main` | `6cf5999` | 0 (same 12 call sites, same reading) | 7
`persistViewPatch` call sites; 2 row-key writes |
| objectstack `packages/**`, `examples/**` | `e46218674` | 0. Examples
author no `viewKind` at all, and no view-level `hidden` / `owner` in 10
view files. No framework source writes an overlay body with either key.
| `label:` 88 times in the same 10 example view files |
| HotCRM | `2f7b2326` (= its remote `main`) | 0. No view write call, and
no view-level `hidden` / `owner` in 14 view files. | `label:` 159 times
in those files |
| cloud | not reachable | NOT MEASURED. REST read answered 403 and
`add_repo` was refused for this session. #20227's census at cloud
`48d70663` recorded no code writer, and one test double that pins a lean
`{hidden:true}` PUT as accepted. That is a test fixture, not a writer.
It goes red on cloud's next spec bump only if it parses through the spec
schema. | — |
Readers, re-checked: `.hidden` / `.owner` reads on a view in
`rest-server.ts` = 0/0 and in `metadata-manager.ts` = 0/0. The 5
`.hidden` reads in `metadata-protocol/src/protocol.ts` are all
field-level. Control: `.order` is read 2 / 1 / 2 times in the same three
files.
## Dispatch assumptions, measured
1. The two keys were at `view.zod.ts:5284-5285` on `e46218674`, and
`flattenedViewOverlayFields(kind)` takes a `kind` argument. **Held.**
Only those two keys move.
2. The `retiredKey()` tombstone applies. **Held.** Both overlay members
`.strip()`, and a `z.never()` member refuses loudly instead of
stripping: the pins below assert issue code `invalid_type` at path
`[key]`, carrying the prescription.
3. A D2 conversion is owed. **Held, and the view-item entry does not
cover it.** `view-item-owner-hidden-removed` skips any body without a
`config` dict, and its own fixture pinned an overlay's `hidden: true` as
kept. This PR adds a separate entry, disjoint by `config`.
4. Other `view.zod.ts` regions were not touched: no edit in
`FormViewSchema.layout`, `ViewMetadataParsed` or `diagnoseViewMetadata`.
## The route
- **Tombstones.** `owner: retiredKey(VIEW_ITEM_OWNER_RETIRED)` and
`hidden: retiredKey(VIEW_ITEM_HIDDEN_RETIRED)` in
`flattenedViewOverlayFields()`. These are the view item's own constants,
so both doors answer with the same text, as the order asked. A pin
asserts the overlay's issue message is byte-equal to the view item's.
- **D2 `view-overlay-owner-hidden-removed`** (`toMajor: 18`,
`retiredFromLoadPath: true`, lossless `stripKeys`). Scope: the flattened
spelling, meaning a body with no `config` and no container slot. It
walks `views` (stack sources, and every stored row, which
`convertStoredItem` replays before serving or badging) and `viewItems`
(the assembled channel). It does NOT require `viewKind`: a flat row
stored before the #7741 binding has none until the write path heals it
in, and then the save would refuse the key it still held. It is wired
into `MIGRATIONS_BY_MAJOR[18]`, and the step rationale is extended.
- **Why the D2 matters at runtime, and what it cannot do.** objectui's
`updateView` is a read-merge-write, and `buildPersistedViewBody`
re-sends a saved view whole. A stored row served WITH `hidden` would
make the next toolbar toggle a 422, so the read path strips first.
- For a content-bearing row, that is the whole story.
- For a hide-only row, the strip leaves identity only, and the door
refuses that (the identity precondition: only identity fields). The
badge turns invalid, a whole-row re-save or a rename (`label` is
identity) answers 422, and `--apply` reports `failed` and leaves the row
as stored. A toggle that adds a real key saves.
- Remedy: delete the row, or add the setting its author meant.
- **D3 `view-overlay-owner-hidden-retired`** (ruling B on #17152). It
names its conversion by id in `reason`, which is the shape #20255's
census pin reads. That pin is now live on `main` and green here. Its
`acceptanceCriteria` state both classes, the hide-only row included. The
view item's pair is a separate family with its own D2 and its own D3
(`18.view-item-owner-hidden-retired.ts`, from #20255). This PR corrects
that entry's one stale sentence (amendment `5859181450`).
- **`RETIRED_KEYS_BY_MAJOR[18]`**: `ui/ViewMetadata:owner` and
`ui/ViewMetadata:hidden`. The overlay members are not exported.
`ui/ViewMetadata` is the exported door they are reached through, and it
is listed in `unemitted-schemas.baseline.json`, so these rows are
declared, not judged. The retirement test pins them.
- **No liveness row.** The `view` ledger walks the container keys only
(`name`, `label`, `object`, `list`, `form`, `listViews`, `formViews`),
so a row would be an ORPHAN. `check:liveness` is green without one.
- **Generated artefacts.** `check:generated`: all 15 were current, and
there was nothing to regenerate. The four surface ratchets are
byte-identical, which is expected on this route: the def is unemitted.
`spec-changes.json` and the upgrade guide project up to protocol 17, so
no major-18 entry shows there either (the same reading as PR #20227).
- **Forms / examples / skills / docs.** No form offers either key. There
are zero authorings in `examples/`, `skills/` and `content/docs/`. The
tree-scoped pin below holds that.
- **Changeset.** `@objectstack/spec: minor`, `**BREAKING**`, FROM → TO,
the one-line fix, `Clause-②: no (narrowing)`, ADR-0087 disposition
`registered view-overlay-owner-hidden-removed,
view-overlay-owner-hidden-retired`.
## Pins
The new file is
`packages/spec/src/ui/view-overlay-owner-hidden-retirement.test.ts`
(in-package, local project):
- Both overlay members refuse each key at its path: `invalid_type`, the
path, and the prescription. The `view` door
(`getMetadataTypeSchema('view')`) refuses with `invalid_union`, the
prescription surfaces as the union's message, and the claimed member
locates the key. The assembled channel refuses too.
- CONTROL: the same overlays without the keys pass every door, with
`isDefault` / `order` / `scope` intact and no key grown. The view item
door refuses the pair as well, so the family is closed on both doors.
`defineView` is the container door, not an overlay door.
- D2: a stored row rehydrates clean and then parses at the door, while
the unconverted row is refused. A `viewKind`-less flat row is stripped.
The `viewItems` channel is reached, with each door's key stripped by its
own entry. Containers are left alone. Idempotence: the second replay has
0 notices and returns the same reference. Load path: a live author is
refused, not rewritten.
- Registration: the two keys, the chain id, and one D3 record for the
conversion. Any other entry naming the conversion must also name
`view-overlay-owner-hidden-retired`, so it is a pointer, never a second
record.
- **Hide-only residue** (patch round 1):
- A stored `hidden`, `owner` or both row strips to identity only. The
door refuses it with the identity precondition's own text, as one custom
issue at the root rather than the prescription.
- A rename (`label`) is refused.
- Controls `isDefault` / `order` / `columnState` save.
The ADR-0112 envelope is pinned at the door that produces it.
`packages/metadata-protocol/src/protocol.save-union-issues.test.ts` adds
a describe block over the existing stub-engine harness (no new double).
For each key and each family, `saveMetaItem` rejects with `code`
`INVALID_METADATA` and `status` `422`, persists 0 rows, and carries an
issue located at the key with the prescription. CONTROL: the same bound
overlays without the keys save, 1 row each.
Patch round 1 adds two pins here:
- **Save door:** a whole-row PUT of the stripped hide-only row answers
`INVALID_METADATA` / 422, with 0 rows and "only identity fields". The
same row plus `isDefault` saves.
- **Read path:** `getMetaItem` over a seeded row serves a stored overlay
without `owner` / `hidden`. `_diagnostics` is valid when the row carries
content and invalid when it is hide-only. The existing harness gains an
optional seed; its default is unchanged.
## Flipped pins: repo-wide sweep, each one load-bearing
The sweep grepped every test file that spells `viewKind` beside `hidden`
/ `owner`, in all packages.
| pin | before | after |
|---|---|---|
| `spec/ui/view-item-owner-hidden-retirement.test.ts` BOUNDARY | an
overlay with the keys parses | refused, with the SAME prescription |
| same file, conversion test | overlays left alone | the overlay key is
stripped by `view-overlay-owner-hidden-removed`, the record key by the
view-item entry (asserted as pairs) |
| same file, tree-scoped matcher | record spelling only | both spellings
(`viewKind` + a retired key); anti-vacuity cases for an overlay (TS,
YAML) and a container |
| `spec/conversions/registry.ts` view-item fixture | overlay neighbour
kept `hidden: true` | the neighbour carries neither key, which keeps the
fixtures disjoint once the overlay entry replays |
| `spec/ui/view-metadata-schema.test.ts` | `a hide PUT` accepted;
`identity + hidden` accepted | the hide PUT is refused at the member
with the prescription (not by the precondition); identity + a live key
is accepted, identity + `hidden` refused |
| `spec/ui/view-union-diagnostics.test.ts` | `overlay.list.aux` (with
`hidden`) and `put.hidden` ACCEPTED | moved to REFUSED, plus
`put.owner`; a new test asserts those rows are refused BY the tombstone
(the prescription, `invalid_type` at the key) |
| `spec/conversions/view-spelling-walk.test.ts` | the overlay's `owner`
survives conversion | `owner` stripped, with the notice under the
overlay entry; every binding key still survives |
| `metadata-protocol/src/metadata-diagnostics.union-issues.test.ts` |
`{hidden, object, viewKind}` badged `valid: true` | badged invalid, with
the prescription at `hidden`; a live key is badged valid |
## Verification
**Patch round 1, final head `a05b32f8b`**, merged with `origin/main` at
`4e0f72e8d`, which carries #20238, #20255 and #20244 (dev report
`5860055944`):
- spec `--project local`, full: 553 files / 16341 tests.
- The touched pins plus `migrations.test.ts`, with the census pin shown
verbosely: 6 / 530.
- The repo view-item pin: 18/18.
- `turbo build rest^...`: 24/24.
- metadata-protocol save-door + diagnostics: 2 / 40.
- Typecheck spec + metadata-protocol: exit 0.
- `check:generated`: 15/15 current.
- Gates: 88 derived, 86 run and exit 0, 2 NOT-MEASURED
(`check:dual-build-cjs-loads`, `check:type-check-debt`: exit 3,
PREREQUISITE NOT MET), 0 UNRUN.
- Ablation (round 1, at `e38a8027b`): the overlay strip replaced by
`return view` → 6 red (the residue, stored-row, `viewKind`-less and
`viewItems` pins) / 18 green. The restore was proven by blob == HEAD and
an empty `git diff HEAD`.
The round-0 readings below are at `2a40c104c`.
Round 0: final head **`2a40c104c`**. That is after merging `origin/main`
at `17bd3187`, which carried #19920's `view.zod.ts` /
`assembled-views.zod.ts` type change. Heavy runs went through
`scripts/pm/os-verify-lock.sh`, and every exit code was written to disk
before its log was read. The box was shared, with lock waits of 3–9 min,
so wall-clock readings are contended.
| run | head | reading |
|---|---|---|
| `turbo run build --filter='@objectstack/rest^...'` (spec + the
consumer closure) | `2a40c104c` | exit 0, 24/24 tasks |
| `pnpm --filter @objectstack/spec check:generated` | `2a40c104c` | exit
0, all 15 artifacts current; nothing regenerated |
| spec `--project local`, full | `2a40c104c` | 553 files / 16275 tests
passed |
| spec `--project repo`, `view-item-owner-hidden-retirement.test.ts`
(tree-scoped pin) | `2a40c104c` | 18/18 passed |
| metadata-protocol, the edited files +
`view-write-path-identity.test.ts` | `2a40c104c` | 3 files / 41 tests
passed |
| typecheck: spec (`tsc` + scripts + `check:test-typecheck`), lint,
metadata-protocol | `2a40c104c` | exit 0 ×3 |
| consumers, full: metadata-protocol / lint / metadata; objectql and
rest (their 24 / 13 view files) | `cbc81c574` | 189 files / 2720 tests
(3 skipped) · 110 / 4262 · 54 / 821 · 24 / 380 · 13 / 191, all exit 0 |
**Reverse verification** (a one-shot probe removed by an EXIT trap,
verified absent afterwards):
`packages/lint/src/zz-issue20230-dts-probe.ts` typed `{ object,
viewKind: 'list', hidden: true }` as `ViewMetadata`, against the REBUILT
spec `.d.ts`. `@objectstack/lint` `tsc --noEmit` exited 2:
`src/zz-issue20230-dts-probe.ts(2,14): error TS2322: Type '{ object:
string; viewKind: "list"; hidden: boolean; }' is not assignable to type
'ViewMetadata'.` With the probe removed, `git status` showed 0 lines and
`lint typecheck` exited 0. Predicted direction: red. Observed: red.
**Ablation** (`scripts/ablation-replace.mjs`, on committed state, wrap
mode). The mutation swapped the overlay's `hidden:
retiredKey(VIEW_ITEM_HIDDEN_RETIRED),` for `hidden:
z.boolean().optional(),`: anchor 1 → 0, blob `1f93b520` → `e9ad3dec`.
Three spec files then read 10 failed / 139 passed, and the 10 are
exactly the overlay `hidden` pins: both members, the same-text pin, the
door, the assembled channel, the hide-PUT refusal, the identity pin, and
the three union-diagnostics rows. The `owner` pins stayed green, as they
should. The restore brought the blob back to HEAD `1f93b520`, with `git
diff HEAD` at 0 bytes and `git status --porcelain` at 0 lines. Predicted
direction: red. Observed: red. (The metadata-protocol save-door pins
resolve spec through `dist/`, so they were not part of this ablation.)
**Gates.** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `2a40c104c` derived 88 commands. All 88
ran with the exit code captured before any pipe, and were reconciled
with `--ran`: **88 derived, 86 run, 2 NOT-MEASURED, 0 UNRUN**. All 86
measured commands exited 0. That includes `check-adr-0087-registration`
(`registered view-overlay-owner-hidden-removed,
view-overlay-owner-hidden-retired (new here …)`,
`[BREAKING+bang+clause-②-narrowing]`), `check-changeset-no-major`,
`check-empty-changeset`, `check:nul-bytes`,
`check:cross-package-test-inputs`, `check:doc-authoring`, and the spec
`check:*` family (`check:authorable-surface`, `check:liveness`,
`check:migration-registry`, `check:spec-changes`, `check:upgrade-guide`,
`check:api-surface`, `check:docs`).
NOT MEASURED (exit 3, `PREREQUISITE NOT MET`; each reads built output of
the whole workspace, which was not built locally): `pnpm
check:dual-build-cjs-loads`, `pnpm check:type-check-debt`. This diff
touches no package entry point, export or tsconfig. CI's build lanes
measure both. Also owned by CI: `pnpm lint`, the remaining objectql /
rest suites, and the lanes `dispatch-gates` lists outside the derived
total. The CLI `integration` tier does not apply (no `packages/cli`
change).
## Acceptance notes (observed, not fixed here)
_The seat updated this body at 2026-09-27T21:40Z after patch round 1,
per dev report `5860055944`. Reviews: `5859174998` (FAIL at
`2a40c104c`)._
1. **One family or two for D3, and the overlap with PR #20255.** PR
#20255 (#20201, not merged when this opened) adds
`18.view-item-owner-hidden-retired.ts` as the view item family's D3
entry, and a census pin requiring every major-18 conversion to be named
by a D3 entry of its step. This PR's conversion is separate, disjoint by
`config`, so it carries its own D3 entry naming it. That keeps one
record per conversion and no second file under #20255's filename, which
would be an add/add collision. #20255 has since landed (`f415bcf18`),
and the census pin is green here at `a05b32f8b`. Its sentence 「A
flattened view overlay keeps its own `owner` and `hidden` …」 is replaced
in this PR (amendment `5859181450`): the overlay pair is a separate
family, with its own D2 `view-overlay-owner-hidden-removed` and D3
`view-overlay-owner-hidden-retired`.
2. **This PR supersedes one sentence of #20227's pending changeset.**
`.changeset/view-item-owner-hidden-retired.md` says an overlay "still
parses". It is left as landed, because `check-empty-changeset` refuses
an edit to another PR's release note. This PR's changeset states the
supersession instead. The release compiler should read the two together.
3. **Cloud is NOT MEASURED** (above). If its mock-protocol double parses
`{hidden:true}` through the spec, it goes red at cloud's spec bump. That
is a fixture edit there. Carrier: cloud, at its next `@objectstack/spec`
bump.
4. **The assembled channel's refusal loses the branch diagnostics**
(#20227's acceptance note 4, pre-existing):
`AssembledViewArtifactSchema` is a plain `z.union`. Carrier: none.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 10ea9eb commit eea8787
15 files changed
Lines changed: 1072 additions & 70 deletions
File tree
- .changeset
- packages
- metadata-protocol/src
- spec/src
- conversions
- migrations
- entries
- retired-keys
- semantic
- ui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
Lines changed: 12 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
193 | 193 | | |
194 | 194 | | |
195 | 195 | | |
196 | | - | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
197 | 208 | | |
198 | 209 | | |
199 | 210 | | |
| |||
Lines changed: 127 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
49 | | - | |
50 | | - | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
51 | 60 | | |
52 | 61 | | |
53 | 62 | | |
| |||
65 | 74 | | |
66 | 75 | | |
67 | 76 | | |
68 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
69 | 86 | | |
70 | 87 | | |
71 | 88 | | |
| |||
81 | 98 | | |
82 | 99 | | |
83 | 100 | | |
84 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
85 | 104 | | |
86 | 105 | | |
87 | 106 | | |
| |||
363 | 382 | | |
364 | 383 | | |
365 | 384 | | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
0 commit comments