Repository navigation
Commit dfd8e39
fix(spec): os migrate meta guidance for the ui-* and plugin-* migration entries states each lesson in words, not tracker numbers (stage 2) (#20324)
Part of #20233
Clause-②: no
**Stage 2 of a staged card.** The card stays open for later stages; this
PR carries no closing keyword. Text only: no entry id, `from` / `to`,
conversion or matching logic moves, and the chain rewrites exactly what
it rewrote before.
## What this does
`os migrate meta` prints every ADR-0087 semantic entry it crosses as one
block: `⚠ [protocol N] SURFACE → REPLACEMENT`, then `why:` (the entry's
`reason`) and `verify:` (its `acceptanceCriteria`). AGENTS.md's
runtime-string rule applies to all of it: 「Runtime strings — refusal
prose, prescriptions, anything an author is shown — carry no tracker
number (`pnpm check:doc-authoring`): the lesson goes into the text.」
Form **D** of ruling C+D on the parent card sets the shape: the lesson
in words, and no number, dead or alive.
This stage covers the next two families by site count, `ui-` and
`plugin-`: **111 sites → 0** in the three prose fields, plus the
`surface` field of the two entries that carried an id there (ruling A in
the stage-1 ACCEPT, `5858839916`). Each site now says what the cited
ruling, measurement or fix decided. ADR ids stay. `registry.ts`,
`spec-changes.json` and `docs/protocol-upgrade-guide.md` are regenerated
from the entries (`gen:migration-registry`, `gen:spec-changes`,
`gen:upgrade-guide`), never hand-edited. The stage-1 pin is widened to
hold `engine-`, `ui-` and `plugin-`.
## Census — tracker ids in the author-shown fields
**Instrument.** The stage-1 instrument, re-implemented: a TypeScript-AST
walk over every `packages/spec/src/migrations/entries/**/*.ts`. For each
`entry` object literal it evaluates the string value of `replacement`,
`reason`, `acceptanceCriteria` and (counted separately) `surface`,
joining string literals with `+`, then counts `#` followed by 4 or 5
digits at a word boundary. **Tree:** `objectstack-ai/objectstack` at
`2aa25efb4e` (this branch's base, the stage-1 merge). Unevaluable
fields: 0.
**Controls, same run.**
- **Lit:** `17.aggregation-node-distinct-retired.ts` reads 7 sites
(replacement 1, reason 6), the same reading stage 1 took.
- **Dark (comment lines):** 734 `//` lines in entry files carry a
tracker id, and none is counted — for example
`18.client-envelope-convergence-analytics-automation.ts` has 5 such
lines and counts 0. Comment lines belong to the sibling card, and ⛔ this
PR touches none (the count is 734 before and after).
- **Dark (field boundary):**
`17.authoring-schemas-strict-unknown-keys.ts` carries one id in
`surface`; it counts 0 in the three-field total and 1 in the `surface`
column.
**Re-measured on the base, matching the stage-1 census:** `ui-` 17
entries, **65** sites (replacement 6 / reason 58 / acceptanceCriteria
1), 42 distinct ids; `plugin-` 11 entries, **46** sites (1 / 39 / 6), 31
distinct ids. `surface`: 1 site each. `engine-`: 0 (stage 1). Whole
tree: 267 entries, **950** sites, 9 `surface` sites.
**After this PR:** `ui-` 0, `plugin-` 0, `engine-` 0; whole tree **950 →
839** sites and `surface` **9 → 7**. The next family by site count is
`driver-` / `kernel-` / `system-` (44 each).
| entry | sites (replacement / reason / acceptanceCriteria) | `surface`
|
|---|---|---:|
| `17.plugin-activation-events-retired` | 5 (0 / 4 / 1) | 0 |
| `18.plugin-auto-restart-never-reinitialised` | 11 (0 / 7 / 4) | 0 |
| `18.plugin-manifest-contributes-dead-members-retired` | 3 (0 / 2 / 1)
| 0 |
| `18.plugin-manifest-contributes-routes-retired` | 6 (1 / 5 / 0) | 1 |
| `18.plugin-manifest-dead-containers-retired` | 3 (0 / 3 / 0) | 0 |
| `18.plugin-manifest-kind-globs-retired` | 2 (0 / 2 / 0) | 0 |
| `17.plugin-manifest-loading-retired` | 2 (0 / 2 / 0) | 0 |
| `17.plugin-runtime-family-retired` | 5 (0 / 5 / 0) | 0 |
| `18.plugin-security-scan-result-surface-retired` | 6 (0 / 6 / 0) | 0 |
| `18.plugin-security-scanner-retired` | 3 (0 / 3 / 0) | 0 |
| `18.ui-cloud-connection-widgets-unknown-keys-refused` | 3 (0 / 3 / 0)
| 0 |
| `18.ui-form-field-length-malformed-refused` | 8 (2 / 6 / 0) | 0 |
| `18.ui-form-field-precision-scale-integer-refused` | 4 (1 / 3 / 0) | 0
|
| `18.ui-form-view-predicate-features-root-refused` | 2 (0 / 2 / 0) | 0
|
| `17.ui-interaction-config-family-retired` | 7 (1 / 6 / 0) | 0 |
| `18.ui-list-view-groupbyfield-padded-refused` | 1 (0 / 1 / 0) | 0 |
| `18.ui-list-view-grouping-field-padded-refused` | 2 (0 / 2 / 0) | 0 |
| `18.ui-mcp-connect-agent-unknown-keys-refused` | 5 (0 / 5 / 0) | 0 |
| `17.ui-notification-action-embed-config-retired` | 8 (0 / 8 / 0) | 0 |
| `18.ui-object-grid-page-size-positive-integer-refused` | 4 (0 / 4 / 0)
| 0 |
| `18.ui-react-list-view-binding-aliases-retired` | 2 (0 / 2 / 0) | 1 |
| `18.ui-record-blocks-unknown-keys-refused` | 3 (0 / 3 / 0) | 0 |
| `18.ui-reference-rail-unknown-keys-refused` | 2 (0 / 2 / 0) | 0 |
| `17.ui-widget-i18n-family-retired` | 14 (2 / 11 / 1) | 0 |
| four entries with no site: `plugin-version-semver-2-0-0`,
`ui-action-undoable-unfulfillable-refused`,
`ui-bulk-action-param-unknown-keys-refused`,
`ui-report-joined-container-selection-refused` | 0 | 0 |
| **total, 28 entries** | **111 (7 / 97 / 7)** | **2** |
## Every citation read, and what the text now says
I read each cited issue or PR myself with single-card REST reads: the
body, and the comments where a ruling or a measurement lives. Ids are in
code spans so this body posts no cross-references. `objectui#N` ids were
read from `objectstack-ai/objectui`; bare ids from this repository.
| cited | what it decided (read) | how the text now carries it |
|---|---|---|
| `#3733` | The pruned `cached` field key: the parse succeeded and the
removed key was dropped without a word; the orphan schema was deleted. |
"an earlier field-key prune measured exactly that — the parse succeeded
and the removed key was dropped without a word" |
| `#3950` | Removed the plugin sandboxing / integrity / approval config
nothing read: an exported schema with no consumer is read as a
capability. | "the lesson of the unwired plugin sandboxing / integrity /
approval config …: an exported schema with no consumer is read as a
capability", and the plugin-runtime "earlier removal of this module's
discovery/sandbox config island" |
| `#4001` | Maintainer, 2026-08-03: every authorable surface refuses an
unknown key (strict), in the v17 window, measured file by file for an
authoring door. | "the component-props unknown-key gate (an authorable
surface refuses a key it does not declare …)"; "the v17 unknown-key
strictness sweep (its ui/ batch 14)"; "the batch of the v17 unknown-key
strictness sweep that measured this file as having no authoring door" |
| `#4115` | Ruling A: an objectui symbol named like a spec export must
import it, or take a name of its own (or an allowlist row), enforced by
a CI guard. | "renamed off the spec's names under objectui's rule that a
symbol named like a spec export must import it or take a name of its
own" |
| `#4484` | `findStream` removed with no tombstone: a TS/API surface
nothing parses, so tsc at the call site carries the ban. |
"`contracts.IDataDriver.findStream` (removed with no tombstone, because
nothing parses a driver object)" |
| `#4535` | The dual-source cleanup: 52 names declared twice across
entry points, taken to 0. | "the dual-source cleanup removed the `./ui`
copies …" |
| `#4583` | The datasource capability flags were dead; `readOnly` was
precisely validated and inert, and the CRM example called a datasource a
read replica while writes went through. The strictness ledger records
the "more convincing lie" lesson there. | "(the lesson of the datasource
capability flags: `readOnly` was precisely validated and read by
nothing, while a shipped example called a datasource a read replica and
wrote through it)" |
| `#4610` | Removed the `./ui` `Notification` / `NotificationConfig`
copies (zero import sites measured); the `./api` inbox row stayed live.
| "the dual-source cleanup removed the `./ui` copies of
`NotificationSchema` / `NotificationConfigSchema` (the same names
declared differently on other entry points)" |
| `#4653` | Maintainer ruling A, 2026-08-02: converge `activationEvents`
on the kernel's structured `{ type, pattern }` shape, re-exported from
studio. | "once the kernel and studio copies had converged on the
kernel's structured `{ type, pattern }` shape" |
| `#4657` | Retire both `activationEvents` keys (REMOVE, v17 window):
kernel tombstone, studio strict refusal, the orphan schema deleted. |
"Both keys took ADR-0049's REMOVE answer, not ENFORCE, while protocol 17
was still unreleased"; its id sentence in plugin-runtime is covered by
the entry id `plugin-activation-events-retired` |
| `#4834` | Maintainer, 2026-08-03: REMOVE the rest of the
plugin-runtime family; hot loading returns with its implementation, if
ever. | "The maintainer's ruling of 2026-08-03 is that decision,
answered REMOVE: …"; "the maintainer's REMOVE ruling on the rest of the
plugin-runtime family"; `plugin-runtime-family-retired` by id elsewhere
|
| `#4875` | The health-check timeout guard is cleared when the race
settles, and deliberately not `unref`'d (an unref'd guard can swallow
the timeout). | "its guard timer (kept ref'd while the race is
undecided, cleared the moment it settles)" |
| `#4910` | Inbound rate limiting was built from a new seam: a `server:`
key that carries only the keys its executor consumes. | "the way inbound
rate limiting came back, as a new key carrying only what its executor
consumes" |
| `#4914` | Maintainer, 2026-08-04: REMOVE `manifest.loading`, with a
hard precondition of a clean cloud and objectui bare-name sweep. | "the
maintainer ruled REMOVE on 2026-08-04, on condition that a bare-name
sweep of cloud and objectui came back clean first" |
| `#4938` | Maintainer, 2026-08-04: retire `HttpServerConfig`'s seven
unreachable keys with their container. | "the `HttpServerConfig`
retirement (seven keys no runtime read and no authoring door reached,
retired with their container)" |
| `#4988` | Maintainer, 2026-08-04: retire the five ui interaction
files; touch, dnd, keyboard and motion are renderer built-in behaviour,
offline belongs to a sync engine. | "The 2026-08-04 ruling retired the
family — touch, drag-and-drop, keyboard and motion are renderer built-in
behaviour and offline belongs to a sync engine …";
`ui-interaction-config-family-retired` by id in the widget entry |
| `#5015` | REMOVE `NotificationActionSchema` / `EmbedConfigSchema`,
2026-08-04: a no-door dead surface retires implementation-first, as
three same-shape rulings that week had decided. | "left the disposition
to ADR-0049's enforce-or-remove, which came back REMOVE on 2026-08-04: a
dead surface with no authoring door retires implementation-first, …" |
| `#5021` | Maintainer, 2026-08-04: retire all nine unconsumed theme
token groups; theme-driven typography is not near-term. | "the
theme-token retirement (theme-driven typography is not a near-term
capability, so nine token groups nothing consumed were retired)" |
| `#5040` | Build the declarative ApiEndpoint executor in 17.x; the v17
loud refusal of a non-empty `apis:` becomes execution. | "live since
protocol 17, once the declarative endpoint executor was built and the
loud refusal of a non-empty `apis:` became execution" |
| `#5055` | Maintainer, 2026-08-06: retire the doorless widget and i18n
shapes (8 of 9 widget sites; `FieldWidgetProps` kept). | already stated
by the entry ("The 2026-08-06 ruling weighed …"); the trailing id is
dropped |
| `#5068` | Maintainer, 2026-08-05, direction A: parse a component's
`properties` against its `ComponentPropsMap` row by `type`, at publish
and lint; a type with no row is skipped because the type union is open.
| "the props gate's dispatch (it parses `properties` against the type's
row at publish and lint time, and skips a type with no row because the
type union is open)" |
| `#5781` | Correction: objectui did re-export the `./ui` notification
names; the removal stands. | "falsified for objectui, which re-exported
both names, … the removal itself stands" |
| `#6011` | Maintainer: close the `ctx.user` `roles` alias now, no
window. | "`actor-user-roles-to-positions` (the `ctx.user` `roles`
alias, closed at once on the maintainer's word rather than given a
window)" |
| `#7751` | Maintainer, 2026-08-12, direction A: the `object-*` blocks
get `ComponentPropsMap` rows, key sets from renderer read points. | "the
shape it was given when the `object-*` blocks first got
`ComponentPropsMap` rows measured from their read points" |
| `#8321` | `Field.scale` / `precision` refuse non-integer and negative
values (`int().min(0)`). | "(that surface tightened first, to a
non-negative integer)"; "after that surface converged on
`z.number().int().min(0)`" |
| `#8691` | A strict `record:reference_rail` row, key set from the
renderer's read points. | "the class already closed for
`record:reference_rail` …"; "after the rail was given its strict row" |
| `#8744` | Strict rows for `record:alert` / `record:quick_actions` /
`record:history`. | "… and then for `record:alert` /
`record:quick_actions` / `record:history`, each by declaring a strict
`ComponentPropsMap` row" |
| `#11168` | The kind-registration log names the declared `id`; the
`kind` bucket is reachable through `GET /metadata/:type`; `globs` had
zero readers. | "Measured by the engine-lane fix that made kind
registration log its declared `id` (which also found the `kind` bucket
itself reachable …)" |
| `#11169` | Maintainer, 2026-08-24 (「接受你的建议。」): remove `globs` through
the full ADR-0049 ceremony. | "maintainer ruling 2026-08-24 (「接受你的建议。」)
…: remove, through the full ADR-0049 ceremony" |
| `#11327` | The doc-correction half of the routes ruling (2026-08-22,
「接受所有」, Option B): four author-facing sites redirected to the imperative
`http.server` mount. | "the author-facing corrections landed FIRST (the
skill's decision table, the dispatcher protocol doc, ADR-0088:40 and
app.mdx, each redirected to the imperative mount)"; the ruling sentence
states Option B's content |
| `#11566` | Maintainer, 2026-08-24: `maxLength` →
`z.number().int().min(1)`. | "`maxLength` by the maintainer's 2026-08-24
ruling"; "tightened first, to a positive integer, by maintainer rulings"
|
| `#11575` | Strict, empty rows for `cloud-connection:panel` /
`marketplace:installed-list`. | "the strict, empty
`cloud-connection:panel` / `marketplace:installed-list` rows closed the
previous two" |
| `#11825` | Maintainer, 2026-08-25: retire the declarative
`AdvancedPluginLifecycleConfig` container; the classes stay a
host-driven library. | "which is why the maintainer retired its
declarative config container on 2026-08-25 and kept the classes as a
host-driven library"; "The maintainer's 2026-08-25 keep of the
host-driven library still stands" |
| `#11852` | Both failure routes (returned, thrown or timed out) funnel
into one failure step: one counter, one threshold comparison. | "the two
failure routes — a returned failure and a thrown or timed-out check —
sharing one failure counter and one threshold comparison" |
| `#11949` | Maintainer, 2026-08-25, option B: `minLength` →
`int().min(1)`, zero refused. | "`minLength` by the 2026-08-25 one,
which refused zero too" |
| `#11955` | `successThreshold` binds from every status that records a
failure. | "The fix that made `successThreshold` bind from every status
that records a failure made that MORE convincing" |
| `#12174` | The form-field row keys are live, so they were
shape-tightened in place on the object-field templates. | "The
form-field row still carried the object field's old shape … The row keys
are LIVE … The schema now refuses …" (unchanged tail) |
| `#12269` | Closure A: `packages/mcp` gets its own canonical-envelope
gate. | "door 3 of the canonical-envelope gate `@objectstack/mcp` was
given for its shipped page" |
| `#12340` | Maintainer, 2026-08-26: retire the `'disk'` /
`'distributed'` state strategies (silent memory fallbacks) and
`distributedConfig`; "a vocabulary of nothing is not a vocabulary". |
"the `'disk'` / `'distributed'` state strategies that fell back to
memory in silence"; "(ruled 2026-08-26: a vocabulary of nothing is not a
vocabulary)" |
| `#12400` | The cloud leg for `capabilities` / `configuration` /
`extensions` measured clean at cloud `15f55df`. | "dispatched once the
cloud half of the census below came back clean" (the census clause names
`15f55df`) |
| `#12428` | Refuse/retire: `startWatching` throws instead of logging
success; `watchPatterns` is tombstoned because a key leaving a surviving
def has no route-3 exit. | "the file-watching placeholder whose
`startWatching` logged success while watching nothing"; "for the reason
the file-watching retirement recorded" |
| `#12665` | Implement the maintainer's 2026-08-27 option B: a form view
may not name `features.*` in a predicate; refused at authoring. | "Ruled
by the maintainer on 2026-08-27 (option B — vocabulary narrowing: a form
view may not name `features.*` in a predicate, and the authoring door
refuses it loudly)" |
| `#14791` | Maintainer, 2026-09-07: retire the `objectName` /
`viewType` aliases now, no window. | "(2026-09-07)" in the sentence that
states the retirement |
| `#15513` | Maintainer, 2026-09-05: retire the incident-response,
training and change-management families whole; not roadmapped. |
"retired whole, with the training and change-management families
(maintainer ruling 2026-09-05: not roadmapped, so retired rather than
marked experimental …)" |
| `#15930` | Retired `PluginSecurityScanner`; no replacement, repair
refused. | "the scanner retirement recorded as
plugin-security-scanner-retired. That retirement removed
PluginSecurityScanner …" |
| `#15932` | Maintainer, 2026-09-07 (「同意」): retire the scan-result
family and `securityScan`. | "maintainer ruling 2026-09-07 (adopted
verbatim 「同意」): retire the scan-result family and its securityScan
sibling, because once the scanner was gone nothing so much as imported
their types" |
| `#16526` | Maintainer, 2026-09-07, option A: cloud does not re-host
the consumer-less control-plane files; they are deleted. | "(ruled
2026-09-07: cloud does not re-host the control-plane files it never
consumed)" |
| `#17360` | Ruling C: refuse a padded grouping field name at the
producer (not a trim). | "Ruled by the maintainer on 2026-09-10
(「其他同意」): refuse at the producer." |
| `#17499` | Refuse a padded `groupByField` on kanban, gantt and
timeline. | "The same padded-name defect the grouping-level narrowing …
refused, on the axis that one scoped out by name, and given the same
refusal." |
| `#19046` | Bound the grid component arm's page sizes to positive
integers. | the sentence now opens "This door still carried the shape
…"; the declaration half is stated in the entry |
| `objectui#3161` | Batch 7/8 of the objectui burn-down under the
`#4115` rule (renames). | folded into the `#4115` sentence |
| `objectui#3169` | objectui stopped declaring symbols under names the
spec owns; its rename tripwire fails both ways. | "the rename tripwire
objectui added when it stopped declaring symbols under names the spec
owns" |
| `objectui#3289` (PR) | `@object-ui/fields`' validation slot renamed
onto the spec's `error` and connected to its producer. | "an objectui
fix of 2026-08-03, made to follow the spec, renamed …" |
| `objectui#5595` | The console FormPage honours the form's own
`maxLength` override. | "(fixed so that a form's own bound wins over the
object's, as its docstring promised)" |
| `objectui#5898` | The form-view bridge maps every spec key or explains
why not. | "mapField, which maps every spec key or explains why it does
not" |
| `objectui#6262` | The measured `features.*` asymmetry, and the ruling
record. | folded into the `#12665` sentence |
| `objectui#7347` | The measured padded-grouping failure, and ruling C's
record. | folded into the `#17360` sentence |
| `objectui#9853` | Measured `pagination.pageSize: 0` reaching
`ObjectGrid`. | "an objectui grid measurement found that …" |
| `objectui#9896` (PR) | A non-positive `pageSize` is refused at all
three grid read points. | "objectui's grid plugin repaired the consumer
half — it now refuses a non-positive page size at all three read points
…" |
The eight dead ids, and the two ids whose page does not say what the
text claimed (`#2561`, `#3896`), are in **Acceptance notes**. No
call-shaped token moves: a `name(` census over `registry.ts` is
identical before and after, so textual call-spelling ratchets read the
same.
## Pin — `packages/cli/test/migrate-meta-engine-guidance.test.ts`,
widened
The stage-1 pin now selects every entry whose id starts with a covered
prefix: `engine-`, `ui-` or `plugin-`. It spawns the real CLI (`os
migrate meta --from 16 --to 18`) once, locates each covered block
**verbatim** in stdout, and asserts the printed block carries no `#`
plus 4 or 5 digits. That block includes `surface`. Anti-vacuity:
- the derived set must contain all 29 rewritten entries (5 `engine-`, 10
`plugin-`, 14 `ui-`), and every covered prefix must select at least one
entry;
- presence in stdout is asserted before cleanliness;
- the detector is exercised on both sides first (lit on 4 and 5 digits,
dark on 3, 6 and `ADR-0112`).
The chain reports every semantic entry of every crossed hop, whatever
the stack authors (`applyMetaMigrations` maps `step.semantic` straight
to TODOs), so the fixture is kept as-is and the header now says so. The
file keeps its stage-1 name; a rename is left to the stage that covers
the last family. An entry added later to a covered family is held on
arrival — see Acceptance notes for the one known in-flight case.
## Ablation — the widened pin can fail on a `ui-` block and on `surface`
From committed state, HEAD `8a1076b0a6`, with
`scripts/ablation-replace.mjs` in wrap mode and
`scripts/ablation-dist-preflight.mjs` gating each leg. The bundle is
built from the generated `registry.ts`, so that is the file mutated
(stage 1's attempt 2 records why the entry file is the wrong target).
- **Mutation.** In `registry.ts`, the `surface` of
`ui-react-list-view-binding-aliases-retired`: anchor `(the react-tier
overlay aliases published as deprecated` → `(the react-tier overlay
aliases #11284 published as deprecated`. The tool read anchor 1 → 0 and
replacement 0 → 1, blob `ab26922f` → `9a200491`.
- **Mutate leg.** Spec build under the lock: command-exit 0. Preflight:
marker present in 4 built files. Pin: **red**, `1 failed | 2 passed` —
`ui-react-list-view-binding-aliases-retired: the printed guidance cites
a tracker id: expected '#11284' to be undefined`.
- **Restore.** Tool-proven: blob `ab26922f` == HEAD, `git diff HEAD`
empty.
- **Restore leg.** Spec build under the lock: command-exit 0. The
`--absent` preflight found the marker in none of 222 built files, with
the working tree clean against HEAD. Pin: **green**, `3 passed`.
## Verification
Final head **`071dc7fc1d`** unless a line says otherwise.
- **Pin and its neighbour:** `pnpm --filter @objectstack/cli exec vitest
run --project integration --maxWorkers=2
test/migrate-meta-engine-guidance.test.ts
test/migrate-meta-default-range.test.ts` gives `Test Files 2 passed`,
`Tests 10 passed | 1 skipped` (the skip is the default-range file's own
pre-existing `skipIf`).
- **Spec tests that read these entries or the registry:** `pnpm --filter
@objectstack/spec exec vitest run --project local --maxWorkers=2
src/migrations` plus the 14 other spec test files that read
`MIGRATIONS_BY_MAJOR` or one of these entries' text
(`plugin-runtime-tier-truthful-text`, `interaction-config-retirement`,
`widget-i18n-retirement`, …) and
`scripts/build-schemas-check-mode.test.ts`: `Test Files 15 passed`,
`Tests 438 passed`.
- 1 parent eea8787 commit dfd8e39
30 files changed
Lines changed: 533 additions & 297 deletions
File tree
- .changeset
- docs
- packages
- cli/test
- spec
- src/migrations
- entries/semantic
| 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 | + | |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | | - | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
15 | | - | |
16 | | - | |
17 | | - | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
18 | 20 | | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
24 | 29 | | |
25 | 30 | | |
26 | 31 | | |
27 | | - | |
28 | | - | |
29 | | - | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
30 | 36 | | |
31 | 37 | | |
32 | 38 | | |
| |||
65 | 71 | | |
66 | 72 | | |
67 | 73 | | |
68 | | - | |
69 | | - | |
| 74 | + | |
| 75 | + | |
70 | 76 | | |
71 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
72 | 82 | | |
73 | 83 | | |
74 | 84 | | |
75 | 85 | | |
76 | 86 | | |
77 | 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 | + | |
78 | 112 | | |
79 | 113 | | |
80 | 114 | | |
| |||
88 | 122 | | |
89 | 123 | | |
90 | 124 | | |
91 | | - | |
| 125 | + | |
92 | 126 | | |
93 | 127 | | |
94 | 128 | | |
| |||
102 | 136 | | |
103 | 137 | | |
104 | 138 | | |
105 | | - | |
106 | | - | |
107 | | - | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
108 | 144 | | |
109 | 145 | | |
110 | 146 | | |
| |||
144 | 180 | | |
145 | 181 | | |
146 | 182 | | |
147 | | - | |
| 183 | + | |
148 | 184 | | |
149 | 185 | | |
150 | 186 | | |
| |||
153 | 189 | | |
154 | 190 | | |
155 | 191 | | |
156 | | - | |
| 192 | + | |
157 | 193 | | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
158 | 197 | | |
159 | 198 | | |
160 | 199 | | |
161 | | - | |
| 200 | + | |
162 | 201 | | |
163 | 202 | | |
164 | 203 | | |
| |||
0 commit comments