Commit 8d2c7c1
tune: a progress display for --tune, per-ISA [tuned] fallbacks, and arm64 cpu_supports (#3583)
* tune: design notes for progress events and a single renderer
Captures the current four-level process shape, the buffered-relay blocker in
run_scope_tuner, the event vocabulary, the renderer-vs-forwarder rule, the new
daslib/tty binding, and the watchdog.py strings that are a live contract.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: route the flag rail through daslib/clargs in the design notes
Records the four hand-rolled parsers to migrate, get_user_args as the accessor,
the shared-argv precedent (ReleaseDepsArgs, same module), and the unknown-flag
value-passthrough hazard that keeps the tune spec bool-only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: make gen_tune_probe honour --tune-fast a decided item in the notes
The generator half silently drops the flag the tuner passes it. Records the
round-count cut as the analogue of tune_kernels' screening cut, and why the
confirm pass stays untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: record the supervised dasllama-server scenario as the goal
Maps the tuning/restart/normal narrative onto the restart policy rail, which is
already correct end to end; the two gaps are the up-front promise and the
buffered silence. Adds the watchdog-as-renderer consequence and the STATE
control-page surface.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: no duration estimates; add pass name and live-candidate count
Everything displayed is observed, never predicted. Records the three honest
axes beyond the outer counter, including the screening/narrowing/finalists
passes tune_candidate_active already runs and the live count screening_keep
already computes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: stream the scope tuner's output instead of buffering it to a file
run_scope_tuner redirected the tuner to a temp file with an empty popen
callback and printed the file after the child exited, so a minutes-long tune
produced no signal at all until it finished. Relay live via fgets, the same
shape tune_auto_reexec and dasllama_tuner already use.
Also stops discarding the tuner's exit code: popen returns it, so report a
non-zero rc and return it rather than an unconditional true. Both current
callers ignore the result, so this changes no behavior today.
Tests: llvm_tune_scope.das and llvm_tune_manifest.das, both under -jit (they
short-circuit to pass without it).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* daslib/tty: terminal capability probes, with the fio_core binding behind them
daslang had no way to ask whether a stream is a terminal — isatty appeared only
in vendored doctest/fmt/gtest C++, and no width query existed at all. Sniffing
TERM (what ansi_colors does for styling) is not a substitute: it stays set when
stdout is a pipe or a log file, which is exactly the case a redrawn progress
display must not fire in.
fio_core gains is_terminal(fd) and terminal_width(); daslib/tty wraps them as
named predicates plus terminal_columns(fallback), and does not re-export
fio_core. Width falls back to COLUMNS, then to the caller's fallback.
Verified: piped -> false/0; piped with COLUMNS=123 -> 123; attached to a real
pty sized 137 cols -> true/137. AOT emission checked via -aot on daslib/tty.das
(the daslib glob AOTs it, hence the aot_builtin_fio.h declarations).
Tests: tests/daslib/tty_test.das (registered for AOT), plus tests/fio and
tests/daslib green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: progress events, a single renderer, and the up-front promise
The tuner runs as a chain of child processes, so progress travels as prefixed
lines on stdout ("@tune kind k=v ...") — a pipe is the only channel spanning
them. llvm_tune owns the vocabulary and the display, so any library's tuner
gets it, not just dasLLAMA's.
One rule decides who draws: a process renders when its OWN stdout is a
terminal, and otherwise forwards events verbatim. Forwarding is unconditional;
verbosity gates only what a human sees. That is what lets "silent" mean
literally nothing on a terminal while a supervisor still receives every event.
Raw tuner chatter is muted only while a display is actually live. A tuner that
emits no events keeps printing exactly as before — the existing scope test
caught the earlier rule, which had made adopting the protocol a prerequisite
for being visible at all.
No duration is ever shown, estimated or otherwise; the segments are too uneven
to predict. The counters are outer kernels, inner rounds, the pass name
(screening/narrowing/finalists) and the live-candidate count, plus observed
elapsed.
Adds the up-front promise: an untuned start now says a tune takes a while and
ends in a restart BEFORE the wait, and says whether the process restarts itself
(auto) or must be restarted (restart policy).
tune_progress_line/_feed/_active/_reset are public so another front end can
render the same state — and so the protocol is testable without owning a tty.
Tests: modules/dasLLVM/tests/llvm_tune_progress.das (9 cases, no tty needed);
whole dasLLVM suite green under -jit. Verified end to end against a real pty:
pipe forwards 19 events and draws 0 bars, pty draws 19 and forwards 0, silent
draws nothing on the pty yet still forwards all 19 under a pipe, verbose alone
shows raw chatter.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: mark the built sections in the design notes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: clargs flag rail, --tune-fast for the generator half, and real emitters
The flags now go through daslib/clargs everywhere, replacing three hand-rolled
argv scans. llvm_tune parses the APP's argv it does not own, so it uses the
two-arg parse_args form (the ReleaseDepsArgs precedent in this same module);
its spec is bool-only and never reads positionals, because clargs skips an
unknown flag without consuming its value and an app's `--model foo.gguf` thus
leaves `foo.gguf` in the positional list. get_user_args replaces the hand-rolled
post-`--` walk and also gets the standalone-exe slice right.
--tune-quiet / --tune-verbose set DAS_TUNE_VERBOSITY, which inherits down the
whole tuner process chain. They are adopted at macro time, so the value has to
travel by environment: the runtime guard is a different context and would not
see this one's global.
gen_tune_probe never parsed --tune-fast although dasllama_tuner passed it to
both halves and bannered "FAST". It now honours it, ROUNDS 6 -> 3 — the flat
best-of-N has no screening phase to narrow, so the round count is the only
dial. The confirm pass is deliberately untouched: it is a correctness gate, and
cutting it ships an unconfirmed crown. The banner no longer advertises
tune_kernels' budget as though it covered both halves.
The three consumers share one flag spec, harness/tuner_cli.das, required by
bare name; the producer side (daspkg) was already clargs.
Both halves now emit progress events. tune_kernels reports the pass and the
live-candidate count that screening_keep already computes; gen_tune_probe gives
the end-to-end confirm its own visible step so it is not an invisible stall.
Verified by running both tuners for real:
tune_kernels --tune-fast -> plan total=25, 25 begin/end, 500 steps
(25 x 20 rounds), phases split 100 screening / 100 narrowing / 300 finalists
— exactly fast mode's 4/8/20, which also proves the clargs migration took —
live counts narrowing 20 -> 12 -> 4, verdicts 18 beats / 7 holds.
gen_tune_probe --tune-fast -> plan total=7, per-family total=3 (the 6 -> 3 cut).
Docs: skills/tune.md (what a tune shows + the event protocol),
skills/environment_variables.md (DAS_TUNE_VERBOSITY), skills/llvm_tune.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: keep event values space-free, and test the truncation
The wire format is k=v split on spaces, so gen_tune_probe's
"confirm (end-to-end prefill)" step name truncated to "confirm" and left two
junk tokens. It degraded rather than corrupted — the display and counters were
fine — but it broke the contract, so the name is now confirm_e2e_prefill and
the contract is stated where the prefix is defined.
Found by reading the real emitted stream rather than by a test, so a test now
pins the degradation shape.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* watchdog: consume tune progress events instead of inferring them from prose
A supervised child never owns a terminal, so llvm_tune forwards its @tune
events rather than drawing a bar — which is exactly what makes them the
watchdog's to consume. They fold into STATE["tune"] for the control plugin's
status route, and log only at plan/end: a real tune is hundreds of steps, and
logging each would recreate the per-variant flood these events exist to
replace. Measured, that is 26 log records from 551 events, where the whole raw
tuner output used to be JSON-wrapped line by line.
This is the part of STARTUP_STAGES that no longer has to regex human prose.
The rest still does, and both load-bearing strings are untouched, so a deployed
old watchdog meeting a new daslang (and the reverse) still works — verified
that both stage regexes still match.
Every published field is a counter. Nothing is an estimate, and the README says
not to synthesize one: the tuner cannot know how long it has left.
Verified by replaying both real captured tuner streams through the new parser:
done lands exactly on total for each (25/25 kernels, 7/7 generator families),
done never exceeds total at any snapshot, malformed input never raises, and a
prose line is never mistaken for an event.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: render from the emitter too, and clear llvm_tune's lint debt
Running a tuner half straight from a terminal spewed raw @tune lines instead of
a bar, because only the relay rendered. Emitting now goes through the same
relay, so the rule is uniform: any process owning a terminal draws, any other
forwards. Verified under a pty — 0 raw event lines leaked, 551 bar frames.
tune_progress_finish() closes the display; both halves call it.
llvm_tune.das lint 49 -> 0, since a PR has to be clean and the rest of daslib
already is (143 files, 0 issues).
8x LINT016: `errors :=` on a plain `string&` promised a clone it does not
perform. Only the two string& functions were touched — the nine das_string
ones use := correctly and were left alone.
41x STYLE014/STYLE015: public //! docs trimmed to what they document, with
the deep semantics already carried by skills/tune.md and skills/llvm_tune.md;
internal // blocks cut to the one WHY a reader cannot get from the code. No
nolint markers — the rule's escape exists but the tree essentially does not
use it (3 files), so complying is the honest fix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: mute the tuner's own chatter under a live display
The display only replaced output that flowed through the relay. A tuner half
run directly has no relay above it, so report()'s per-variant lines and the
checksum lines went straight to stdout and trampled the bar, and the run ended
by fread-ing the whole sidecar back — the "output mainly duplicates json"
complaint, still intact.
tune_detail() is the gate for a tuner's own measurement lines: shown under
verbose, or whenever no display is live, so a tuner that emits no progress
events still prints exactly as before. Both halves route their chatter through
it; the summary block, hard failures and the "wrote <path>" line stay
unconditional, and the sidecar body is now verbose-only.
finish_progress no longer emits a newline when nothing was drawn — under a pipe
the state is live but no bar exists, so it was adding a stray blank line.
Measured on a real terminal at normal verbosity: per-variant chatter 0 (was
~500), checksum lines 0, sidecar json 0, 551 bar frames, 31 lines of tuner
output total.
Note the ~100 `loop not vectorized` lines around a JIT tune are LLVM's own
diagnostics on stderr, not this rail: the [tuned] grid deliberately requests
vectorization widths LLVM cannot always honour. stdout carries none of them, so
2>/dev/null leaves a clean display. Quieting them needs an LLVM diagnostic
handler and is a separate change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: the per-kernel stamp report is verbose-only
A real tune printed 34 `dasllama_tune: <kernel> <- <perm>` lines (plus the
llvm_tune twin) before anything else — the compile reporting every stamp it
made. That is a wall in front of an app's own startup, and it says the same
thing log_tune_status() says on request and the closing summary says at the
end. Worse, side by side the two disagree by design: the stamp list is what
THIS compile used, the summary is what the run just measured.
Both are gated to verbose now. The two tests that read those lines as their
stamped-truth proof pass DAS_TUNE_VERBOSITY=verbose to their children; in
llvm_tune_manifest that also lets the env prefix lead, so the windows
sacrificial-quote wrap is no longer needed.
On a terminal a full --tune-fast run is now: 4 JIT lines, the tuner banner,
one live bar, the summary, and "wrote <path>". Measured: 551 bar frames, 0 raw
events, 0 stamp lines.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: per-ISA [tuned] fallbacks, and make cpu_supports answer on arm64
[tuned]'s fallback= was a single string — one generic default for every target
— while [tune]'s was already a per-ISA `;`-chain. That asymmetry is why 18 of
25 kernels beat their shipped default on an M1: a single guess cannot be right
for both ARM and x64, and an untuned box (CI, AOT, a release with no sidecar)
just ate the miss.
fallback= is now a `;`-chain of `suffix` or `suffix:requires` entries, first
passing entry wins, so ONE annotation ships a different default per ISA. Its
perms are generated and have no row to hang requires= on, hence the inline
form; [tune]'s own chain is unchanged. A bare name is a one-entry chain, so
every existing annotation behaves exactly as before.
The requires= evaluator moves to llvm_tune as public tune_requires_ok(expr) +
tune_pick_fallback(chain), so both halves share one implementation of the
`,`=AND / `|`=OR grammar and the DAS_JIT_*_FORCE_FEATURES overrides.
PREREQUISITE, not scope creep: cpu_supports was x86-only and returned false for
every name on arm64 — including neon. Built on that, the feature would have
been dead on the platform that motivated it, always falling through to the
generic entry. It now answers on arm64 via sysctl (macOS), AT_HWCAP (Linux) and
IsProcessorFeaturePresent (Windows), using LLVM target-feature spellings so the
names match what DAS_JIT_ARM64_FORCE_FEATURES and `llc -mattr` take. Unknown
and wrong-architecture names stay fail-closed.
Verified on an M1 Max against sysctl ground truth: dotprod/fullfp16/lse/rdm/
crc/sha3 true, i8mm/bf16/sve false, x86 names false. End to end on a real
kernel, three ways: dotprod present picks the arm row; gated on i8mm (absent
here) falls through to the generic row; DAS_JIT_ARM64_FORCE_FEATURES=i8mm picks
the arm row again.
resolve_perm now reports every path at verbose (sidecar / fallback / default),
not just sidecar hits — the fallback decision was previously unobservable.
Tests: modules/dasLLVM/tests/llvm_tune_requires.das (9 cases, host-independent);
tests/language/cpu_supports.das gains arm64 coverage and loses a comment that
this change made false.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune_kernels: derive the summary from report() instead of parallel arrays
The shipped-fallback fact lived in three hand-maintained copies: the
[tuned(fallback=)] annotation, report()'s baseline argument at 23 call sites,
and the kfall array. Two of them were display-only; report()'s baseline is not
— a sub-0.5% win reverts to it, and that decides what lands in the sidecar.
report() is called exactly once per kernel and already holds all three values,
so it now records (kernel, winner, fallback) in call order and the summary
reads that back. kfall, knames and kwin — three parallel 25-entry arrays —
are gone, and the summary can no longer disagree with the decision it reports,
because it IS that value.
All three copies agreed before this change (verified across all 25 kernels), so
this is a refactor with no behavioural delta: same 25 lines, same order, same
note logic. The winner locals stay — they still feed the sidecar table, which
carries extra semantics the summary does not (softmax_sink mirrors softmax,
plus explicit entries for kernels this half does not sweep).
TUNED_KERNEL_COUNT stays hand-written: it is the progress denominator and is
needed before the first kernel runs, so it cannot come from the results. main
now compares it against the rows actually collected and says so if they differ,
rather than letting the bar quietly misreport.
The remaining duplicate is annotation <-> report baseline. That one has to close
before any kernel adopts a per-ISA fallback chain, since a chain resolves per
box and a literal baseline argument cannot follow it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune_kernels: derive the shipped fallback from the annotation, not literals
The last duplicate. report()'s baseline was 23 hand-written literals restating
the [tuned(fallback=)] annotations, and it is not cosmetic: a sub-0.5% win
reverts to the baseline, so a wrong one changes what ships. With a per-ISA
chain the literal could not be right at all — a chain resolves per box.
[tuned] now banks each kernel's resolved fallback and [dasllama_fallbacks]
emits dasllama_tuned_fallbacks() from that bank; report() looks it up. All 23
literals are gone. Verified the derived values equal the removed literals for
all 25 swept kernels, and the registry carries all 34 [tuned] kernels.
Probed the module-hop risk before building on it: a bank filled during the math
modules' compile IS visible to a macro applied in tune_kernels (34 entries),
because both are the same macro module. The per-requiring-module-copy trap
llvm_tune documents applies across macro modules, not within one.
Proven with a real chain on rmsnorm: gated on dotprod (present here) the
summary reports the fallback as vec16; gated on i8mm (absent) it reports plain.
Both said "plain" under the literals, and the noise-floor guard would have
judged against the wrong default.
Also: `explicit` is a reserved word (DAS_EXPLICIT, the generic-parameter
modifier) — hit while naming a local. Added to CLAUDE.md's reserved list, which
had label/expect/pass but not this one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: wire daslib/tty and the new fio terminal builtins into das2rst
A new daslib module and two new fio externs both trigger doc.yml. Registers the
module (require + document_module_tty + the call + the sec_io toctree + the
stdlib index) and groups is_terminal/terminal_width under fio's new "Terminal
queries" heading, since an ungrouped public function lands in Uncategorized and
fails CI. Fills the three handmade stubs das2rst generated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: hoist the arm64 feature includes out of namespace das
The arm64 detection block put <sys/sysctl.h>, <sys/auxv.h> and <asm/hwcap.h>
inside `namespace das` — the namespace opens at the top of the file and the
block sits ~1950 lines in. It built here only because macOS takes the __APPLE__
branch and clang tolerated it; the linux branch pulls two more headers into
das::, and a mac-only syntax pass never compiles that path at all.
Headers and the HWCAP_* fallback defines move to file scope; the helper
functions stay where they were. No behavioural change — same declarations, same
macros, just not injected into the namespace.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: archive the tune progress-UX design notes
The arc ships with this branch, so per skills/doc_archiving.md the plan doc
moves to history/compiler/ rather than sitting stale in a live module dir. Its
operative content is now skills/tune.md (user-facing) and skills/llvm_tune.md
(internals); what remains is the record of why it is shaped this way. Ledger
line added to history/README.md; no inbound references to the old path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: include windows.h for the arm64 Windows cpu_supports branch
The _M_ARM64 path calls IsProcessorFeaturePresent with PF_ARM_* constants, but
nothing in this TU's include graph pulls windows.h in — include/daScript/ does
not include it anywhere — so an arm64 Windows build would not compile. CI has
no windows-arm64 lane, so this would have shipped latent.
Guarded to arm64 + _WIN32, with NOMINMAX and WIN32_LEAN_AND_MEAN, so no lane CI
actually builds sees any change. Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* watchdog: clear published tune state when a child starts
stream_child kept `tune` local per child, but STATE["tune"] was only written
when an event arrived — so the tune-bootstrap restart, which is the normal
first-run path, left the control page showing the finished tune's counters for
the rest of the run. The relaunched child is already tuned and emits no events
at all, so nothing ever overwrote them.
Publish an empty tune state as each child starts. Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune_kernels: close a kernel whose bench returned early
bench_laneq4x4 returns before report() on non-arm64 or without -jit, and
report() is the only place that emits the end event and records a result row.
kernel_begin had already announced the kernel, so on those hosts the outer
counter stopped one short of its plan for the rest of the run — the bar never
completed, the summary silently dropped the row, the hand-written-count check
misfired, and watchdog's STATE["tune"] never converged.
Fixed in kernel_done rather than at the one call site: it brackets every kernel
in main and runs even when the bench returns early, so any future skip path is
covered by construction. Audited the other 22 bench functions — laneq4x4 is the
only one with a non-report return. Skipped kernels now render as "skipped"
instead of a blank winner, and `skipped` joins the documented verdict set.
Caught by Copilot on #3583. Verified the normal -jit path is unchanged:
25 begin / 25 end against plan total=25, 25 summary rows, no count-drift note.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: a new plan clears the previous scope's kernel state
consume_event's plan branch set the outer counters but left kernel/phase/inner
counters/live from the scope before it. One relay sees BOTH dasllama halves, so
after the generator half ends, the kernel half's plan left the display showing
"0/25 confirm_e2e_prefill" — and that is not a single frame: tune_kernels has
~30 lines of fixture setup between its plan and its first kernel_begin, so the
wrong kernel name is on screen for all of it.
plan now rebuilds the whole state, which is what a fresh scope means; begin
already did the same for per-kernel fields. Test added for the two-plan
sequence.
Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* watchdog: clear the per-round fields when a kernel ends
apply_tune_event's "end" cleared rounds/live but left round and phase from the
last step, so between kernels STATE published an incoherent in-flight round —
round=47 against rounds=0 — which a status page renders verbatim. The das
renderer hides those fields when innerTotal is 0, but STATE has no such guard;
it is read raw.
Same class as the plan-reset fix in llvm_tune, and more visible here for that
reason. Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* watchdog: a hostile @tune line must not kill the streaming thread
emit(logger, "tune", pid=..., kind=kind, **fields) splats parsed fields as
kwargs, so a line carrying pid= or kind= is a duplicate-keyword TypeError, and
ts=/event= would silently shadow the log envelope. The child's stdout is
arbitrary bytes — the watchdog also supervises non-daslang programs — so that
input is allowed by contract, and parse_tune_event's docstring already promises
never to raise on malformed input.
The blast radius is bigger than a lost log line: stream_child runs in a daemon
thread, so the exception kills it silently and the watchdog keeps running blind
— no stage detection, no child log relay, and no tune_restart_seen, which is
what tells exit 3 apart from a crash. A garbled line would have turned every
subsequent tune bootstrap into a backoff restart.
Reserved keys are dropped before the splat. Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tune: a must-see line no longer collides with the live display
report()'s "no passing variant" printed straight to stdout while the bar was
live, so it landed on the bar's line and the next redraw wrote over it — the one
message you must not lose was the one most likely to be destroyed.
Routing it through tune_detail (the obvious fix) would be worse: that mutes
under normal verbosity, so a hard failure would vanish entirely. Added
tune_progress_note instead — it wipes the bar's line, prints the text, and
leaves the display armed so the bar redraws underneath. Silent still suppresses.
Verified on a pty by replaying the CR/LF stream the way a terminal does:
k0: no passing variant
[######--------------] 1/3 k1 finalists 2/4 4 live 0s
Copilot also flagged the summary block for the same reason; that one is fine —
it runs after tune_progress_finish() has already closed the display.
Caught by Copilot on #3583.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent ef978ae commit 8d2c7c1
32 files changed
Lines changed: 1799 additions & 416 deletions
File tree
- daslib
- doc
- reflections
- source/stdlib
- handmade
- history
- compiler
- include/daScript/simulate
- modules
- dasLLAMA
- dasllama
- harness
- dasLLVM
- daslib
- tests
- skills
- src/builtin
- tests
- aot
- daslib
- language
- utils/watchdog
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
304 | 304 | | |
305 | 305 | | |
306 | 306 | | |
307 | | - | |
| 307 | + | |
308 | 308 | | |
309 | 309 | | |
310 | 310 | | |
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
220 | 221 | | |
221 | 222 | | |
222 | 223 | | |
| 224 | + | |
223 | 225 | | |
224 | 226 | | |
225 | 227 | | |
| |||
648 | 650 | | |
649 | 651 | | |
650 | 652 | | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
651 | 662 | | |
652 | 663 | | |
653 | 664 | | |
| |||
1839 | 1850 | | |
1840 | 1851 | | |
1841 | 1852 | | |
| 1853 | + | |
1842 | 1854 | | |
1843 | 1855 | | |
1844 | 1856 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| 166 | + | |
166 | 167 | | |
167 | 168 | | |
168 | 169 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| 101 | + | |
0 commit comments