Repository navigation
Commit 92ea760
Fixes #20525
Clause-②: no (narrowing)
The record validator's `date` / `datetime` arm now stores a real
calendar day and an ISO instant, or it refuses. A string whose leading
`YYYY-MM-DD` names a day that does not exist is refused, for a `date`
and for the day part of a `datetime`. A `datetime` string outside the
ISO 8601 spellings below is refused. Both answer `VALIDATION_FAILED` /
400 with the field code `invalid_date`, naming the field, before any
driver write. Nothing is rolled over, and nothing is read in the
server's zone. This executes triage's ruling on the card (5880930860),
Arm 1 and Arm 2 as written.
Measured head: `0999284ab`. It is the last change commit `5083d6742`
plus a true merge of `origin/main` `288611e3e` (two parents). The merge
brought spec, `driver-sql` and `platform-objects` changes. It touched no
file under `packages/objectql`, `packages/core`, `packages/rest` or
`packages/drivers/driver-memory`: those four trees are byte-identical
between `5083d6742` and `0999284ab`.
## The change
One source file changes:
`packages/objectql/src/validation/record-validator.ts`, +72 / −2.
- Two private helpers sit beside `validateOne`. Neither is exported, and
`packages/core` is not edited.
- `namesRealCalendarDay(s)`: the leading `YYYY-MM-DD` has month 01..12
and a day from 01 to that month's length, with February 29 only in a
leap year. It is arithmetic, not a `Date` round trip.
- `ISO_DATETIME_WRITE_FORM`: the admitted `datetime` grammar, below.
- The arm's verdict line gains one conjunct: `readable && readsAsDay &&
writtenAsIso && !isOutsideTemporalYearRange(value, t)`.
- `writtenAsIso` is `true` for a non-string.
- For a string it is `writesAsIsoTemporal(value, t)`. Both kinds need a
real leading day, and a `datetime` must also match the grammar, after
trimming.
- A `Date` and a number go through the arm exactly as before. The `time`
arm is not in the diff.
### The admitted `datetime` grammar (H3)
After trimming, a `datetime` string is one of:
- `YYYY-MM-DD`, midnight UTC;
- `YYYY-MM-DDTHH:MM[:SS[.fraction]]`, then `Z`, a `±HH:MM` or `±HHMM`
offset, or nothing. With nothing, the wall clock is read as UTC
(ADR-0074).
- `YYYY-MM-DD HH:MM[:SS[.fraction]]`, zone-naive only, and read as UTC
the same way.
On top of that, the leading day is real, `Date.parse` reads the string
(so `T25:00` and a `+99:99` offset stay refused), and the year is
0001..9999.
Each admitted spelling was read through core's `temporalStorageForm`
under four host zones: `UTC`, `America/New_York`, `Asia/Shanghai` and
`Pacific/Kiritimati`. All 34 probes gave the same instant in every zone.
That includes years 0050, 0100 and 0999, fractions of any length,
`+0800` offsets and `T24:00` (the end of the named day, stored as the
next day's `00:00Z`).
Refused by the grammar, with the reason for each borderline case:
- **A space separator with a zone** (`"2026-07-15 10:00Z"`, `"2026-07-15
10:00:00+08:00"`). The storage rule hands such a string to `Date.parse`
whole, and its non-ISO reading moved `"0050-01-01 10:00+01:00"` to
`1950-01-01T09:00:00.000Z` in all four zones. The `T` spelling of the
same value is read correctly.
- **Lower-case `t` / `z`**. The storage rule's zone-naive branch matches
an upper-case `T` only. A zone-naive `"…t10:00"` would reach
`Date.parse` and be read in the host zone.
- **Reduced precision** (`"2026"`, `"2026-07"`) and **an expanded year**
(`"+002026-07-15T10:00:00Z"`). These are not spellings the platform
writes. `"2026"` was stored as 2026 epoch milliseconds
(`1970-01-01T00:00:02.026Z`). The `date` arm already refuses
`"+002026-07-15"` since #20481.
## H1: before and after, at the public door
`POST /api/v1/data/:object`, then a read-back through `POST
/api/v1/data/:object/query`. The process ran in `TZ=America/New_York`
(offset 240 on 2026-07-15). PostgreSQL 16 was a private local server at
`Asia/Shanghai`, `DateStyle` `ISO, MDY`. The base is `b2b6a0643`. The
head column was measured on the fix at `5083d6742`, and the source trees
it reads are the ones at `0999284ab`.
H1 holds as the dispatch wrote it, on every cell.
**Arm 1, an impossible day:**
| written | memory, base | SQLite, base | PostgreSQL, base | head, all
three |
|:--|:--|:--|:--|:--|
| `date` `"2026-02-30"`, `"2026-02-29"`, `"2026-04-31"`,
`"2026-02-30T10:00:00Z"` | 201, read back as written (`"2026-02-30"`, …)
| the same | 500 `DATABASE_ERROR` | 400 `invalid_date` |
| `datetime` `"2026-02-30T10:00:00Z"`, `"2026-02-30 10:00"` | 201,
`"2026-03-02T10:00:00.000Z"` | the same | the same | 400 `invalid_date`
|
| `datetime` `"2026-02-30"` | 201, `"2026-03-02T00:00:00.000Z"` | the
same | the same | 400 `invalid_date` |
| `datetime` `"2026-02-29T10:00:00Z"` | 201,
`"2026-03-01T10:00:00.000Z"` | the same | the same | 400 `invalid_date`
|
| `date` `"2028-02-29"` (the leap-day control) | 201, `"2028-02-29"` |
the same | the same | unchanged |
| `datetime` `"2028-02-29T10:00:00Z"` (the leap-day control) | 201,
`"2028-02-29T10:00:00.000Z"` | the same | the same | unchanged |
**Arm 2, a non-ISO `datetime`:**
| written to a `datetime` | memory, base | SQLite, base | PostgreSQL,
base | head, all three |
|:--|:--|:--|:--|:--|
| `"2026/07/15 10:00"`, `"07/15/2026 10:00"`, `"15 July 2026 10:00"` |
201, `"2026-07-15T14:00:00.000Z"`, the process zone | the same | the
same | 400 `invalid_date` |
| `"07/08/2026"` | 201, `"2026-07-08T04:00:00.000Z"`, month-first in the
process zone | the same | the same | 400 `invalid_date` |
| `"2026-07-15 10:00 PM"` | 201, `"2026-07-16T02:00:00.000Z"` | the same
| the same | 400 `invalid_date` |
| `"2026"` | 201, `"1970-01-01T00:00:02.026Z"` | the same | the same |
400 `invalid_date` |
| `"2026-07"` | 201, `"2026-07-01T00:00:00.000Z"` | the same | the same
| 400 `invalid_date` |
| `"Wed, 15 Jul 2026 10:00:00 GMT"`, `"2026-07-15t10:00:00z"`,
`"+002026-07-15T10:00:00Z"`, `"2026-07-15 10:00Z"` | 201,
`"2026-07-15T10:00:00.000Z"` | the same | the same | 400 `invalid_date`
|
| `"2026-07-15 10:00:00+08:00"` | 201, `"2026-07-15T02:00:00.000Z"` |
the same | the same | 400 `invalid_date` |
**Controls:**
| written | memory, base | SQLite, base | PostgreSQL, base | head, all
three |
|:--|:--|:--|:--|:--|
| `datetime` `"2026-07-15 10:00"`, `"2026-07-15 10:00:00"`,
`"2026-07-15T10:00"`, `"2026-07-15T10:00:00Z"` | 201,
`"2026-07-15T10:00:00.000Z"`, UTC and not the process zone | the same |
the same | unchanged |
| `datetime` `"2026-07-15T10:00:00+08:00"`, `"2026-07-15T10:00:00+0800"`
| 201, `"2026-07-15T02:00:00.000Z"` | the same | the same | unchanged |
| `datetime` `"2026-07-15T10:00:00.123Z"`, `"2026-07-15T24:00:00Z"`,
`"2026-07-15"`, `"0050-01-01"`, `"0050-01-01T10:00:00Z"` | 201, the same
instant | the same | the same | unchanged |
| `date` `"2026-07-15"`, `"0050-01-01"` | 201, as written | the same |
the same | unchanged |
| an epoch-millisecond number, and the string `"1784109600000"` | 400
`invalid_date` | 400 | 400 | unchanged |
| a `Date` (engine, since JSON carries none) | accepted | accepted |
accepted | unchanged |
## H2: one calendar-day predicate, private to objectql
No reusable core helper exists.
- `packages/core/src/utils/filter-tokens.ts` has a private
`daysInMonth`.
- `packages/spec/src/data/calendar-day.ts`'s exported
`nextUtcCalendarDay` is the one public real-day check. It is a
`Date.UTC` round trip, and `Date.UTC` reads years 0..99 as 1900..1999.
So it answers `null` for `"0050-01-01"`, a supported year since #20264,
and reusing it would have refused a date the door accepts today. The
same holds for `utcInstantMs`. That is reported below as a finding.
The predicate is therefore a private arithmetic helper in the validator.
No core export is added, so the claim's `Clause-②: no (narrowing)`
holds, and only `@objectstack/objectql` carries a changeset. It can be
lifted into core as a move if the comparand door later takes the same
answer (H5).
## H4: producer census
Read at objectstack `0999284ab` / `b2b6a0643` and objectui `origin/main`
`0eb9f36`.
- **Seeds and examples.** Seed loaders write through `engine.insert` /
`engine.update`, so they are validated.
- A literal census over the 256 tracked files under `examples/**` found
41 ISO temporal literals in 5 files (the positive control). It found 0
`Date.parse`-readable non-ISO literals and 0 impossible-day literals.
- A grep for `toLocale*` / `toUTCString` / `toDateString` / `String(new
Date(…))` feeding a record over `examples/**` and non-test `packages/**`
found no temporal field producer.
- **Flows and formulas.** CEL `now()` returns a `Date`, which is
admitted as before. No string formatter of a date feeds a record in
`packages/formula` or `service-automation`.
- **objectui writers.** All are ISO.
- `DateTimeField` sends `fromDateTimeInputValue`, which is
`toISOString()`. An impossible day is returned untouched there "because
the engine would re-emit it as the rolled day" (objectui
`native-date-value.ts`). The engine now refuses it, which is the answer
that comment wanted.
- The calendar and gantt `datetime` writers use `toISOString()`.
- The action and bulk param widgets map `datetime-local` to that same
`DateTimeField`.
- **AI / MCP.** `create_record` / `update_record` pass values through. A
model-written non-ISO `datetime` now gets the 400 back as the tool
error.
- **`/import` (`packages/rest/src/import-coerce.ts` `parseDateCell`).**
Measured at `POST /api/v1/data/:object/import`, `TZ=America/New_York`,
no business timezone, on memory, SQLite and PostgreSQL.
- A `date` cell `2026-02-30`: at the base, memory and SQLite stored
`"2026-02-30"` and PostgreSQL failed the row with `22008`. At head it is
a per-row `invalid_date` on all three. That is the intended loud answer
(H4), not a producer to fix.
- A `datetime` cell is turned into ISO text by the importer itself,
before this door, so this card does not change it. Three readings there
are not ISO-faithful:
- `2026-02-30`, `2026-02-30 10:00` and `2026-02-30T10:00:00Z` are stored
as March 2 (`Date.UTC` / `Date.parse` roll the day over);
- `07/15/2026 10:00` is stored as `2026-07-15T14:00:00.000Z` (the
process zone);
- `07/08/2026` is stored as `2026-07-08T04:00:00.000Z` (month-first, the
process zone).
- `import-coerce.ts` is outside this claim's surface, so these are
reported, not edited. The zone and locale half is an import-format
question, raised for a decision.
- **driver-sql's `canonicalUtcDatetime`** (measured only) is today a
one-line delegate to core's `temporalStorageForm`. It has no private
reading left to diverge. No census write path reaches a driver around
`validateRecord`.
## H5: the comparand door keeps its own answer, and diverges
Measured through `POST /api/v1/data/:object/query` at head,
`TZ=America/New_York`. The comparand door (`temporal-comparand-door.ts`,
core's `isUninterpretableTemporalComparand`) is not edited.
| `where` | memory | SQLite | PostgreSQL |
|:--|:--|:--|:--|
| `placed_on $eq "2026-02-30"` (a `date`) | admitted, 200, `[]`
(compared as text) | the same | 500 `DATABASE_ERROR` |
| `opened_at $eq "2026-02-30T10:00:00Z"` | admitted and **rolled over**:
matches the row stored at `2026-03-02T10:00:00.000Z` | the same | the
same |
| `opened_at $eq "2026/07/15 10:00"`, `"07/15/2026 10:00"` | admitted,
read in the **process zone**: matches the row at
`2026-07-15T14:00:00.000Z` | the same | the same |
So an impossible day is admitted as a comparand on both kinds: a `date`
is compared as text or is a 500 on PostgreSQL, and a `datetime` is
rolled over. A non-ISO `datetime` comparand is read in the host zone.
The write door is now strictly narrower. #20481's "a `date` string
refused as a comparand is refused as a written value too" still holds,
and its converse no longer does for an impossible day. This is reported
as an out-of-scope finding. Sharing the predicate would change the
comparand door's answer for every `where`, `filter` and `having`, so it
is not the costless same-predicate change the dispatch allows.
## Tests
- `packages/objectql/src/engine-temporal-write-real-day-iso.test.ts`
(new, 3 tests, recording driver).
- It covers 9 impossible-day values across both kinds, 12 non-ISO
`datetime` spellings and 4 already-refused values, including an epoch
number.
- Each is tried on insert, update, a multi-row update and
`engine.validate`. Each asserts `code` `VALIDATION_FAILED` and `fields`
exactly `[field, invalid_date]`, with zero driver writes.
- The positive control has 21 values: the leap days, each grammar form,
a leading blank, year 0050 and a `Date`. Each reaches the driver
unchanged on every door.
- `packages/rest/src/data-temporal-write-real-day-iso.test.ts` (new, 3
tests per cell).
- It sends `POST` and `PATCH` over a real `SqlDriver`, with the process
switched to `America/New_York` and the switch asserted. SQLite always
runs. Live PostgreSQL runs where `OS_TEST_POSTGRES_URL` is set and is a
named skip otherwise.
- The card's `2026-02-30` for both kinds and its four non-ISO spellings
each assert 400, `VALIDATION_FAILED` and the field code, with no write.
The existing row keeps its values.
- There is an epoch-number control. The leap days and the ISO spellings
read back unchanged in UTC, `"2026-07-15 10:00"` as `…T10:00:00.000Z`
and not `…T14:00Z`.
-
`packages/drivers/driver-memory/src/memory-20525-temporal-write-real-day-iso.test.ts`
(new, 2 tests). Under `America/New_York`, each admitted `datetime`
spelling and a `Date` is stored as its UTC instant and found by it. The
leap day is stored as itself.
**Reverse verification.** The fix was committed first.
- **objectql (src):** `scripts/ablation-replace.mjs` removed
`writtenAsIso` from the verdict line.
- The mutation landed: anchor 1 → 0, blob `e51b0aff89c1` →
`fe92054de0c4`.
- The new engine file went 2 failed / 1 passed. The positive control
stays green, as it should.
- The tool restored the file: blob equals HEAD, and `git diff HEAD` is
empty.
- **REST (reads `@objectstack/objectql` from `dist`).**
- The first attempt was a no-run. Deleting the conjunct left
`writtenAsIso` unused, the DTS build failed with TS6133, and no test
ran.
- Re-anchored: `writesAsIsoTemporal(value, t) || value.length >= 0`
(blob `e51b0aff89c1` → `0782d15e00fb`), then an objectql rebuild.
`ablation-dist-preflight` found the marker in 4 built files. The new
REST file went 2 failed / 4 passed: the refusal test was red on SQLite
and on live PostgreSQL, and both controls were green.
- Restore leg: the source was back to HEAD, and objectql was rebuilt.
The preflight found the ablation marker absent from all 14 built files,
the tree clean, and the fix marker present in 4. The REST file then
passed 6/6.
Suites:
- **objectql, at `5083d6742`:** `--project local` 334 files / 6643
passed. `test:repo` 1 / 5. `typecheck` exit 0. `check:test-typecheck`
compiles the new file (`--listFiles` lists it), with the debt unchanged
at 40 files / 234 errors / 65 signatures.
- **rest, at `5083d6742`:** `--project local` 224 files, 4241 passed /
46 skipped. `test:repo` 1 / 8. `typecheck` exit 0, and test-typecheck
debt is 0.
- **driver-memory, at `5083d6742`:** 61 files / 1423 passed. `typecheck`
exit 0, and its `tsconfig.json` program lists the new file.
- **The three new files and #20481's three, at `0999284ab`, after the
merge and a closure rebuild:**
- objectql: 2 files, 7 / 7;
- rest: 2 files, 12 / 12, SQLite and live PostgreSQL 16, 0 skipped;
- driver-memory: 2 files, 4 / 4.
## Gates at `0999284ab`
- **`dispatch-gates --commands --repo objectstack-ai/objectstack`:** 65
commands. Each was run with its exit code captured before any pipe, and
63 exited 0. `check-adr-0087-registration` reads the changeset as
`[BREAKING+bang+clause-②-narrowing] not-required
(no-migration-prescription)`, exit 0.
- **NOT MEASURED: `check:dual-build-cjs-loads`,
`check:type-check-debt`.** Both exit 3 `PREREQUISITE NOT MET`, because
they need the whole tree built. Only the rest and driver-memory closures
are built here. Scoped reading: both `require` entries of
`@objectstack/objectql` load from the rebuilt `dist`, `.` with 178
exports and `./core` with 52.
- **`--ran` reconciliation:** 65 derived, 63 run, 2 NOT-MEASURED
(derived from the recorded exit 3), 0 UNRUN.
- **Narrowed lint:** `eslint --no-inline-config --format json` over the
4 changed TS files gave 4 files, 0 errors and 0 warnings.
`--print-config` shows no `parserOptions.project` or `projectService` on
any of them. Type-aware linting is off, so this diff cannot move a
verdict on an untouched file. The repo-wide `pnpm lint` is CI's.
## Acceptance notes
- **REST on memory** is not a cell of the committed REST file, as on
#20481. `@objectstack/driver-memory` has no binding in `packages/rest`,
and a new binding is a census disposition. Memory is covered three ways:
- the engine pin (the refusal reaches no driver);
- the driver-memory pin;
- the H1 table, measured through `RestServer` over `InMemoryDriver` with
a scratch script that was not committed.
- **The refused ISO-adjacent spellings are a deliberate reading of "an
ISO 8601 string is admitted":** space plus zone, lower case, reduced
precision and the expanded year. The measured reason for each is in the
grammar section. The changeset names them.
- **The `invalid_datetime` message** ("must be a valid datetime
(ISO-8601)") now states the rule exactly. The `date` message is
unchanged.
- **Not edited, by the claim:** the `time` arm (#20480),
`packages/spec`, `import-coerce.ts` (#20534 holds that file),
driver-sql, and the comparand door. `driver-mongodb` keeps its own
storage copy and is unmeasured here. The refusal sits in the engine in
front of it.
- **Out of scope, measured and reported to the seat with public-door
readings:**
- the comparand door (H5);
- `/import`'s `datetime` rollover and process-zone reading (H4);
- spec's `nextUtcCalendarDay` / `utcInstantMs` refusing years
0001..0099. A `datetime` `where … $lte "0050-01-01"` returns `[]` on all
three backends, while the control `$lte "2026-07-15"` includes that
day's 14:00Z row.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8538edf commit 92ea760
5 files changed
Lines changed: 593 additions & 2 deletions
File tree
- .changeset
- packages
- drivers/driver-memory/src
- objectql/src
- validation
- rest/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 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 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 | |
|---|---|---|---|
| |||
| 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 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
0 commit comments