Commit 125cd12
Spec 034 — Element allocation reduction (LayoutModifiers / VisualModifiers shim, UseMemoCells, REACTOR_HOOKS_007) (#126)
* spec 034 §A — bucketed ElementModifiers (Component A)
Move 27 layout/visual fields off the parent ElementModifiers record into
two lazy sub-records (LayoutModifiers, VisualModifiers). Public surface
stays identical via get/init shim properties; Merge merges buckets at
the sub-record level so a Padding-only update no longer clones every
unrelated field.
- src/Reactor/Core/Element.cs: 17-field LayoutModifiers + 10-field
VisualModifiers, parent shims, bucket-aware Merge
- tests/Reactor.Tests: LayoutModifiersTests, VisualModifiersTests,
ElementModifiersBucketTests covering Merge semantics, shim ⇄ bucket
round-trip, and bucket-reference preservation under partial Merge
All 6,748 unit tests pass (6,727 pre-existing + 21 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 §B — StressPerf.ReactorOptimized + advanced.md "Hot loops"
Add a sibling stress-perf project that demonstrates the direct-record-
initializer cell-construction idiom from spec 034 §B. The naive
StressPerf.Reactor stays untouched and remains the framework-level
baseline; the new optimized sibling will accumulate Components B + C
through Phases 2–4.
- tests/stress_perf/StressPerf.ReactorOptimized: cloned from
StressPerf.Reactor, inner-loop replaced with direct
new TextBlockElement { Modifiers = new ElementModifiers
{ Layout = …, Visual = … } } construction. UseMemoCellsByIndex
arrives in Phase 4.
- Reactor.sln: project entry, Debug/Release × x64/ARM64 config rows,
parent mapping under the StressPerf solution folder.
- run_stocks_grid_baseline.ps1, run_bench_aot_publish.sh,
run_benchmark.sh, run_sweep_arm64.ps1: ReactorOptimized variant
added alongside the naive Reactor row.
- docs/_pipeline/templates/advanced.md.dt: new "Hot loops" section
with side-by-side fluent/direct example, workload-shape guidance,
trade-offs, and a forward reference to spec 008's builder pattern.
Compiled output in docs/guide/advanced.md regenerated via mur.
- tests/stress_perf/README.md and SPEC.md: document the naive vs
optimized split.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 §C — UseMemoCells hooks + REACTOR_HOOKS_007 analyzer (Component C)
Add cell-level memoization for high-frequency list / grid bodies plus the
companion analyzer that catches missing closure-capture deps at compile
time. The hook intentionally takes params-deps to match
UseMemo/UseEffect/UseCallback; the analyzer is what makes the params
shape safe.
- src/Reactor/Hooks/UseMemoCells.cs: three RenderContext extension
methods (UseMemoCells / UseMemoCellsByKey / UseMemoCellsByIndex)
plus matching Component-class shims. ArgumentNullException at
validation boundaries; ArgumentOutOfRangeException for bad index
in ByIndex.
- src/Reactor.Analyzers/UseMemoCellsAnalyzer.cs: REACTOR_HOOKS_007.
Walks the builder lambda's data flow, enumerates captures (filtering
the lambda's own params, the implicit-this parameter, method
symbols, const, and static-readonly fields), reports any capture
not present in the trailing deps slot.
- src/Reactor.Analyzers/UseMemoCellsCodeFix.cs: appends the missing
capture to the deps slot. Handles both params-tail and explicit
array-literal forms.
- AnalyzerReleases.Unshipped.md: REACTOR_HOOKS_007 row.
- tests/Reactor.Tests/UseMemoCellsTests.cs: 22 hook tests covering
first render, full reuse, partial reuse, deps invalidation, count
growth/shrink, ArgumentNullException at boundaries, ByKey identity
/ mutation / reorder / duplicate-key last-write-wins, ByIndex empty
/ single / out-of-range / count-change fallback.
- tests/Reactor.Tests/AnalyzerTests/UseMemoCellsAnalyzerTests.cs: 11
analyzer + codefix tests covering happy path, missing-deps warning,
zero-deps + capture, this-field capture, indirect-capture blind
spot, ByKey / ByIndex variants, codefix transforms input → input
with capture appended.
- docs/_pipeline/templates/advanced.md.dt: "Memoizing list cells"
section with the three-overload table, gen2 trade-off, and
analyzer pointer. Compiled output regenerated via mur.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 — wire UseMemoCellsByIndex into ReactorOptimized + skill + close
Final phases of spec 034:
- tests/stress_perf/StressPerf.ReactorOptimized/Program.cs: replace the
inner cell `for` loop with `UseMemoCellsByIndex(data, changedIndices,
builder, GreenBrush, RedBrush)`. The data source's existing
`Update()` return value already produced the changed-index list;
thread it via `UseRef<IReadOnlyList<int>>` between the timer Tick
and Render. ReactorOptimized is now the spec's canonical "all three
components combined" reference.
- skills/perf-tips.md: agent-facing playbook covering UseMemo /
UseCallback, UseMemoCells (3 overloads), direct-record-initializer,
COM-resource caching, the gen2 trade-off, profiling entry points,
and "when NOT to" — written so an unfamiliar agent can pick the
right tool from this skill alone.
- docs/specs/034-element-allocation-reduction.md: status flipped from
Drafted → Implemented (2026-05-02). Production re-bench is logged
as a follow-up; the prototype's table from
reactor-vs-direct-10pct.md remains the operating reference until
that re-bench lands.
- CHANGELOG.md: top-level "Spec 034 — Element allocation reduction"
rollup bullet under Changed.
Sample audit (Phase 5): no samples have a workload that crosses the
threshold (~50+ items × frequent mutation × pure-of-T builder) where
UseMemoCells would beat the fluent chain. The reference implementation
is StressPerf.ReactorOptimized; samples stay fluent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 close-out — verified perf table + Phase 5/7/8 wrap-up
- Same-day three-variant bench (Reactor / ReactorOptimized / Direct)
at 20/50/100 % mutation, 10s ARM64 Release. Captures reconcile-time
delta as the cleanest in-app proxy for the alloc story (no ETW —
PresentTracer needs admin and was not run for this close-out).
- Verified close-out section appended to spec 034 with the matrix and
reads. Headline: ReactorOptimized cuts reconcile time -60 % at
20 % mutation, -33 % at 50 %, -8 % at 100 %, clearing Direct
outright at every rate sampled.
- CHANGELOG rollup updated with verified numbers (replaced the
prototype-only placeholder).
- Phase 5 sample audit complete: zero migrations. Audit findings
documented in commit body — TodoApp lists are too small,
PerfStressDemo bars rebuild every render, ChatTimeline already
uses keys, gallery samples are demos.
- Phase 7 spec status flipped to "Implemented — 2026-05-02" with the
re-bench locked in.
- Phase 8 AOT smoke logged as follow-up (vswhere/MSVC linker not on
this shell's PATH); spec 034 surface is reflection-free by
inspection.
- Implementation task file updated with phase-level completion
markers and outstanding-followups annotations.
Adds:
tests/stress_perf/run_spec034_bench.ps1
tests/stress_perf/baselines/spec-034-final.{csv,log}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 — capture pre/post Reactor baseline (Component A in isolation)
Re-bench'd the unmodified naive StressPerf.Reactor source against the
pre-spec-034 commit (247a525, parent of Component A merge) via
git worktree. Same source, same fluent-chain usage on both sides — only
the framework changed (transparent LayoutModifiers/VisualModifiers shim).
Result at 20/50/100 % mutation (10 s, ARM64 Release):
Mutation Pre-A renders Post-A renders ΔRenders ΔReconcile
20 % 81 77 -4.9 % +2.3 %
50 % 48 50 +4.2 % -16.7 %
100 % 34 34 0 % -3.4 %
Honest read: Component A's transparent shim does NOT deliver
renders/sec uplift outside run-to-run noise at these mutation rates.
The cleanest signal is -16.7 % reconcile at 50 %; 20 % and 100 % are
within noise. This is consistent with Component A being an allocation-
side improvement (~-11 % bytes/tick per the prototype) on a workload
that is GC-bound at high mutation. The prototype's predicted +6 %
renders was at 10 % mutation — a point not sampled here.
PR framing for Component A: the win is real on the allocation axis,
invisible on renders/sec at the high mutation rates sampled, and worth
re-measuring at 10 % before quoting a renders-side number. Components
B + C carry the user-visible perf story.
Spec close-out section + CHANGELOG rollup updated to reflect the
isolated-A measurement instead of folding it into the
ReactorOptimized headline.
Adds:
tests/stress_perf/run_spec034_reactor_before.ps1
tests/stress_perf/baselines/spec-034-reactor-before.{csv,log}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* stress_perf: full-matrix bench script with ETW + auto-build
run_full_matrix.ps1 — single-entry script that builds and benches every
C# StressPerf variant (Direct, Bound, Wpf, DirectX, Reactor,
ReactorOptimized, ReactorGrid, VirtualListReactor) at 10/20/50/100 %
mutation, 10 s each, ARM64 Release, with PresentTracer ETW capture for
ground-truth Present/sec.
- Hard admin gate up front: PresentTracer needs an elevated ETW kernel
session (DxgKrnl), so the script aborts with a clear message if not
run from an admin shell. -SkipETW lets you run in-app-metrics-only
mode without admin (no Present/sec, no DxgKrnl rates).
- Auto-builds each variant csproj + PresentTracer at the configured
Configuration / Platform (default: Release / ARM64). -SkipBuild
reuses existing binaries.
- -VariantFilter @('Reactor','ReactorOptimized') restricts the run.
- -Repeats N for noise control; output CSV has per-run rows + a
per-(variant, percent) median/min/max summary.
- Output goes to baselines/full-matrix-<timestamp>/ with run.log,
run.csv, run.summary.csv. Each run gets its own dir so historical
matrices accumulate.
Replaces the half-broken run_stocks_grid_baseline.ps1 (hardcoded
reactor3 paths, no admin gate, no build phase, fixed-three-percent).
That script is left in place for now in case anything else references
its CSV path; new runs should target run_full_matrix.ps1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* stress_perf: add RN-Fabric to full-matrix bench, drop VirtualListReactor
- New RN-Fabric variant entry: IsRN=$true, Exe path under
tests/stress_perf_rn/StocksGrid/windows/ARM64/Release/StocksGrid.exe.
In-app report scraped via UIA from the testID="HeadlessReport" Text
node before process teardown (RN doesn't write report files to disk).
- Build phase auto-builds RN: npm install (only if node_modules
missing) followed by npx @react-native-community/cli run-windows
--release --arch arm64 --no-launch --no-deploy in
tests/stress_perf_rn/StocksGrid. ~10-15 min on first build,
incremental after.
- Variant table loses VirtualListReactor — not needed for the spec 034
comparisons.
- Build phase skips the npm/npx step entirely if no RN variant is in
the requested set; missing-exe error message points the user at the
right build command for either kind of variant.
- Run loop branches on IsRN:
• C# variants — Read-VariantReport from .report.txt as before.
• RN — Scrape-RnReport via UIA before killing the process.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* stress_perf: clearer error message when RN-Fabric build can't find VS
react-native-windows 0.82 specifically wants VS 17.11+ and does not
accept VS 18 — same VS-detection issue that blocks the AOT smoke
elsewhere. When the build fails, point the user at the three most
likely causes (VS 17 missing, admin shell, node_modules drift) plus
the -VariantFilter escape hatch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* stress_perf: auto-set MinimumVisualStudioVersion=18 for RN-Fabric on VS 18-only machines
react-native-windows 0.82's MSBuild detection (findLatestVsInstall in
@react-native-windows/cli/lib-commonjs/utils/vsInstalls.js) clamps the
acceptable VS version range to [minVersion, floor(minVersion)+1). The
default minVersion is 17.11.0, so the range becomes [17.11.0, 18.0) —
which excludes VS 18 entirely. The CLI does honor the
MinimumVisualStudioVersion env var to override the floor.
Detect Visual Studio installations under both Program Files locations
before invoking npx; if VS 17 is missing but VS 18 is present, set
MinimumVisualStudioVersion=18.0 in the build's environment so the
range becomes [18.0, 19.0) and the installed VS 18.x matches.
Restored to whatever it was before (typically unset) when the build
finishes. No-op when VS 17 is on the box.
Verified: with this fix, the RN-Fabric solution builds clean against
VS 18.5 Enterprise on this machine in ~2 min.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* stress_perf: auto-build single missing target under -SkipBuild
-SkipBuild used to fail the whole run if any single target's exe was
missing — which bites when you've already built the variants but
forgot PresentTracer (or vice versa). Now each missing C# target
auto-builds on demand right before the run starts, so -SkipBuild
skips the bulk-rebuild but still recovers from "I just added one
new variant" or "PresentTracer was never built on this branch."
RN-Fabric still hard-errors with the npm + npx command to run
manually — auto-running react-native run-windows from inside this
script would block the matrix on a 5-min build with confusing output
interleaving.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 — verified close-out with ETW Present-tracking
Replaces the no-ETW close-out section with the 2026-05-03 full-matrix
bench: 8 variants × 4 mutation rates (10/20/50/100 %) × 10 s, ARM64
Release, ETW Present-tracking via PresentTracer (admin shell). The
prototype's 10 % headline is now validated on production code.
Headline:
ReactorOptimized at 10 % mutation reaches 17.1 Effective Refresh/s
- within run-to-run noise of DirectX (17.2) and Wpf (17.9)
- +66 % over naive Reactor (10.3) on the same hardware
Reconcile-time win on the same A/B (Reactor → ReactorOptimized):
10 %: 32.5 ms → 7.9 ms (-76 %)
20 %: 36.8 ms → 14.4 ms (-61 %)
50 %: 43.9 ms → 30.4 ms (-31 %)
100 %: 53.7 ms → 47.3 ms (-12 %)
Memo's win tracks the partial-reuse opportunity exactly as predicted
in §C: large at low mutation, narrows toward saturation. DirectX
runs away above 50 % mutation - no allocating framework keeps up
once GC pressure dominates, which is a known shape, not a spec 034
regression.
The "ReactorOptimized > Direct at every rate" result deserves an
asterisk - StressPerf.Direct/MainWindow.cs has dev instrumentation
(File.AppendAllText to C:\temp on the UI thread, plus per-tick
header TextBlock SetValues regardless of value change) that biases
the comparison. The headline (matches DirectX/Wpf within noise) is
robust; the "beats Direct" framing should be read as "ties or beats
after fixing those scaffolding warts." Filed as a bench follow-up.
Two scrape anomalies noted honestly in the doc - Bound @ 10 % and
RN-Fabric @ 50 % exited before the script's 500 ms post-run UIA
scrape window. ETW Present rates were captured cleanly so the
variants did run; only in-app Total Renders is zero in those rows.
Adds:
tests/stress_perf/baselines/full-matrix-2026-05-03-070935/{run.csv,run.summary.csv,run.log}
CHANGELOG rollup updated to reference the verified numbers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spec 034 — address Copilot CR feedback on PR #126
Three review comments from copilot-pull-request-reviewer.
1. UseMemoCellsCodeFix re-parsed the capture name from the diagnostic
message text. Brittle to message edits / localization. Now the
analyzer attaches the capture name to Diagnostic.Properties under
UseMemoCellsAnalyzer.CaptureNameProperty; the codefix reads it from
there and falls back to message parsing only for diagnostics from
stale analyzer builds. Existing 11 analyzer tests still pass — the
round-trip is internal plumbing, behavior is unchanged.
2. UseMemoCellsByIndex XML doc claimed item-count change was "not
supported" and callers "must fall back" to UseMemoCells, but the
implementation already detects prev.Children.Length != count and
does a full rebuild (Hooks/UseMemoCells.cs:211). Doc updated to
describe the actual behavior — count change → full rebuild,
changedIndices treated as "rebuild everything" — and points
callers whose lists grow/shrink frequently at the value- or
key-equality overloads for better incremental reuse.
3. tests/stress_perf/SPEC.md still claimed net8.0-windows10.0.22621.0
but every csproj targets net9.0 (WinUI: net9.0-windows10.0.22621.0,
WPF: net9.0-windows, PresentTracer: net9.0). Updated to list the
actual TFMs per variant family.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 25e1bb6 commit 125cd12
35 files changed
Lines changed: 7955 additions & 119 deletions
File tree
- docs
- _pipeline/templates
- guide
- specs
- tasks
- skills
- src
- Reactor.Analyzers
- Reactor
- Core
- Hooks
- tests
- Reactor.Tests
- AnalyzerTests
- stress_perf
- StressPerf.ReactorOptimized
- baselines
- full-matrix-2026-05-03-070935
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 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 | + | |
32 | 59 | | |
33 | 60 | | |
34 | 61 | | |
| |||
70 | 97 | | |
71 | 98 | | |
72 | 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 | + | |
73 | 127 | | |
74 | 128 | | |
75 | 129 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
| 43 | + | |
42 | 44 | | |
43 | 45 | | |
44 | 46 | | |
| |||
383 | 385 | | |
384 | 386 | | |
385 | 387 | | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
386 | 404 | | |
387 | 405 | | |
388 | 406 | | |
| |||
1347 | 1365 | | |
1348 | 1366 | | |
1349 | 1367 | | |
| 1368 | + | |
1350 | 1369 | | |
1351 | 1370 | | |
1352 | 1371 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 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 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
113 | 220 | | |
114 | 221 | | |
115 | 222 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
253 | 253 | | |
254 | 254 | | |
255 | 255 | | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
256 | 363 | | |
257 | 364 | | |
258 | 365 | | |
| |||
0 commit comments