Repository navigation
Commit 7dbb89d
fix(lint): one-line fix lines for 16 more author-time rule ids;
Part of #22161
Clause-②: no
Stage 2 of the card, slice 12: the over-long `fix:` lines, continued in
slice 11's shape. Each finding's `hint` (the CLI's `fix:` line, the
runtime issue's `hint`) of 16 more `packages/lint` rule ids, in ten
whole rule files, is now one remedy line of at most 200 characters, and
what the lines used to enumerate or explain is each id's
`RULE_EXPLANATIONS` entry behind `os explain RULE_ID`. The card stays
open: 91 author-time ids still carry a hint over 200 characters (the
last section).
## What changes
- **One remedy line per finding.** The 16 ids, every hint the lint suite
fires, before → after:
| rule id | file | lint suite: hints · range, before → after | runtime
door |
|---|---|---|---|
| `validation-rule-json-schema-unknown-format` |
`validate-rule-schema-formats.ts` | 10 · 606–646 → 10 · 143–183 |
`object` write, 422 |
| `measure-aggregate-field-type-refused` |
`validate-dataset-measure-aggregates.ts` | 694 · 574–645 → 694 · 111–178
| `dataset` write, 422 |
| `dimension-json-stored-field-refused` | same | 5 · 177–262 → 5 ·
161–177 | `dataset` write, 422 |
| `predicate-rhs-path-shaped` | `validate-predicate-path-refs.ts` | 12 ·
381–643 → 12 · 153–184 | `view` write, 422 (dotted) / 2xx advisory (bare
word) |
| `predicate-path-unrooted` | same | 1 · 214 → 1 · 122 | `view` write,
422 |
| `predicate-path-unresolved` | same | 10 · 84–201 → 10 · 20–153 |
`view` write, 422 |
| `rls-predicate-unknown-user-variable` |
`validate-rls-predicate-enforceability.ts` | 6 · 566–618 → 3 · 158–193 |
`permission` write, 422 |
| `rls-predicate-unparseable` | same | 1 · 523 → 1 · 171 | `permission`
write, 422 |
| `hook-api-update-readonly-when-field` |
`validate-readonly-hook-writes.ts` | 1 · 607 → 1 · 173 | CLI only |
| `action-name-undefined` | `validate-action-name-refs.ts` | 32 ·
181–560 → 29 · 91–195 | CLI only |
| `ai-skill-tool-unresolved` | `validate-ai-tool-references.ts` | 22 ·
308–548 → 22 · 150–189 | CLI only |
| `org-axis-permission-inheritance` | `validate-org-axis-red-lines.ts` |
1 · 542 → 1 · 145 | CLI only |
| `org-axis-cross-org-bu-grant` | same | 1 · 315 → 1 · 141 | CLI only |
| `object-reference-unknown` | `validate-object-references.ts` | 23 ·
254–522 → 2 · 123–134 | `dataset` write (its `object`), 422 |
| `object-reference-unregistered-platform` | same | 8 · 366–500 → 1 ·
187 | `dataset` write (its `object`), 2xx advisory |
| `filter-empty-node` | `validate-empty-combinators.ts` | 3 · 170–515 →
3 · 69–113 | `flow` / `report` write, 422 |
A count that falls is several old hints that differed only in what the
new line no longer carries: the stack's object or action list, the
site's consequence sentence, the kernel key list's position against the
suggestion.
- **Lists are no longer echoed.** `object-reference-unknown` drops
"Defined objects: …" and `action-name-undefined` drops "Defined actions:
…" and the related object's action list: the verdict's "Did you mean"
already names the nearest one.
`validation-rule-json-schema-unknown-format` names the nearest
registered format and moves the full registered set (26 names) into its
explanation, written out there and held to `registeredFormatNames()` by
the rule's test. `ai-skill-tool-unresolved` moves the family prefixes
into its explanation, held to `PLATFORM_TOOL_FAMILY_PREFIXES`.
`rls-predicate-unknown-user-variable` keeps the six kernel keys and the
nearest one, so its line holds no author text at all (a test holds the
worst-case suggestion under 200).
- **The reasoning moves, the remedy stays.**
- `object-reference-*`: each `check()` site passed a consequence
sentence that closed every hint (the record picker, the view container's
index, the dashboard filter, the dataset's reports, the nav gate). Those
are now one paragraph in both ids' explanations; the `check()` argument
is a `remedy`, which only the view-container site passes (the
namespace-prefixed spelling, which is then the whole line).
- `measure-aggregate-field-type-refused`: the line names the aggregates
the declaration accepts (the "accepts: count." pins hold); why `count` /
`count_distinct` reach further, the stored-numeric route and the two
doors that refuse the pair later (`DATASET_COMPILE_DOOR` /
`CUBE_QUERY_DOOR`, now deleted with the `door` parameter) are the
explanation's.
- `hook-api-update-readonly-when-field`: the two routes and "runAs:
'system' and sudo() do not waive this lock"; why (the system context,
the sandbox), the drop-the-field alternative and "never blocks a build"
are the explanation's.
- `rls-predicate-unparseable`: the SQL-to-CEL translations in one line;
the subquery route (ADR-0055, ADR-0105 D11) is the explanation's.
- `predicate-rhs-path-shaped`: both spellings in one line, and the
bare-word arm keeps "Do NOT simply add the root in place" (pinned by
`runtime-gate.test.ts`); why quoting changes nothing today and why two
paths cannot be compared are the explanation's.
- `filter-empty-node`: `OMIT_THE_KEY` / `MATCH_NONE_SPELLING` are
deleted from the rule and their text is the explanation's.
- `org-axis-*`, `ai-skill-tool-unresolved`, `action-name-undefined`, the
two other predicate ids, `dimension-json-stored-field-refused`
(multi-value arm) and `validation-rule-json-schema-unknown-format`:
likewise, one line each.
- **Two ids gain an explanation entry**, because their reasoning had no
entry to move into: `object-reference-unknown` ("how an object name
resolves, and what a miss costs") and `org-axis-permission-inheritance`
("why access never walks the organization tree"). Their `rule:` line now
ends with the `os explain` pointer, which `explainPointer` prints for
every id the table holds. The two object-reference entries share the
sites, the ladder and the per-site cost paragraphs; the two org-axis
entries share the ADR-0105 D6 opening. The other 14 entries gain
paragraphs.
- **Nothing else moves.** Every `message`, rule id, severity and `path`,
and what each rule accepts or refuses, is unchanged: every hunk in the
ten rule files is a `hint` expression, a comment, a deleted hint
constant, or (two places) a parameter that only fed a hint (`door`, and
`fix` renamed `remedy` with a default). No condition, branch, skip or
dedupe moved.
- `.changeset/22161-lint-slice-12-one-line-fix.md`: `@objectstack/lint`
`patch`, `Clause-②: no`, naming every door that prints `fix:` and the
runtime `hint` FROM → TO.
## The runtime wire (Zone 2 item 3)
Measured at the door with `runRuntimeAuthoringRules` on the base dist
and on the rebuilt one (a scratch probe, 28 writes):
- an `object` write: `validation-rule-json-schema-unknown-format` (422
`issues[].hint`, 638 / 606 → 175 / 143, with and without a nearest
name);
- a `dataset` write: `measure-aggregate-field-type-refused` (422, 606 /
581 → 147 / 122), `dimension-json-stored-field-refused` (422,
multi-value 259 → 166, structured JSON 177 unchanged),
`object-reference-unknown` on the dataset's `object` (422, 331 → 134)
and `object-reference-unregistered-platform` (2xx `advisories[].hint`
and the `[Protocol] authoring advisory` log line, 449 → 187);
- a `view` write of a schema-bound metadata form:
`predicate-rhs-path-shaped` (422 dotted 384 → 156; 2xx advisory bare
word 631 → 180), `predicate-path-unrooted` (422, 214 → 122),
`predicate-path-unresolved` (422, 100 → 36 with a nearest key);
- a `permission` write: `rls-predicate-unparseable` (422, 523 → 171),
`rls-predicate-unknown-user-variable` (422, 566 / 590 / 634 → 158 / 180
/ 190, without a nearest key, with `email`, with `organization_id`);
- a `flow` or `report` write: `filter-empty-node` (422, 515 / 278 / 170
→ 113 / 107 / 69);
- no write reaches `hook-api-update-readonly-when-field`,
`action-name-undefined`, `ai-skill-tool-unresolved` or the two
`org-axis-*` ids (a `hook`, `skill`, `page`, `sharing_rule`, `view`
bulk-action and `permission` write were probed), nor the
object-reference ids on an `object` or `view` write.
Readers of `hint`, read-only against objectui `main` at `f3d5408141`
(fetched into a ref of its own, `git grep`, no edit): Studio's
`saveAdvisoryToast.ts` `formatFinding` renders `[rule] where — message
hint` for every 2xx advisory; `DraftChangesPanel.tsx` renders `p.hint ||
p.message` for the in-browser security-posture lint (none of the 16);
`metadata-client.ts` `readSaveAdvisories` checks only that `hint` is a
string; the 422 `issues` renderers read `path` and `message`. REST (`PUT
/api/v1/meta`, `SaveMetaItemResponseSchema.advisories`, the error
envelope's `issues`) forwards the array as JSON; `packages/mcp` has no
metadata write tool, so an MCP or AI author reaches the gate through
REST. In this repository `toIssue` forwards `hint` verbatim, the
advisory log line prints it, and `build-probes.ts` reads `hint` only for
`object-field-ref-unknown` (not one of the 16). **No reader in either
repository matches on `hint` text.**
`check:watch-hint-literal` guards something else of the same name (every
`*_WATCH_HINTS` population declaration in a gate script is a literal
array): exit 0, 72 declarations across 4 rostered names, standalone and
inside the gate set.
## Census (taken first, before any edit, at the base `63739521d8`)
Method: slices 4 to 11's scratch preload (`NODE_OPTIONS=--import`, never
committed) patching `Array.prototype.push` to record every
finding-shaped object, deduped by (rule, hint) per process, with its
push site. Lengths are the `hint` alone. Runs, each before and after:
- **`packages/lint` suite** (137 files, 6,497 tests at the base): 240
ids fire, **131 carry a hint over 200** = 21 of the 26 fenced ids, 3
repo-gate ids (`lint-startup-registry-verdict.ts`) and 107 author-time
ids; the 16 here match slice 11's census lengths exactly. After, at the
merged head `26fe94f3e1` with the lint dist rebuilt: **115 over 200** =
21 fenced + 3 repo-gate + **91 author-time**.
- **Runtime publish gate**, the whole `@objectstack/metadata-protocol`
suite reading `@objectstack/lint` from its built dist (base dist before,
rebuilt after): fires `measure-aggregate-field-type-refused` (588 → 129)
and `rls-predicate-unparseable` (523 → 171) of the 16.
- **`packages/cli` unit tier** (283 files): fires
`hook-api-update-readonly-when-field` (604 → 170) and
`object-reference-unknown` (7 hints · 242–348 → 1 · 134).
- **`os validate`** (the built CLI) on `app-crm`, `app-todo`,
`app-showcase`, `app-multi-package`, exit 0 each, before and after: none
of the 16 fires on any of them; each app prints the same 9 / 7 / 70 / 3
`rule:` lines, and the printed output is byte-identical before and
after.
## Tests
Every heavy run went through `scripts/pm/os-verify-lock.sh` (slot
`issue-22161-s12`); its VERDICT lines are in the report.
- **Each rule's own suite pins the new shape.** Every touched suite
already records what its cases fire; a new last block per file holds
every recorded `fix:` line of its converted ids to one line of at most
200 characters behind a coverage control (each arm fired: both format
arms; the measure id on a type row and a flagged declaration and the
dimension id on both classes; both unresolved arms and both right-hand
arms; the variable id with and without a nearest key; the generic action
arm with both placements and both related-list arms; both ai-skill arms;
both org-axis ids; the object-reference id with and without the
namespace remedy; all three empty-node positions), plus a check per id
that `explainRule(id)` holds what the line stopped saying. The three RLS
sibling files' bounds now cover every `rls-predicate-*` id. Pins that
read the old hint text moved to the explanation, text-only, except two
that needed a new reading: the related-list drawn-locations pin now
reads its own paragraph (the new fix paragraph names the header's
`record_header` / `record_more`), and the artifact-context pin reads the
verdict's "Did you mean" on a near miss instead of the dropped object
list.
- **Lint suite** at the merged head `26fe94f3e1`: Test Files 137 passed
(137), Tests 6,528 passed (6,528); VERDICT command-exit 0 (6,518 before
the merge of `origin/main`).
- **Lint build + typecheck:** `pnpm --filter @objectstack/lint build`
(`check-dts-emitted` 6/6), rebuilt with its closure after the merge, and
`run typecheck` at `9d56f0f431` (`check:test-typecheck` OK, 2 files / 6
errors / 2 pinned signatures held), VERDICT command-exit 0 each. The
rebuilt dist carries the new text (`constraint with \`pattern\`, which
is enforced` and `test an app-staged membership` 1 hit each in
`index.js`, `index.cjs`, `runtime.js`, `runtime.cjs`; the old `The
registered names are: ${` 0).
- **CLI unit tier** on the rebuilt dist: Test Files 283 passed (283),
Tests 4,265 passed (4,265); VERDICT command-exit 0. No `packages/cli` or
`packages/metadata-protocol` test asserts these ids' hint text, so the
declared rider went unused.
- **Runtime gate:** the whole `@objectstack/metadata-protocol` suite,
after: Test Files 226 passed, 3 skipped (229), Tests 28,171 passed, 19
skipped; VERDICT command-exit 0.
- **Ablation** (one-shot, from the committed head `9d56f0f431`, through
`scripts/ablation-replace.mjs` under the lock, with a shell `trap`
restoring `HEAD` by absolute path). The rule suites import the rule
source, so there is no dist leg. `rls-predicate-unparseable`'s pre-slice
line was restored: `hint: UNPARSEABLE_FIX,` → the 523-character
SQL-to-CEL hint as one literal (anchor x1 → x0, blob `1e997b3fc7cc` →
`371d8e008841`). Predicted before the run: exactly the new bound pin
goes red, and the older `canonical CEL` / `&&` pins stay green.
Observed: `src/validate-rls-predicate-enforceability.test.ts` Tests 1
failed, 132 passed (133), exactly that pin, which read 523. Restored:
blob `1e997b3fc7cc` == HEAD, `git diff HEAD` empty, `git status
--porcelain` empty.
- **Corpus pins over `packages/lint/src`:** `pnpm --filter
@objectstack/spec test:repo` at `9d56f0f431`: Test Files 55 passed (55),
Tests 971 passed (971); VERDICT command-exit 0. No new text carries an
`os migrate meta --from` sentence, and no tracker id is in a printed
hint or explanation (citations stay in comments and test names).
- **ESLint, narrowed:** `npx eslint --no-inline-config --format json`
over the 24 changed `.ts` files: 24 files in the report, 0 errors, 0
warnings. The population is `eslint.config.mjs`'s `**/*.{ts,…}` block
plus its `packages/**` blocks; the config never enables type-aware
linting (no `parserOptions.project`), so no untouched file's verdict can
move. A control-character scan of every changed file found no match.
- **Gates:** one merge of `origin/main` through
`scripts/pm/os-regen-merge.sh` (`0cc2194a2b` → `26fe94f3e1`, onto
`9fdb12752c`; no conflict, and the branch edits no generated artifact).
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` with no paths at the final head `9d56f0f431`
(25 paths vs the merge base) derived 62 commands; 60 ran, each exit code
captured before any pipe, all 0 (longest: `check:query-options-erasure`
348s, `check:slot-lookup` 175s, `check-comment-mask-corpus` 142s). NOT
MEASURED, as dispatched: `check:dual-build-cjs-loads` (needs every
package's dist) and `check:type-check-debt` (its script is
`--re-measure`; `check:type-check-coverage` ran). `--ran`: `Run
reconciliation — 62 derived, 60 run, 2 NOT-MEASURED, 0 UNRUN.` The
artifact-roster block (51 families): the 48 that need no pull request
exited 0 at `9d56f0f431`, `check:published-readme-exports` after
building its four missing dists (`client-react`, `embedder-openai`,
`knowledge-ragflow`, `organizations`, 54 tasks) under the lock (its
first answer was the exit-3 prerequisite refusal, not a verdict); the
three PR-context guards run against this PR and report on the card.
- **Which tree each reading is from:** the lint suite and the census at
`26fe94f3e1` (the merge; `9d56f0f431` adds one changeset figure only);
the CLI unit tier, the metadata-protocol suite, `os validate` and the
runtime probe on the pre-merge head `0cc2194a2b`, whose hint text the
merge did not touch (main brought no change to the ten rule files or
`rule-explanations.ts`).
## Acceptance notes
- **A long name can still lengthen a line.** The bound holds on every
variant the suites, the runtime probe and the four example apps fire;
the names in a hint (the measure's column, the dimension's object and
field, the right-hand text, the action and related-object names, the
readonlyWhen field and object) are the author's. The closest measured
case is `action-name-undefined` at 195.
`rls-predicate-unknown-user-variable` and `rls-predicate-unparseable`
carry no author text at all.
- **The dropped lists now print nowhere on the CLI.** A near miss still
gets the verdict's "Did you mean"; a far miss of an object or action
name no longer sees the stack's whole list on the `fix:` line. The
card's "Asked for" names no list, and slice 11 made the same call for
`rls-predicate-unknown-field`'s field list.
- **Two `rule:` lines gain the `os explain` pointer**
(`object-reference-unknown`, `org-axis-permission-inheritance`), through
the new entries. That is the printer's own rule for an id the table
holds, not a printer change.
- **The bare-word right-hand line is two sentences**: the remedy, then
"Do NOT simply add the root in place", kept verbatim because
`runtime-gate.test.ts` (outside this slice's files) pins it.
- **The namespace remedy replaces the generic line on both
object-reference arms.** A platform-prefixed short name whose namespaced
spelling the stack declares gets that spelling alone, where it used to
get the generic platform text and then the spelling.
## Remaining for this card
**91 author-time `packages/lint` ids still carry a hint over 200
characters** in the final lint census (at `26fe94f3e1`: 115 over 200 =
91 + 21 fenced + 3 repo-gate), by file, longest first:
- `lint-flow-patterns.ts` (2): `flow-double-brace-interpolation` 1339,
`flow-bare-dollar-reference` 1231
- `lint-flow-credential-literals.ts` (1): `flow-credential-literal` 646
- `data-model-rules.ts` (6): `unique/legacy-organization-composite` 578,
`unique/unscoped-declared-index` 380, `object/missing-name-field` 327,
`rollup/non-numeric-aggregand` 282, `unique/double-declaration` 279,
`field/select-missing-options` 207
- `validate-widget-bindings.ts` (11):
`dashboard-filter-field-unprovisioned` 561, `chart-field-unknown` 415,
`dashboard-filter-field-unknown` 403, `chart-measures-missing` 369,
`widget-legacy-analytics-shape` 338, `widget-measures-missing` 330,
`widget-filter-field-unknown` 322,
`widget-legacy-analytics-unrenderable` 320, `table-count-only` 311,
`chart-dimensions-missing` 291, `dashboard-filter-field-not-included`
218
- `validate-readonly-flow-writes.ts` (2):
`flow-update-readonly-when-field` 549, `flow-update-readonly-field` 400
- `validate-action-dispatch-contract.ts` (1):
`action-dispatch-contract-mismatch` 514
- `validate-security-posture.ts` (5):
`security-controlled-by-parent-ambiguous-relation` 496,
`security-master-detail-ungranted` 314,
`security-controlled-by-parent-no-relation` 294,
`security-fls-unknown-field` 293, `security-wildcard-vama` 218
- `validate-sharing-rule-enforceability.ts` (2):
`sharing-rule-object-not-shareable` 482,
`sharing-rule-object-controlled-by-parent` 395
- `validate-page-visualization-bindings.ts` (1):
`page/visualization-without-binding` 480
- `validate-readonly-action-writes.ts` (1):
`action-api-update-readonly-when-field` 470
- `validate-flow-trigger-readiness.ts` (5):
`flow-api-trigger-secret-missing` 461,
`flow-time-relative-descriptor-unroutable` 441,
`flow-trigger-unroutable` 295, `flow-trigger-unknown-event` 268,
`flow-trigger-unknown-object` 210
- `validate-searchable-fields.ts` (3): `searchable-field-unknown` 448,
`searchable-field-unprovisioned` 362, `searchable-field-unsearchable`
328
- `validate-flow-filter-tokens.ts` (1): `flow-filter-token-unknown` 427
- `validate-action-locations.ts` (1): `action-no-placement` 424
- `validate-mapping-target-fields.ts` (1):
`mapping-target-field-unknown` 405
- `validate-dashboard-widget-options.ts` (1): `unconsumed-widget-option`
396
- `validate-sortable-fields.ts` (3): `sort-field-unprovisioned` 378,
`sort-field-unsortable` 332, `sort-field-unknown` 301
- `validate-visibility-predicates.ts` (3):
`visibility-predicate-unknown-function` 375,
`visibility-bare-identifier` 221, `visibility-predicate-syntax` 214
- `validate-nav-access.ts` (1): `nav-object-ungranted` 370
- `validate-hook-body-writes.ts` (3):
`hook-body-write-unprovisioned-anchor` 365,
`hook-body-write-unknown-field` 275, `hook-body-source-unparseable` 254
- `validate-ai-agent-authoring.ts` (2): `agent-authoring-withdrawn` 363,
`default-agent-outside-roster` 237
- `validate-react-page-props.ts` (4): `react-chart-field-unprovisioned`
362, `react-prop-missing-required` 277, `react-page-source-unparseable`
254, `react-block-needs-record-context` 228
- `validate-translatable-sections.ts` (1):
`translation-section-name-missing` 359
- `validate-action-body-writes.ts` (4):
`action-body-write-unprovisioned-anchor` 358,
`action-body-write-unknown-field` 323, `action-record-write-discarded`
309, `action-body-source-unparseable` 254
- `validate-flow-node-writes.ts` (2):
`flow-node-write-unprovisioned-anchor` 358,
`flow-node-write-unknown-field` 289
- `validate-managed-api-methods.ts` (1):
`object/managed-api-method-unaffordable` 357
- `validate-nav-object-servability.ts` (1): `nav-object-unservable` 348
- `validate-rule-compilability.ts` (2):
`validation-rule-json-schema-uncompilable` 341,
`validation-rule-regex-uncompilable` 300
- `validate-dataset-references.ts` (2): `dataset-include-unknown` 336,
`dataset-field-unknown` 206
- `validate-translation-references.ts` (1): `translation-target-unknown`
317
- `validate-approval-approvers.ts` (3):
`approval-approver-not-membership-tier` 313,
`approval-expression-no-empty-policy` 294, `approval-expression-invalid`
292
- `validate-seed-replay-safety.ts` (1):
`seed-insert-mode-duplicates-on-replay` 309
- `validate-chart-bindings.ts` (1): `chart-measure-unknown` 285
- `validate-object-field-refs.ts` (1): `object-field-ref-unknown` 284
- `validate-capability-references.ts` (1):
`capability-reference-unknown` 273
- `validate-record-title.ts` (2): `title-format-retired` 267,
`title-unresolvable` 237
- `validate-list-view-field-refs.ts` (2): `list-view-field-unknown` 258,
`list-view-field-dotted` 233
- `validate-view-containers.ts` (1): `view-container-shape` 256
- `validate-seed-state-machine.ts` (1):
`seed-value-outside-state-machine` 251
- `validate-ai-surface-affinity.ts` (1): `ai-skill-surface-mismatch` 235
- `validate-page-source-styling.ts` (1):
`page-source-className-tailwind` 231
- `lint-liveness-properties.ts` (1): `liveness-planned-property` 230
- `validate-list-view-mode.ts` (1): `list-view-filters-in-views-mode`
219
Not in the 91: the 26 fenced ids as PR #22448 lists them (21 fire a hint
over 200), the 3 repo-gate ids (`startup-open-vocabulary-verdict`,
`startup-source-unparseable`, `startup-verdict-assertive-wording`), and
the `packages/cli` ids on #22841.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01KNKBCRDJCu5tGy3TEbvtrF)_
---------
Co-authored-by: Claude <noreply@anthropic.com>os explain RULE_ID carries what they enumerated (#22909)1 parent 7de0265 commit 7dbb89d
25 files changed
Lines changed: 734 additions & 250 deletions
File tree
- .changeset
- packages/lint/src
| 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 | + | |
0 commit comments