Commit d0f1845
Fixes #15178
Clause-②: yes
## What is ruled, and what landed
Maintainer ruling batch #132 item 2 letter ② (comment 5653315643, 「同意」
2026-09-13), quoted verbatim:
> 1. `packages/spec` `TranslationDataSchema` becomes two exports (names
per the file's convention): the platform bundle schema (eleven groups,
`settings` included) and the per-app bundle schema (`settings` absent,
strict — an authored `settings` in a per-app bundle is refused with a
remedy saying it is platform-only). Every reader that consumes a per-app
bundle types against the per-app schema.
> 2. The card's original "removal" disposition is struck: `settings` is
a live platform key (`pickSettingsEntry`, `i18n-resolver.ts:2305`;
console `useSettingsLabel`).
> 3. `check:i18n-walk-parity`: the `settings` exemption disappears with
the per-app key; `LEDGER_CEILING` 3 → 2 in the same PR (the ledger is
governed — declared in the claim).
> 4. Accept-set narrowing on the per-app bundle: `Clause-②: no`;
ADR-0087 semantic entry — a per-app bundle carrying `settings` was
inert, so the conversion drops the group and records a note; no
deprecation window (「创业阶段不渐进」), launch-window convention applies.
The card's own closing line (「⛔ Not a queue card: zero measured pull
today」) is stale and the ruling overrides it. The removal option is
struck; this is the SPLIT.
**Which name took which face, and why.** `TranslationDataSchema` keeps
its name and becomes the **per-app** bundle entry (ten groups); the new
`PlatformTranslationDataSchema` / `PlatformTranslationBundleSchema`
(types `PlatformTranslationData` / `PlatformTranslationBundle`) carry
the eleven-group platform face. The ruling's "names per the file's
convention" is satisfied by the file's existing habit — a qualified
prefix marks the other face, as `ObjectTranslationDataSchema` already
does — and the direction was chosen on a measurement, not on taste:
- The card body itself names the narrowing target "the per-app
`TranslationDataSchema`", and the gate's ledger reason says "removal
from the per-app schema" about that same export.
- Every EXISTING per-app author already types against `TranslationData`:
`stack.translations`, `defineTranslationBundle`, the three examples, the
CLI walker and coverage reader, and the header `os i18n extract` emits
into every scaffolded bundle. Putting the narrowing on a NEW name would
have left all of them accepting `settings`, and re-pointing them would
have re-typed the nine platform `*.generated.ts` files the same emitter
writes.
- Only the genuinely-platform readers had to move, and only one of them
authors `settings` at all.
So "every reader that consumes a per-app bundle types against the
per-app schema" holds by construction here, and the movement fell on the
platform side.
## The ruling's "was inert" is falsified — the record says what was
measured instead
Ruling item 4 describes a per-app `settings` as inert. Measured on
`origin/main` at `1ff3a8f210`, it was **live**:
- `AppPlugin.loadTranslations` (`packages/runtime/src/app-plugin.ts`)
hands each `stack.translations` bundle entry WHOLE to
`II18nService.loadTranslations`.
- `FileI18nAdapter.loadTranslations` deep-merges it into the one
per-locale tree; `getTranslations(locale)` serves that tree.
- Every platform plugin contributes into the SAME tree at `kernel:ready`
— `SettingsServicePlugin` does exactly this with
`settingsBuiltinTranslations`.
- `pickSettingsEntry` reads `pickData(bundle, locale)?.settings`, and
the console's `useSettingsLabel` scans every namespace carrying a
`settings` branch. The tracked liveness ledger
`packages/spec/liveness/translation.json` records that reader with its
evidence pointer and says both doors "merge into ONE tree".
So an app-authored `settings` did not sit unread — but nor did it
override the platform. The app's bundles load in `AppPlugin`'s `start()`
(kernel Phase 2) and the platform's at `kernel:ready` (Phase 3), and
`deepMerge` gives the later source the leaf, so the platform won every
key both defined. What an application actually had was a GAP FILLER on a
namespace it does not own: it rendered only where the platform bundle
carried no string for that key and locale. That makes the ruling's
DIRECTION stronger, not weaker, and it changes only what the record must
say: the drop is a visible change only on the screens where the entry
was FILLING A GAP, and those fall back to the manifest's own English
literal; where the platform already carried the string, nothing changes.
The ADR-0087 semantic entry and the changeset both say so in those words
rather than reciting the house "pure lossless delete" phrase.
## Diff
**Spec (`packages/spec`)**
- `src/system/translation.zod.ts` — `translationDataShape()` becomes
`appTranslationDataShape()` (ten groups) and the `settings` group moves
to `platformSettingsShape()`. `TranslationDataSchema` = per-app, strict,
with a `guidance` prescription for both `settings` and the singular
`setting`; the `setting` alias is deleted, because an alias prescribing
a key the shape now rejects is a suggestion the author cannot take.
`PlatformTranslationDataSchema` = the ten plus `settings`.
`TranslationBundleSchema` is per-app; `PlatformTranslationBundleSchema`
is new. `TranslationItemSchema` is UNCHANGED and still declares
`settings`.
- `src/api/protocol.zod.ts` —
`GetTranslationsResponseSchema.translations` moves to the platform face.
The served document is the merge of every loaded bundle, so it carries
`settings`; leaving it on the per-app face would have published a
declaration the server contradicts.
- `src/system/i18n-resolver.ts` — `pickData` becomes generic over the
entry type, and the settings resolvers take `PlatformTranslationBundle`.
This WIDENS their parameter (every group is optional, so a per-app
bundle is still assignable), so no caller — this repo's or the pinned
sibling's — loses a call.
- `src/conversions/registry.ts` — new D2
`translation-per-app-settings-removed` (`toMajor: 18`,
`retiredFromLoadPath: true`), strips the group from per-app bundle
ENTRIES only. An entry carrying `locale` is a `translation` ITEM and is
left whole; the candidate value must additionally be a dict whose every
key is a declared group, so an `objects` record holding an object
literally named `settings` is not mistaken for a bundle.
-
`src/migrations/entries/semantic/18.translation-per-app-settings-platform-only.ts`
— the ADR-0087 semantic entry, plus the regenerated `registry.ts` and
the extended step-18 rationale. Regenerated with
`gen:migration-registry`, never hand-merged.
- `src/type-alias-convention.pin.test.ts` — the two new aliases are
pinned isomorphic (both faces are all-optional, no default or transform
anywhere), and the pin count moves 784 → 786 with its receipt.
- `authorable-surface/system.json` — `system/TranslationData:settings`
deleted DELIBERATELY, the tripwire the strict-delete route owes. The
build's own deletion gate then adjudicated it and printed its proof
(#4650 proof 2): "def not reachable from the 30 metadata-type roots ...
an over-collected entry, never parsed against a metadata document."
Eleven `system/PlatformTranslationData:*` keys arrived in the same run.
- Regenerated: `api-surface/`, `export-origins/`, `declaration-map/`,
`json-schema.manifest/`, `content/docs/references/**`, the
strictness-ledger counts.
**The gate (ruling item 3)** — `scripts/check-i18n-walk-parity.mjs`: the
`settings` ledger row is gone, `LEDGER_CEILING` 3 → 2, the class-level
note and the recorded self-test samples move with it. **This is the
shrinking direction of a governed, shrink-only ledger**, declared in the
claim and declared here. The gate's own rule at the ratchet says growth
is the reviewed act; slack fails too, which is why the ceiling had to
move in the same diff.
**Platform readers** —
`packages/services/service-settings/src/translations/{en,es-ES,ja-JP,zh-CN}.ts`
and their `index.ts` move to `PlatformTranslationData` /
`PlatformTranslationBundle`. They are the only bundles in the repo that
author `settings`.
**Published prose** — `content/docs/protocol/kernel/i18n-standard.mdx`
published the eleven-group list as "rejected by name at both authoring
doors", and `skills/objectstack-i18n/SKILL.md` published the same list
to customer projects. A **third** published carrier,
`content/docs/ui/translations.mdx`, taught `settings` as
app-translatable in its own table. **All three are corrected** — an
earlier draft of this sentence said "both", before the guide correction
landed. `docs/qa/platform-checklist/areas/i18n.json` had a symbol anchor
on the renamed shape function and a clause naming the wrong face.
## Verification
⚠️ **Provenance corrected — this table was NOT read at the final
commit.** It was read at `5283099838`, which is the **6th of this
branch's 10 commits**; four have landed since (`b33ea66cb3`,
`d5e6b43977`, `b1e7984040`, `8dcd6a42ae`). An earlier draft of this line
called it "the final commit on this branch", and the whole Verification
table, the Tests section and the Reverse verification paragraph hang off
it — so as written the body claimed readings that covered the derivation
change and the guide correction. They did not.
⛔ Nothing below is therefore unmeasured at head; it is re-measured
elsewhere, not here. What covers the later commits is the at-tier
contract review of head `8dcd6a42ae` (record on card #15178), which
re-derived the carrier sweep over all 9156 tracked files, rendered the
migration TODO live, ran the derivation ablation in memory, and read CI
by job conclusion. ✅ One row IS unaffected and re-measured at head: the
**skills** table — `skills/objectstack-i18n/SKILL.md` was last touched
at `2602ccec10`, earlier than `5283099838`, and every figure in it
reproduces at head (494→496 lines, 4713→4752 tokens, ceiling 6338,
headroom 1586).
| Instrument | Reading | Which side it can fail on |
| --- | --- | --- |
| `check:i18n-walk-parity` | `10 declared group(s), 8 walked, 2
exempted` | The `10` is the reading that discriminates: the per-app face
has ten groups, the platform face eleven. It fails if a declared group
has no emitter and no ledger row, if a ledger row is stale, and — the
ratchet — if the ceiling has slack. Its `--self-test` battery is 43
cases. |
| `check:authorable-surface` (inside `gen:schema`) | deletion allowed
with a printed proof; 11 keys added | It refuses ANY authorable key that
vanishes without one of four proofs, and it refused this diff on the
first attempt — that refusal is the control. |
| `check:generated` | 15 of 15 artifacts current after `--fix`
regenerated the 5 it proved stale, each re-checked | It can fail on a
stale artifact in either direction. |
| `check:adr-0087-registration` | `1 declared-breaking changeset(s),
each carrying an ADR-0087 disposition` | It can fail on a breaking
changeset with no marker; it reported `0 non-breaking changeset(s) seen`
before the changeset was committed, which is the control leg. |
| `check-changeset-no-major` | `no major bump` | ⚠️ Its clause-② axis
printed `LEVEL AXIS: NOT APPLICABLE` — there is no PR payload on a local
run, so it can fail HERE only on the `major` axis, not on the
declaration. |
| `check:spec-parsed-alias` | `1455 bare aliases, 786 pinned isomorphic,
669 paired` | It failed first with both new aliases named — that red is
the control. |
| `check:type-check-debt` | `4 ledger entr(ies) re-measured, 53 raw tsc
errors, none above its recorded number` | Re-run after a rebuild; an
earlier run exited 3 (PREREQUISITE NOT MET) on a dist older than its
sources, which is NOT a reading. |
| `pnpm lint` (`eslint . --no-inline-config`) | exit 0, whole repo, no
narrowing | Ran over the repo's own configured universe, so no narrowing
claim is needed. |
**Gate families**: `scripts/pm/dispatch-gates.mjs` derived 139 for this
change set; `--ran` with exit codes recorded reconciles **139 accounted,
138 run, 0 UNRUN, 1 NOT MEASURED**. The one is
`check:dual-build-cjs-loads`, which exits 3 (PREREQUISITE NOT MET)
without a full workspace build — recorded as NOT MEASURED and left to
CI, which builds everything. The reconciliation's own caveat stands: it
answers what this card DERIVES against what was RUN, and the
artifact-roster families, the wide-population families and the
path-scheduled CI jobs are outside that total.
**Tests** (`turbo run test`, `--concurrency=2`): `@objectstack/spec` 508
files / 14,902 tests, `@objectstack/lint` 106 files,
`@objectstack/service-settings` 33 files,
`@objectstack/platform-objects` 51 files, the three examples 41 files,
`@objectstack/cli` unit tier 222 files / 3,141 tests — all pass. `turbo
run typecheck` over spec, cli, lint, platform-objects, service-settings,
service-i18n, runtime and rest: 64 tasks, all pass.
**Reverse verification (one-shot, not left in the tree).** With the fix
committed, `settings` was put back on the per-app shape through
`scripts/ablation-replace.mjs` — the mutation is proved on disk (anchor
1 → 0, blob `3a27c26f6a5c` → `a0b6be68af3e`) — and the two refusal pins
went RED by name. Restored with `--restore`: blob back to
`3a27c26f6a5c`, equal to HEAD, and `git diff HEAD` empty. The predicted
direction was "turns red", and that is what was observed.
## Skills bundle readings (`skills/**` is a governed surface)
Required because the diff touches a published skill. This is a
CORRECTION, not an expansion — the added sentence exists because the old
one became false.
| Reading | Before | After | Delta |
| --- | --- | --- | --- |
| `skills/objectstack-i18n/SKILL.md`, lines | 494 | 496 | +2 |
| `skills/objectstack-i18n/SKILL.md`, tokens | 4713 | 4752 | +39
(ceiling 6338, headroom 1586) |
| Whole bundle, all `SKILL.md` lines | 6145 | 6147 | +2 |
| Whole bundle, tokens (shipped tree) | 140374 | 140413 | +39 |
Before-tokens were measured by restoring the base file, reading
`check-skills-token-ratchet`, and restoring with proof (blob equal to
HEAD, `git diff HEAD` empty). `check-skills-token-ratchet` passes: 34
authored files within their ceilings.
⚠️ **Landing tier.** `skills/**` is Tier H on the governed register, so
this PR's landing is Tier H on one path hit. It is left as a draft
awaiting that record. If the seat would rather land the rest through the
queue, the remedy the directive names is to split
`skills/objectstack-i18n/SKILL.md` off into its own PR — but ⛔ not to
ship the corrected schema while the published skill still teaches the
key the parse now refuses.
## Declared file-surface deviations
The claim declared the surface as `translation.zod.ts` + siblings, the
walk-parity gate + fixtures, `i18n-extract.ts` + tests,
`migrations/entries/semantic/` + `registry.ts`, and `.changeset/`. Five
paths outside it were edited, each forced by the ruling rather than
chosen, and none widened silently:
1. `packages/spec/src/api/protocol.zod.ts` — the served response must
type against the platform face or it declares a shape the server
contradicts. ⚠️ **This path is held by open PR #19493's sibling
declaration set — specifically it was declared disjoint against #19543,
which enumerates it.** One line changes (the import) plus one line in
the response schema, plus a docblock. A textual conflict is possible;
this PR is not asking to land first.
2. `packages/spec/src/system/i18n-resolver.ts` — `pickSettingsEntry`
reads `.settings`; without this the package does not typecheck. The
parameter is widened, not narrowed.
3. `packages/services/service-settings/src/translations/*` (5 files) —
the only bundles that author `settings`; type annotations only.
4. `packages/spec/src/conversions/registry.ts` — the D2 conversion
ruling item 4 asks for ("the conversion drops the group and records a
note"). The semantic entry alone records the judgment but rewrites
nothing.
5. `content/docs/protocol/kernel/i18n-standard.mdx`,
`skills/objectstack-i18n/SKILL.md`,
**`content/docs/ui/translations.mdx`**,
`docs/qa/platform-checklist/areas/i18n.json` — published claims this
change makes false, plus one symbol anchor the rename broke
(`check:platform-checklist` went red on it and is green again). ⚠️
**`content/docs/ui/translations.mdx` was added to this enumeration after
the fact:** it was edited in commit `b1e7984040` and an earlier draft of
this item listed only three paths, under-declaring the deviation by one.
`packages/spec/src/migrations/registry.ts` is the declared overlap with
open PR #19493. Its **generated regions** were regenerated with
`scripts/pm/os-regen-merge.sh`'s generator (`gen:migration-registry`)
and never hand-merged. ⚠️ **One line in that file IS hand-written, and a
reviewer of a generated file should be told:** `registry.ts:47` carries
a value import of `TranslationDataSchema`, **outside every
`<os-generated …>` region** (the first region opens at `:1142`). It is
necessary, not an oversight — `build-migration-registry.ts`'s
`parseEntry` deliberately drops imports and carries only the
initializer, so an entry that derives its text from a value needs that
value in scope in the registry itself. The comment immediately above the
import says so. It survives regeneration because `renderRegistry`
splices only between the region markers, and `check:generated` is the
instrument that would fail if that round-trip were unstable.
`packages/cli/src/utils/i18n-extract.ts` was NOT edited — the walker
does not move, because `settings` never had an emitter.
## Acceptance notes
- **The `translation` metadata-type door is untouched and still accepts
`settings`.** The ruling names the per-app BUNDLE, and
`packages/spec/liveness/translation.json` is that item's ledger, so
narrowing the item would have moved a ledger outside this card's
surface. It leaves a question worth a decision rather than a silent
choice: an app admin authoring a `translation` item through Studio can
still write `settings`, and `authored-translation-sync` merges the raw
stored payload into the same served tree, so the refusal this PR adds at
the file door does not reach the metadata door. Raised in the report,
not decided here.
- Platform bundles that author only shared groups (`platform-objects`,
the five plugins, the other services) keep the narrower
`TranslationData` / `TranslationBundle` types. They are assignable, and
re-typing ~20 files that never carry `settings` would be churn with no
contract effect. noted, not filed.
- `packages/lint/src/validate-translation-references.ts` still lists
`settings` among the groups it deliberately does not judge. The branch
is now unreachable for a per-app stack rather than wrong. noted, not
filed.
## 维护者速读(草稿)
- **改了什么。** 翻译包的类型一分为二:`TranslationDataSchema` 从此只表示「应用自己写的那一份」,十个分组;新的
`PlatformTranslationDataSchema` 是平台那一份,十一个,`settings` 留在它那里。应用再写
`settings` 会被按名字拒绝,并告诉作者这是平台专属。
- **为什么改。**
一个类型同时代表两种包,是这张卡上每一次误读的源头:当初的普查拿「按应用问」的问题去问一个分不出应用和平台的类型,得到零,就差点把平台每天在读的键删掉。更要紧的是实测结果:应用写的
`settings` 并不是没人读 —— 它和平台那一份合进同一棵已服务的树。但它**不是覆盖者**:应用包在 kernel 第 2
阶段加载、平台包在第 3
阶段,合并时叶子归**后到**的一方,所以**两边都定义的键,平台永远赢**。应用那份实际是个**补缺者**:只在平台包对那个键、那个语言没有字符串时才显示。
- **风险与代价(含回滚)。** 风险在于:升级后,**两边都有的键屏幕上根本不变**(平台本来就赢);只有**应用包在补空**的那些键会变
—— 那里平台压根没有字符串,所以屏幕上会回落到 **manifest 自己的英文字面量**,而不是「平台自带的字」。⚠️
一个本地化部署里冒出一串英文,是比「换成平台的措辞」更响亮的一种结果,请按这个来衡量。这是有意的,changeset 与 ADR-0087
条目都写明了,不是静默变化。发布面动了,所以带 `minor` changeset(发射窗口惯例,`major`
会被门禁拒收)。回滚就是回滚这个 PR:没有数据迁移、没有存储改动,`os migrate meta` 的那条转换只在作者主动运行时改源码。
- **席位意见。** 这一轮的方向是 dev **第一手实测**出来的,不是复述:证伪器跑真链路,外加两个亮控 ——
一个把加载顺序反过来证明仪器对顺序敏感,一个用平台没翻译的命名空间证明 app
那份真的被加载且在服务。结论从「覆盖平台文案」改成「只填平台没有的空」,所以 ADR
条目按实测写是对的,原裁决的**方向**不动。本席**不建议拆**技能文件:拆了等于在窗口期里让已发布技能继续教一个已被拒收的键,而
`skills/**` 这道 Tier H 的门你本来就得为它开一次。⚠️ 另:本 PR
先前那份契约复审记录**已作废**(跑在已退役的档位上,台账见 #19603),新的达档复审在 the current
`CONTRACT_REVIEW_TIER` 上重跑;⛔ 结果出来之前本席不做任何落地动作,也不翻 ready。
- **你要做的。** ① 这个 PR 碰了 `skills/`,按规矩属于 Tier
H,落地要维护者的那句话;若不想为一条文案更正开这道门,可以把那个技能文件单独拆一个 PR——但⛔
不能一边发布新契约、一边让已发布技能继续教一个现在会被拒收的键。② 裁决里「was inert」这句与实测不符(它是活的),ADR
条目按实测写,请确认这个改写符合原意。③ `translation` 元数据门仍接受
`settings`,那是本卡范围之外的一个口子,见上面的验收注记。
---
_Generated by [Claude Code](https://claude.ai/code)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 041c8cf commit d0f1845
28 files changed
Lines changed: 929 additions & 180 deletions
File tree
- .changeset
- content/docs
- protocol/kernel
- references
- api
- system
- ui
- docs
- audits
- qa/platform-checklist/areas
- packages
- services/service-settings/src/translations
- spec
- api-surface
- authorable-surface
- declaration-map
- export-origins
- json-schema.manifest
- src
- api
- conversions
- migrations
- entries/semantic
- system
- scripts
- skills/objectstack-i18n
Lines changed: 78 additions & 0 deletions
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
398 | 398 | | |
399 | 399 | | |
400 | 400 | | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
405 | 413 | | |
406 | 414 | | |
407 | 415 | | |
| |||
1046 | 1054 | | |
1047 | 1055 | | |
1048 | 1056 | | |
1049 | | - | |
1050 | | - | |
1051 | | - | |
1052 | | - | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
1053 | 1063 | | |
1054 | 1064 | | |
1055 | 1065 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1615 | 1615 | | |
1616 | 1616 | | |
1617 | 1617 | | |
1618 | | - | |
1619 | 1618 | | |
1620 | 1619 | | |
| 1620 | + | |
1621 | 1621 | | |
1622 | 1622 | | |
1623 | 1623 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
316 | 316 | | |
317 | 317 | | |
318 | 318 | | |
319 | | - | |
| 319 | + | |
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
| |||
354 | 354 | | |
355 | 355 | | |
356 | 356 | | |
357 | | - | |
| 357 | + | |
358 | 358 | | |
359 | 359 | | |
360 | 360 | | |
| |||
0 commit comments