Commit 6f2f2df
perf: synchronous filter fast path on a dense-handle core (2.3× on 50k filter settle) (#487)
* docs: spec + plan for the filter subset rebuild
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(row-model): classify filter-only plan changes
* feat(row-model): synchronous subset rebuild for filter-only changes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(row-model): filter-only setQuery completes synchronously on flat queries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(renderer-dom): scrolling during an active replacement keeps the stale window visible
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: amendment G — renderer membership path + model levers
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(row-model): filter-only commits publish a refilter reset reason
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(core,docs): refilter reason through the public surface and guards
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(layout-core): synchronous refilter over existing height entries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(renderer-dom): filter commits refilter row heights instead of replacing
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(website): the rebuild-progress demo rides a grouping change
* docs: spec for membership verdicts (H-cycle)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): add the filter-verdict membership seam
One resolution helper per root shape: a flat root answers from its visible
tree, a grouped root from group-index leaf membership. Nothing reads it yet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): resolve filter verdicts from membership, not metadata
Every consumer of `CompiledRowMetadata.filterPasses` now asks the structure
that owns the answer: the committed root's membership for OLD verdicts, a
freshly computed verdict for NEW ones. The field is still written; nothing
reads it. Behavior unchanged.
`filterVerdict` gains a memo on the plan's existing evaluation cache entry, so
a producer that evaluates a row and then asks for its verdict still costs one
accessor pass — the per-row work budgets are pinned exact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): filter verdicts resolve from root membership
`CompiledRowMetadata.filterPasses` and `CompiledAggregateLeaf.filteredLeaf`
are deleted, and `refilterRecordMetadata` with them. A row's verdict is its
membership in the root's visible structure — the flat visible tree, or the
group index's leaf trees — and a NEW verdict is computed by the producer that
places the row, never stored.
The point of the exercise: a filter-only change now reconstructs NO record.
The rows HAMT carries by identity exactly as the sort fast path's does, and a
flip is expressed purely by where the row sits in the new visible tree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(row-model): state the plan-coherence precondition at the grouped seam
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): derive byId and trust proven order in bulk tree builds
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): derive byId only when removals beat a refill
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): iterate order-statistic trees without generator delegation
`iterateEntries` walked the tree with `yield* iterateEntries(node.left)`, so
every element leaving a leaf bubbled out through one generator frame per tree
level — ~17 at 50,000 rows, ~850,000 resumptions to walk 50,000 entries.
Measured in isolation at 50k: 30.04ms for the delegating shape, 1.77ms for an
explicit-stack walk of the same tree. On the real 50k filter-metadata commit
that one function body was the largest single frame in the profile.
Rewrites both order-statistic-tree walks (persistent and transient) and the
HAMT's walk in `persistent-map` as explicit-stack generators. The contract is
unchanged: lazy, in-order, same yielded values, and the transient walk still
checks the draft's liveness on first resumption and before every element.
Each carries a comment with the measurement, because the delegating version
is shorter and reads like the obvious simplification.
Also reroutes the five callers that walk a tree to completion into an array —
`filter-rebuild` (both), `sort-rebuild`, `row-store`, `create-local-row-model`
— to the already-shipped `range(0, size)`, which does the same walk without
suspending at all (1.05ms at 50k). The lazy callers are left alone
deliberately: `transaction-draft`'s visible walk breaks on the first
unaffected entry, and the cooperative-transition and distinct-values walks are
iterators stepped across scheduler slices.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* perf(row-model): filter-only changes adopt the previous plan's evaluation cache
A filter-only plan change leaves every cached per-row field valid: rowId and
sourceOrder are guard fields re-checked against the live input, groupPath and
aggregateLeaves and sortKeys are functions of facets the classifier holds
identical (groups, derivations including accessor identity, sort), and the
row object is the map key. So the next plan takes the previous plan's whole
evaluation cache BY REFERENCE — one assignment — instead of walking every row
to refill a store with value-identical copies.
The one filter-dependent field is the cache entry's verdict memo, which H1
left behind when it removed `filterPasses` from the metadata itself. It is
now tagged with the plan that wrote it, so an adopting plan never reads a
verdict its own filters did not produce and runs exactly the accessor pass it
ran before. The tag costs one property write inside a write that already
happens; there is no new per-row work anywhere.
`sortKeyCarries` stops incrementing on this path — the walk it counted was a
100%-carry walk, i.e. precisely the redundant work removed — so
`evaluationCacheAdoptions` pins the replacement instead.
Measured at 50k rows (Node, four interleaved A/B rounds, load ~7-8): median
settle 100.5ms -> 89.4ms.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: dense-handle core design spec (slots, bitsets, columnar evaluation)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M0 probe implementation plan
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M0 pricing probe results for the dense-handle core
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M0 results — record load sensitivity from the review re-run
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M1+M2 implementation plan (slots + membership bitsets)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M1+M2 plan — slotCapacity defined in Task 5 where it belongs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): membership bitset primitive
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): per-model slot allocator
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): chunked copy-on-write slot vector
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* refactor(row-model): fail-loud slot-vector capacity, identity-based COW tracking
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M1+M2 plan tracks the chunksTouched rename
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): stamp lifetime slots on row records
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(row-model): pin buildRowStore slot carry and abandoned-draft release paths
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): per-revision recordsBySlot slot vector
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): per-revision visibleSlots membership bitset
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(row-model): filter-only rebuild walks slots and diffs membership bitsets
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: M1+M2 measured results (slots + membership bitsets)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: Amendment I — dense-identity layout seam design
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: dense layout seam implementation plan (Amendment I)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(layout-core): dense-membership primitive and dense-key type surface
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(layout-core): dense generations — builder ingest, bitset membership, guarded ops
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(layout-core): slot-indexed refilter and reorder for dense generations
Dense generations now run refilter and reorder on the slot lane: survivors
resolve by denseKey against a slot-indexed array with zero identity strings
(only entrants compute an identity, because measurements and tombstones stay
string-keyed in both lanes — Amendment I §3), the duplicate check and next
membership share one bitset exactly like the builder ingest, and measured
leavers retire in OLD-SEQUENCE order so tombstone ticket assignment — which
is observable through cap eviction — matches the string lane bit for bit.
Both interim Task-2 throws are gone; their tests became real dense-path
tests, the only sanctioned existing-test edits.
Ride-alongs from the Task 2 review: retainMeasurement rejects malformed
dense keys before the bit test (a fractional key's &31 truncation would
read a different row's bit), apply's remove/move/update arms reject an
operation whose denseKey drifted from the entry's stamped slot, and
replace() documents its deliberate lane exit.
Pins: a seeded lane-equivalence oracle (200 rows, 30 mixed steps) comparing
geometry, retention, and lane-independent work counters after every step;
the ticket-order/cap-eviction pin (slots deliberately anti-ordered vs the
sequence); and the Amendment §3 slot-reuse trap (new identity on a reused
slot ingests at estimate; the old measurement returns only for the old
identity). Both pins verified by mutation: slot-ordered leavers fail the
ticket pin; a slot-keyed measurement store fails the §3 trap.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): internal dense snapshot reads for the renderer seam
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(renderer-dom): dense-keyed layout sources, bulk visible walk, slot-pooled refs
Task 5 of the dense layout seam (Amendment I): the row-layout controller
now feeds layout-core's dense lane from the row model's internal slot
seam.
- replacementSourceOf declares denseCapacity and stamps every entry's
denseKey when the snapshot supplies the ɵ slot seam; the visible set is
materialized through chunked bulk range walks (one maxUnitsPerSlice-sized
read per chunk, lazy) instead of per-row O(log n) rowAt descents. The
string lane keeps the per-row rowAt shape verbatim — structural snapshot
wrappers (react's bounded-read guards) legitimately refuse wide range
spans, and only ɵ-supplying real model snapshots take the bulk walk.
- Incremental change operations and prepareWindow estimate updates are
slot-stamped (before-first resolution so removes still resolve); staged
measurement replay passes the slot to retainMeasurement, and a staged
measurement whose row was permanently removed drops that one generation
to the string lane (the amendment's wholesale escape hatch) so
identity-keyed retention survives — pinned by the existing
removed-then-reinserted test.
- Data-row refs are pooled by slot: one frozen ref per bound (slot, rowId),
reused across sources and window publications. Verified: every ref
comparison goes through identityOf/sameRef, none by allocation identity.
- Dense-contract refusals keep the honest fallback signals: refilter and
reorder dispatch throws land in refilterFallbackCount and
reorderFallbackCount; apply-path throws restart via the existing
replacementStartCount-observable convention.
Ride-along (comments only, from the Task 3 quality review): the string
lane-pin note at both dense dispatches, the trust-boundary note in both
dense docblocks, and cross-references between the lane-equivalence oracle
and the leaver ticket-order pin.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(react): dense layout seam end-to-end pins
An end-to-end react pin drives a 200-row grid through filter-on ->
narrow -> widen -> filter-off and asserts the DENSE refilter path ran
(refilterPathCount +4, refilterFallbackCount 0), the mounted index is
actually dense (layout-core's unkeyed-op refusal as a lane probe), and
a measured row's height survives a flip-out/flip-in. Mutation-checked:
unstamping denseKey in the dense source fails the probe; a string-lane
refilter source fails the counters.
Ride-along hardening: a DENSE build whose chunked source read throws
(a spread-based snapshot wrapper carrying the seam with its own
bounded-read guard) now takes the amendment's string-lane escape hatch
for one generation instead of the generic failure path; the next full
replacement re-decides dense. Pinned with a bounded-restart test.
API reports regenerated: the three optional @internal slot-seam members
on PretableRowModelSnapshot, mirrored in core and react — nothing else.
Docs api-surface guard green with no table updates.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: dense layout seam measured results
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: Amendment J — columnar verdict cache design
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: columnar verdict cache implementation plan
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): thread slots into compiled-query inputs
Add `readonly slot: number` to CompiledRowInput (Amendment J §1,
dense handle for columnar cells; unread this task). Thread the field
through every production call site: cooperative-transition.ts stamps
it from the record, transaction-draft.ts's createRecord already took
a slot param, and rebuildRowStoreForQuery (dead code, zero callers)
gets it mechanically from the carried record.
buildRowStore and replaceFlatRowsDraft need a slot before evaluate()
runs (evaluate can throw via a user accessor), but their real slot for
a brand-new row is only resolved by input.slots.allocate() AFTER
evaluate succeeds — allocating earlier would leak allocator capacity
(a monotonic high-water mark; release() cannot undo it) on a throwing
accessor. Both keep that exact original ordering/side effects and pass
a harmless placeholder (-1, or the carried previous slot when known)
into evaluate()'s input only, since nothing reads the field yet.
Test fixtures across 6 row-model test files and one react test file
needed `slot` added to CompiledRowInput-shaped literals; no assertions
changed. CompiledRowInput does not appear in any governed public
package (core/react/ui/stream-adapter) or their .api.md reports —
row-model is `"private": true` and outside the `pnpm api` gate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: Amendment J freshness invariant revised — scan is the only writer
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(row-model): compile filter predicates once per plan
evaluateFilter's per-row operator dispatch becomes compileFilterPredicate:
one monomorphic (value) => boolean closure per runtime filter, built at
plan construction with operand normalization hoisted (between bounds
min/maxed once, date operands collapsed to UTC day-ms once, text needles
lowercased once, selection operands coerced into a Set once). Predicate
semantics now exist exactly once, in the compile step; #filterVerdict
walks the construction-time #compiledPredicates array parallel to
#runtimeQuery.filters — no #byId lookup per row.
Exhaustive pinned-literal sweep over all 31 (column type, operator)
pairs in FILTER_OPERATORS, boundary inclusivity included; mutation-
checked (exclusive lower between bound fails exactly the boundary
cases). Full suite 602 green, zero existing-test edits.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(row-model): columnar filter-value cache with commit-side clears
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: Amendment J §2 records the mutable-columnar storage decision
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(row-model): filter rebuild verdicts from columnar scan
The filter-only rebuild's O(n) walk now takes each row's verdict from
bulkFilterVerdictScan: per filter, in filter order, the columnar cell for
(column, slot) answers when present, and a hole falls back to the live
accessor through the shared #readColumnValue seam AND writes through —
the store's only writer (Amendment J §3 revised). One-pass-per-slot for
cell locality; short-circuit exactly like the per-row .every, so a
failing row may leave later filters' cells unfilled (holes refill
lazily). The per-row filterVerdict stays untouched for k-sized and
grouped callers.
Also closes the Task 3 review's stale-cell laundering hole:
setDerivations' plan-REUSE branch now resets the columnar store, because
derivationsEqualForPlan ignores UNREFERENCED columns' accessors and one
intermediate filter-only adoption would otherwise put a new-accessor
plan on a store still holding the old accessor's cells.
Work counters: columnarVerdictScans (one per rebuild) and
columnarCellFills (per hole filled); a second filter-only commit on
unchanged data is pinned at ZERO fills. New tests: seeded randomized
columnar-vs-per-row equivalence oracle (updates, slot reuse, setRows,
newly-referenced column mid-script), the laundering sequence, and
accessor-failed shape parity between scan and per-row paths. All four
covering mutations verified red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: columnar verdict cache measured results
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* perf(row-model): one-call verdict sweep over normalized columnar cells
The filter rebuild's verdict pass is now ONE bulkFilterVerdictSweep call
per rebuild (walk, plan resolution, predicate/column/vector hoisting all
inside the plan; assert-free trusted cell reads over walk-produced slots),
and the columnar store caches SCAN-NORMALIZED cells (text lowercased,
dates as day-ms, enum/boolean coerced) filled once, with normalized
predicate twins compiled per plan. isEmpty/isNotEmpty stay on raw accessor
reads — emptiness is a raw-value property the normalized forms lose.
Re-measured paired at 50k: STILL FLAT (+0.9/+0.4ms medians, controls in
band); traced verdict share ~15.4% vs ~17.1%. The bench scripts' single
cold-store commit makes the fill the measured interaction, so the
warm-path win (zero-fill repeat commits, test-pinned) is invisible to the
settle metric. Details appended to the results doc.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* revert(row-model): drop the columnar verdict store — measured flat twice
Keeps compiled predicates and slot threading. See
docs/superpowers/specs/2026-08-24-columnar-verdicts-results.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: prettier-format the arc's spec documents
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(row-model): tsdoc cannot link-reference ɵ-prefixed members
api-extractor's declaration-reference parser rejects the ɵ start; the
api:check gate treats the warning as an error.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 693f01e commit 6f2f2df
77 files changed
Lines changed: 13870 additions & 687 deletions
File tree
- apps/website/content
- docs/headless
- examples/headless-rebuild-progress
- __tests__
- docs/superpowers
- plans
- specs
- packages
- core
- grid-core/src/__tests__
- layout-core/src
- __tests__
- react
- src/__tests__
- renderer-dom/src
- __tests__
- row-model/src
- __tests__
- persistent
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| |||
Lines changed: 32 additions & 24 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
23 | | - | |
| 22 | + | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
35 | 35 | | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
42 | 45 | | |
43 | 46 | | |
44 | | - | |
45 | | - | |
46 | | - | |
| 47 | + | |
47 | 48 | | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
56 | 57 | | |
57 | 58 | | |
58 | 59 | | |
| |||
72 | 73 | | |
73 | 74 | | |
74 | 75 | | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
83 | 91 | | |
84 | 92 | | |
85 | 93 | | |
| |||
Lines changed: 39 additions & 19 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | 52 | | |
56 | 53 | | |
57 | 54 | | |
| |||
60 | 57 | | |
61 | 58 | | |
62 | 59 | | |
63 | | - | |
64 | | - | |
65 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
66 | 64 | | |
67 | 65 | | |
| 66 | + | |
| 67 | + | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
71 | | - | |
72 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
73 | 84 | | |
74 | 85 | | |
75 | 86 | | |
76 | 87 | | |
77 | 88 | | |
78 | | - | |
| 89 | + | |
79 | 90 | | |
80 | 91 | | |
81 | 92 | | |
82 | 93 | | |
83 | 94 | | |
84 | 95 | | |
85 | 96 | | |
86 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
87 | 105 | | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | 106 | | |
92 | 107 | | |
93 | 108 | | |
| |||
102 | 117 | | |
103 | 118 | | |
104 | 119 | | |
105 | | - | |
106 | | - | |
107 | | - | |
| 120 | + | |
108 | 121 | | |
109 | 122 | | |
110 | 123 | | |
| |||
115 | 128 | | |
116 | 129 | | |
117 | 130 | | |
118 | | - | |
| 131 | + | |
119 | 132 | | |
120 | 133 | | |
121 | 134 | | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
122 | 142 | | |
123 | 143 | | |
124 | 144 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
0 commit comments