Trentin Davide
07197ed8df
chore(portfolio): v1.0.0 prep — docs, CI, demos
...
CI / build (push) Waiting to run
Autonomous portfolio prep batch. All gates green: 207 tests pass on
iosSimulatorArm64Test, assembleRelease green, apiCheck green, app builds.
Docs:
- CHANGELOG.md (Keep-a-Changelog, retroactive v0.1-v0.5)
- CONTRIBUTING.md (build + style + PR workflow + perf rules)
- chart-realtime/README.md rewrite for v0.5.0 API surface
- docs/PERFORMANCE.md (LoD perf table, alloc budget, memory budget,
stability report, threading model)
CI (.github/):
- workflows/ci.yml — macos-latest, JDK 21, konan cache, full gate
- workflows/release.yml — tag-triggered, GitHub release with XCFramework
+ AAR; Maven Central as commented TODO (needs OSSRH + GPG secrets)
- dependabot.yml — weekly gradle + actions updates
- pull_request_template.md + 2 issue templates (bug, feature)
Android demo polish:
- DemoScreen + ControlPanel (Material3 surface)
- Sample rate slider (10..200Hz), 1-6 signal count, per-signal waveform
picker (sine/square/triangle/noise), window seconds, LoD picker, Y
label mode, Y formatter, interaction toggle, theme switch, status chips
- Single producer coroutine (cleaner crosshair readout, easier rate
accounting)
- SignalGenerator + WaveformType + DemoConfig + PushCounter
iOS demo scaffold (samples/ios/ChartRealtimeDemo/):
- SPM Package.swift with local binaryTarget pointing to
chart-realtime/build/XCFrameworks/debug/ChartRealtime.xcframework
- DemoApp.swift + DemoView.swift (smoke test confirming Kotlin types
accessible from Swift)
- README documents the ComposeUIViewController shim needed in
chart-realtime/src/iosMain/ for full SwiftUI hosting (deferred to
v1.0.0 T1)
- xcodebuild against iOS Simulator builds green
Debt:
- gradle.properties: removed kotlin.internal.klibs.non-packed=false
(Compose-MP 1.11.0 final no longer needs the bypass; apiCheck +
native compile + 207 tests still green)
- 8 remaining deprecation warnings tied to com.android.library + KMP
plugin combo; clearing them requires migration to
com.android.kotlin.multiplatform.library 9.2.0 which forces ABI
baseline regen + Maven publish restructure + XCFramework hierarchy
expansion. Deferred as dedicated ticket.
Skipped (need user):
- CODE_OF_CONDUCT.md (content classifier blocks Contributor Covenant
verbatim)
- Maven Central T1 (Sonatype + GPG)
- Benchmark vs competitors T4 (methodology + Maven coords)
- Logo/banner/GIF T7 (design assets)
- Tag + GitHub release T10 (rename pending)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 10:54:26 +02:00
Trentin Davide
af6814e2b8
feat(chart): v0.5.0 architecture + interaction
...
Ships v0.5.0 via kmp-manager 6-phase flow. 13 plan tasks (D1, T1-T10, D3, D4),
14 agent calls, 6 P-groups. 107 → 207 tests on iosSimulatorArm64.
Toolchain (D1):
- Kotlin 2.1.0 → 2.3.21
- Compose-Multiplatform 1.8.0 → 1.11.0
- Android Gradle Plugin 8.7.3 → 9.2.0
- Gradle 8.11.1 → 9.5.1
- coroutines 1.9.0 → 1.11.0, kotlin-test → 2.3.21
- Drop kotlinx-datetime; use stdlib kotlin.time.Clock
- Drop iosX64 target (Compose-MP 1.11.0 has no ios_x64 variant)
Architecture (T1-T6, T10):
- TieredBuffer.snapshotWindow: bisect-based windowed snapshot
- New lod/ package: LodStrategy interface + MinMax/Lttb/MinMaxLttb impls
(MinMaxLttb SOTA per arXiv 2305.00332, 1.80× faster than pure LTTB)
- New render/SignalRenderer: public interface + LineSignalRenderer object
- New render/AxisFormatter: 4 default impls (Time, Decimal, DateTime, Unit)
- HARD BREAK: deleted LodMode, LodDecimator, ChartConfig.targetFps
- ChartConfig split: DataConfig + AxisConfig + RenderConfig + FrameRate sealed
- @Immutable/@Stable on all public types (0 unstable)
- RealtimeChartState.clear() API
Interaction layer (T7):
- New interaction/ package
- ChartInteractionState + rememberChartInteractionState()
- ViewportMode sealed: Following / Frozen / History(anchorMs)
- Pinch zoom + drag pan + tap crosshair gestures
- Swipe-to-edge resumes Following
- InverseProjection: pixel → ms + bisect nearest-sample
Perf finishing (T8, T9, D3):
- LineSignalRenderer Stroke cache, AxisRenderer TextStyle cache
- resolveYRange Pair<Float,Float> → FloatArray out-param
- RealtimeChartState.signalsArray cached (invalidated on add/remove only)
- LTTB upper-bound aligned to half-open [start, start+windowMs) semantic
Correctness (D4):
- NumberFormat.formatFixed Long overflow guard @ |v|≥1e19
ABI baseline regenerated:
- chart-realtime.api: 161 → 428 LOC
- chart-realtime.klib.api: 211 → 501 LOC
Modules touched: chart-realtime (lib), app (consumer), gradle (toolchain),
.paul (state).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 00:05:43 +02:00
Trentin Davide
0e3b79e2da
feat(chart): v0.4.0 portfolio hardening
...
Ship 15-task plan via kmp-manager group-by-group flow. Library moves
from "prototype" to "senior-engineer-built KMP library" per 3-reviewer
audit (android-reviewer + mobile-performance-reviewer + mobile-architect).
Critical fixes:
- LICENSE MIT (T1) — legal blocker resolved
- explicitApi() Strict + BCV 0.16.3 + klib enabled (T2) — ABI locked
baseline: chart-realtime.api 161 LOC + chart-realtime.klib.api 211 LOC
- Internal lockdown: CircularBuffer, TieredBuffer, LodDecimator,
dataVersion, rememberFrameTick (T3)
- kotlinx-datetime 0.6.2 replaces expect/actual currentTimeMs (T4)
Platform.kt + .android.kt + .ios.kt deleted
- CircularBuffer.writeIndex Int -> Long (T5) — fix 124d overflow @ 200Hz
- Remove !! and @Suppress("UNUSED_EXPRESSION") from commonMain (T6)
- Remove dead config: maxBufferSeconds, xLabelDecimals,
SignalConfig.label (T7)
Correctness:
- POSITIVE_INFINITY/Float.MAX_VALUE sentinels -> hasData flag (T8)
- Snapshot.withMutableSnapshot + SnapshotApplyConflictException retry
in push/addSignal/removeSignal (T9)
- dataVersion mutableLongStateOf — Compose-observable, idle = 0
recompositions (T10) — RenderLoop.kt deleted, targetFps @Deprecated
- Single buffer.snapshot() per signal per frame via SignalEntry
per-signal scratch arrays (T11) — render-time snapshot cost halved
- M4 binning Tier1/Tier2: firstTs/V + minTs/V + maxTs/V + lastTs/V
with chronological dedup (T12) — no C7 vertical spike artifacts.
TIER1/TIER2 CAPACITY x2 -> x4 (TOTAL 77.4k -> 94.8k)
- NaN/Inf/backward-timestamp guards on push (T13) — silent drop,
per-signal lastPushedTs tracking, KDoc contract
Test gap fill:
- NumberFormat extracted from AxisRenderer to internal object (T14)
+38 tests pinning rounding/scientific/time-format behavior
- TieredBufferTest +15 tests: tier roll, window-crossing, clear,
edge cases (T15)
- LodDecimatorTest +10 LTTB-specific branch coverage tests (T15)
Test count: 33 -> 107 (+74).
ABI: 211/272 -> 161/211 LOC (locked, baseline committed).
Deferred to v0.5.0:
- Bump kotlinx-datetime 0.6.2 -> 0.7.x (needs Kotlin 2.1.20+)
- Remove ChartConfig.targetFps (currently @Deprecated, ignored)
- NumberFormat Long overflow @ 1e19 (safe via current routing)
- LTTB upper-bound inclusive vs snapshot half-open semantic mismatch
- Macrobench setup for -30% frame-time verification
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:27:15 +02:00
Trentin Davide
d6f51cdef2
feat(ios): iOS build pipeline + XCFramework, fix K/Native source bugs
...
Modules: chart-realtime (commonMain, iosMain), root, .paul
- chart-realtime/build.gradle.kts: applyDefaultHierarchyTemplate() + XCFramework("ChartRealtime") over iosX64/iosArm64/iosSimulatorArm64, baseName CamelCase
- commonMain RealtimeChartState/CircularBuffer: switch to kotlin.concurrent.Volatile, add kotlin.jvm.JvmName import (OptionalExpectation)
- commonMain AxisRenderer: replace JVM-only String.format with multiplatform formatFixed/formatScientific/pow10 helpers
- iosMain Platform.ios.kt: NSDate() + timeIntervalSinceReferenceDate + 978_307_200s 1970-epoch offset (K/Native binding has no direct timeIntervalSince1970)
- gradle.properties: remove Linux JDK pin (rely on JAVA_HOME)
- .paul: phases plan, STATE+ROADMAP updates
Acceptance: A1 compile 3 iOS targets, A2 linkDebugFrameworkIosSimulatorArm64, A3 iosSimulatorArm64Test (33 tests, 0 failures), A4 assembleChartRealtimeXCFramework (ios-arm64 + ios-arm64_x86_64-simulator slices), A5 Android assembleRelease/publishToMavenLocal --dry-run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:45:21 +02:00
dtrentin
73bbd9ddec
feat(chart-realtime): v0.3.0 — dirty flag render, targetFps=30, iOS targets, KDoc, README
...
- Dirty-flag render: dataVersion counter in RealtimeChartState, skip Canvas draw
when no new data since last frame (zero GPU work when sensor idle)
- targetFps=30 default in ChartConfig (pass null for max display refresh rate)
- iOS targets: iosX64, iosArm64, iosSimulatorArm64 + Platform.ios.kt actual
- KDoc: RealtimeChart params, dataVersion, ChartConfig.targetFps, LodMode entries,
AxisLabelMode entries
- README: fixed Maven coords, added LoD/AxisLabels/Material3 sections, updated
feature list and performance notes
- Tests: RealtimeChartStateTest (17 tests, dataVersion + signal lifecycle)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:11:37 +02:00
dtrentin
b9ee5ddfa3
Initial commit: chart-realtime KMP library v0.4.1-SNAPSHOT
...
- RealtimeChart composable with Canvas-based rendering
- TieredBuffer: 3-tier ring buffer (5min full-rate, 10min @10Hz, 45min @1Hz) for 1h data support with ~5MB footprint
- LodDecimator: MEAN / MIN_MAX / MIN_MAX(default) / LTTB render-time decimation
- AxisRenderer: X/Y axis with INSIDE/BESIDE/HIDDEN label modes, T0-relative timestamps, scientific notation
- SignalRenderer: clipRect-bounded path rendering with LoD
- ChartTheme: Material3-compatible dynamic theming (light/dark)
- package: dev.dtrentin.chart
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 01:48:51 +02:00