feat(vehicle-hal): source health fail-closed consumption (PR-2)#72
Merged
Merged
Conversation
PR-1'in taşıdığı halStatusStore.sourceHealth (worker 1 Hz watchdog) artık HAL veri
akışında tüketiliyor → SESSİZ ECU FRAME KAYBI blokajı kapanıyor: kablo takılı ve
port açık olsa bile (native canStatus connected:true der) worker frame sessizliğini
görüyor ve CAN-özel sinyaller fail-closed oluyor.
- Provider snapshot'a bounded sourceHealth {can,obd,gps,ts} (yapısal DI; provider/
adapter store'ları doğrudan import etmez). Araç + sağlık abonelikleri TEK unsub'a
sarıldı → activeSubscriptionCount=1 invaryantı korunur.
- unknown (null) ≠ dead (false): null iken sahte disconnect YOK (W4B davranışı).
- can=false → yalnız CAN-ÖZEL sinyaller source:'none'/supported=false/value=null/
quality='unknown'/confidence=0. Füzyon (speed/rpm/fuel/odometer/reverse) başka
kaynak canlıysa supported kalır; rpm'in canRpm fallback'i CAN ölüyken bayat sayılır.
- Diriltme yasağı: can=true tek başına eski değeri supported yapmaz — yalnız değer
değişince (taze frame kanıtı) gerçek source/quality/confidence ile döner.
- Tek batch / tek HAL emit (W4A korunur); aynı durum duplicate ingest/emit üretmez.
- Bridge: tüm destek kalkınca connection.changed=false; kısmi kayıpta yayınlanmaz;
reconnect'te yalnız gerçek veriyle true.
- Teşhis: support_snapshot'a bounded sourceHealth {can,obd,gps,lastChangeAt}
(null≠false; sinyal değeri/CAN frame/VIN/koordinat yok).
- ignition üretilmez; yeni timer/polling yok.
- Background yanlış-pozitif riski: worker'a görünürlük sinyali TAŞINMIYOR (doğrulandı)
→ kanıtsız eşik EKLENMEDİ, açık risk olarak Ledger'a yazıldı.
- Ledger #56 🔴.
Kapsam dışı: W4D throttle, consumer migration, native canStatus, Kernel/Capability.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012M8LbxyAqd22EU1rqtTjft
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
sourceHealth teşhis raporunda görünüyor (can:false/obd:false/gps:true — araçsız doğru). Sahte disconnect yok (ingestedSignalCount=3 sabit), tek abonelik korunuyor (activeSubscriptionCount=1), bridge dropped=0, boot/CPU/RAM regresyonu yok. Background 45 sn testi: dönüşte gps:true kaldı ve HAL'e düşüş yansımadı; ancak lastChangeAt taşındı → arka planda geçici gps:false DIŞLANAMADI (risk sürüyor). Satır 🔴 KALIYOR: gerçek araç (can=false/reconnect/connection) ve low-tier eksik. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012M8LbxyAqd22EU1rqtTjft
…TH görünürlük gating PR #72 (source health → HAL fail-closed) arka planda YANLIŞ-POZİTİF üretebiliyordu: watchdog canlılığı monotonik saat farkıyla ölçer (_alive, VehicleCompute.worker.ts:409-411); bu saat arka planda ilerler ama WebView timer'ı kısılır ve adaptör frame'leri durur → foreground dönüşündeki ilk tikte now-lastSeen >> timeout → kaynak SAĞLAMKEN can=false. Araç bağlıyken bu, CAN-özel sinyalleri gereksiz unsupported yapar ve bridge'ten sahte connection.changed=false/true çifti üretirdi. ÇÖZÜM (minimum, yeni timer YOK): - sourceHealthGate.ts (yeni, SAF: timer/DOM/store yok, zaman enjekte edilir) hidden → sağlık GEÇİŞİ dondurulur (lastSeen BOZULMAZ) foreground→ timeout SAATİ yeniden tabanlanır (arka plan süresi timeout'a YAZILMAZ) taze frame→ true · görünür zamanda gerçek timeout → false (gerçek kayıp MASKELENMEZ) ikisi de değilse → KARAR YOK (son bilinen değer korunur; yoksa unknown) - worker: bounded VISIBILITY {visible:boolean} kontrol mesajı; kapı YALNIZ SOURCE_HEALTH kararını etkiler — fusion/reverse/SAB ham _alive() kullanmaya devam eder. - resolver: TEK visibilitychange dinleyicisi (mevcut proje deseni), stop()'ta sökülür, duplicate durum POSTLANMAZ. Kapsam dışı bırakıldı: Event Bus/bridge/HAL/Kernel/Capability/DeepScan foundation, UI, SQL, throttle/coalescing, timer sayısı (worker setInterval 4 → 4). Testler: +27 (sourceHealthVisibilityGating) — visible alive→dead, hidden'da false yok, arka plan süresi timeout'a yazılmıyor, dönüşte anında false yok, taze frame → true, görünür timeout → false, CAN/OBD/GPS bağımsız, duplicate visibility pencereyi uzatmıyor, background→foreground event fırtınası yok, zero-leak cleanup. Suite 3571 yeşil · lint 0 hata · build OK · guard 113/113. Ledger #56 🔴 (gerçek araç + low-tier hâlâ eksik). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012M8LbxyAqd22EU1rqtTjft
…Xiaomi) Gerçek "Tanı Gönder" rapor gövdesinden (enstrümantasyonsuz): - Premise teyit: arka planda WebView `document.visibilityState === 'hidden'` döndürüyor. - SAHTE DEAD YOK: ~20 dk arka plan sonrası `sourceHealth.lastChangeAt` boot değerinde KALDI (1026.6) → arka planda SIFIR sağlık geçişi. (Düzeltme öncesi 45 sn arka plan aynı cihazda 3171 → 699171 taşımıştı.) - activeSubscriptionCount=1, halBridge.droppedCount=0, sahte connection.changed YOK. - 🟡 Foreground dönüşünde gps false→true çifti: arka plan saatinden DEĞİL, görünür zamandaki 5 sn GPS sessizliğinden (OS akışı geç başlıyor); ölçümsüz eşik eklenmedi. Ledger #56 🔴 KALIR — gerçek araç + low-tier hâlâ eksik. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012M8LbxyAqd22EU1rqtTjft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Amaç — sessiz ECU frame kaybı blokajını kapatmak
PR-1 worker'ın per-kaynak canlılığını (
SRC_TIMEOUT_CAN_MS=3s, 1 Hz watchdog)halStatusStore.sourceHealth'e taşıdı. Bu PR onu tüketiyor:Kablo takılı / port açık olsa bile (native
canStatusconnected:trueder —CarLauncherPlugin.java:3748-3756) ECU susarsa CAN-özel sinyaller artık fail-closed olur.Model
Provider snapshot'a bounded
sourceHealth { can, obd, gps, ts }eklendi — yapısal DI (provider/adapter store'ları doğrudan import etmez). Araç + sağlık store abonelikleri tek unsub'a sarıldı → teşhistekiactiveSubscriptionCount = 1invaryantı korunur. Yeni registry/DI container yok.unknown ≠ disconnected
nullfalsetrueSinyal-kaynak matrisi (testle kilitli)
can=falseisesource:'none'·supported=false·value=null·quality='unknown'·confidence=0:coolant_temp · oil_temp · throttle · battery_voltage · gear · ambient_temp · tpms · door_state · parking_brakespeed · rpm · fuel_level · odometer · reverserpm'in CAN fallback'i (canRpm) CAN ölüyken bayat sayılır ve kullanılmaz → fusedrpmde yoksa unsupported.ignition→ kaynak yok, üretilmez (guessed false yok).Diriltme yasağı (reconnect)
can=truetek başına eski değeri supported yapmaz: ölüm anındaki değer saklanır; sinyal ancak değer değişince (= taze frame kanıtı) gerçeksource/quality/confidenceile geri döner. Store frame gelmeyince eski değeri tuttuğu için bu, sahte eski değer diriltmesini yapısal olarak engeller.Batch / emit
Bir geçişte düşen (veya dönen) tüm sinyaller tek
hal.ingest(batch)→ tek HAL emit (W4A korunur). Aynı durum tekrarında duplicate ingest/emit yok. Batch throw ederse dedupe kirlenmez, sonraki refresh yeniden dener.Bridge (W4C)
Tüm supported sinyaller kalkınca
vehicle.connection.changed=false; kısmi kayıpta yayınlanmaz; reconnect'te yalnız gerçek veriyletrue.droppedCountartmıyor (testli).Diagnostic (PR #68 yüzeyi)
Bounded
sourceHealth { can, obd, gps, lastChangeAt }—nullilefalseayrı. Sinyal değeri (hız/RPM), CAN frame, VIN, koordinat, ham payload, event history, secret gönderilmez. Yeni endpoint/timer/otomatik gönderim yok.Kaynak kodda worker'a görünürlük/pause sinyali taşınmıyor (doğrulandı — VDL'de
visibilitychange/pause yok). Dolayısıyla uygulama arka plandayken worker timer'ı kısılır veya plugin event teslimi gecikirse yanlış-pozitifcan=falseüretilebilir. Ölçümsüz "N ardışık tur" eşiği eklenmedi (magic number yasağı); açık risk olarak Ledger'a yazıldı ve cihaz planında ölçülecek.Test / lint / build / guard
vehicleHalSourceHealthConsumption.test.ts— 25 test (unknown, CAN-dead matrisi, fallback, diriltme yasağı, batch/emit, bridge connection true/false/reconnect, lifecycle/tek abonelik, kapsam)platformRuntimeDiagnostics(yenisourceHealthbölümü) +workerSourceHealthTransport(adapter artık sağlığı snapshot'tan tüketiyor;halStatusStoredoğrudan import etmiyor)npm run test: 3544 test / 200 dosya yeşil ·lint: 0 hata ·build: başarılı ·guard: 113/113 yeşil (pre-existing_hasAnyFieldtimeout'u bu koşuda tekrarlamadı)Kapsam dışı
W4D throttle · consumer migration · native
canStatuswiring · worker watchdog davranışı ·VehicleSignalResolver·SystemBoot· Event Bus/bridge/HAL foundation · Kernel · Capability · Deep Scan · UI · SQL. Hiçbiri değişmedi.Rollback
Tek atomik commit →
git revert. Provider/adapter eski (health'siz) davranışa döner;sourceHealthyalnız bilgi olarak store'da kalır.🤖 Generated with Claude Code
https://claude.ai/code/session_012M8LbxyAqd22EU1rqtTjft
🔧 EK DÜZELTME (cf8aef7) — Background sahte "kaynak öldü" kapısı
Kök neden: watchdog canlılığı monotonik saat farkıyla ölçer (
_alive(),VehicleCompute.worker.ts:409-411). Bu saat arka planda ilerler, ama WebView timer'ı kısılır ve adaptör frame'leri durur → foreground dönüşündeki ilk tiktenow - lastSeen ≫ timeout→ kaynak sağlamkenfalse. Araç bağlıyken bu, CAN-özel sinyalleri gereksizsupported=falseyapar ve bridge'ten sahteconnection.changed=false/trueçifti üretirdi. (Önceki cihaz testinde 45 sn arka plansourceHealth.lastChangeAt'i 3171 → 699171'e taşımıştı.)Çözüm — Model C (+ görünürlük kanalı), yeni timer YOK:
sourceHealthGate.ts(timer/DOM/store yok; zaman enjekte edilir):hidden→ sağlık geçişi dondurulur (lastSeenbozulmaz)foreground→ timeout saati yeniden tabanlanır (arka plan süresi timeout'a yazılmaz)true· görünür zamanda gerçek timeout dolarsa →false(gerçek kayıp maskelenmez)unknown)VISIBILITY {visible:boolean}kontrol mesajı. Kapı yalnızSOURCE_HEALTHkararını etkiler — fusion/reverse/SAB ham_alive()kullanmaya devam eder. setInterval sayısı 4 → 4.visibilitychangedinleyicisi (mevcut proje deseni),stop()'ta sökülür, aynı durum tekrar postlanmaz.Reddedilen modeller: B (yanlış
falsestore'a yazılır → gelecekteki tüketiciler görür) · D (ölçümsüz "N ardışık tur" magic number).Testler: +27 (
sourceHealthVisibilityGating.test.ts) — görünürken alive→dead normal · hidden'da yenifalseyok · arka plan süresi timeout'a yazılmıyor · dönüşte anındafalseyok · taze frame →true· görünür-zaman timeout'u →false· CAN/OBD/GPS bağımsız · duplicate visibility pencereyi uzatmıyor · background→foreground event fırtınası yok · zero-leak cleanup. Suite 3571 yeşil · lint 0 hata · build OK · guard 113/113.🟢 Cihaz kanıtı (Xiaomi, araç YOK — gerçek rapor gövdesi, enstrümantasyonsuz):
document.visibilityState === 'hidden'döndürüyor.sourceHealth.lastChangeAtboot değerinde kaldı (1026.6) → arka planda SIFIR sağlık geçişi.activeSubscriptionCount=1,halBridge.droppedCount=0, sahteconnection.changedyok.gps:false→trueçifti gözlendi — arka plan saatinden değil, tasarım gereği görünür zamandaki 5 sn GPS sessizliğinden (OS konum akışı dönüşte geç başlıyor). Kalıcı hasar yok (ingestedSignalCount3'e döndü,droppedCount=0). Ölçümsüz grace eşiği eklenmedi.Hâlâ eksik (Ledger #56 🔴): gerçek araç (CAN canlı→ölü→dönüş) · low-tier cihaz (K24/T507) · araç bağlıyken foreground görünür-zaman timeout'unun CAN'de geçici
falseüretip üretmediği.