← Docs hub

Device Source Freshness Contract

이 문서는 DeviceAgent가 Cloud Planner에 전달하는 상태값이 언제 관찰됐고, 지금 계획과 답변에 사용해도 되는지를 설명한다.

쉽게 설명하면

device_context를 만든 시각과 센서가 실제 값을 본 시각은 다르다. 이전에는 오래된 배터리나 공기질 값을 새 Context에 다시 담으면 Planner가 현재 값으로 오인할 수 있었다. 이제 각 source에 관찰 시각과 사용 가능성을 붙이고, Cloud는 명시적으로 오래되거나 무효인 값을 조건과 답변에서 제외한다.

센서 또는 상태 producer
-> SourceFreshnessTracker
-> DevicePlanningContextProvider
-> On-device voice_context
-> Cloud compact context
-> Planner condition 또는 사용자 답변

이 경계는 사용자 문장이나 keyword를 검사하지 않는다. 어떤 발화든 같은 source 신뢰 계약을 사용한다.

왜 source를 두 종류로 나누는가

종류 대표 source 현재 정책 이유
주기 샘플 배터리, 공기질 관찰 후 TTL 만료 새 샘플이 계속 들어와야 현재값으로 볼 수 있음
이벤트 기반 현재 상태 AWS IoT, 음성 LLM pipeline 현재 부팅에서 producer가 보고한 뒤 다음 상태 변경·무효화까지 유지 상태가 그대로라는 이유로 callback이 반복되지 않으므로 임의 TTL을 주면 정상 상태도 stale이 됨

1차 운영 TTL은 배터리 300000ms, 공기질 60000ms다. 값은 SourceFreshnessTracker 중앙 상수로 관리한다. 실기기 샘플 cadence를 확인한 뒤 조정할 수 있으며 발화별 예외값으로 분산하지 않는다.

MR6 Context 계약

루트 schema_version=device_context.v1은 호환성을 위해 유지하고, freshness_contract_version=device-source-freshness.v1을 추가한다.

{
  "schema_version": "device_context.v1",
  "freshness_contract_version": "device-source-freshness.v1",
  "snapshot_ts": 1785400000000,
  "battery": {
    "available": true,
    "percent": 82,
    "observed_at_ms": 1785399999000,
    "freshness_ms": 1000,
    "ttl_ms": 300000,
    "source_valid": true,
    "stale": false,
    "usable": true,
    "source_state": "ready",
    "expiry_mode": "ttl"
  }
}
필드 의미
observed_at_ms source producer가 상태를 받은 시각
freshness_ms Context 조립 시각에서 관찰 시각을 뺀 값
ttl_ms 주기 source 허용 기간. 이벤트 기반은 0
source_valid producer가 값 자체를 유효하다고 판정했는지
stale source 무효 또는 TTL 초과 여부
usable Planner가 현재 조건·답변 근거로 사용 가능한 최종 판정
source_state ready, warming_up, connected, idle, unobserved 등 bounded 상태
expiry_mode ttl, event_driven, unknown

관찰 전에는 fail-closed로 다음과 같이 표현한다.

{
  "observed_at_ms": 0,
  "freshness_ms": -1,
  "source_valid": false,
  "stale": true,
  "usable": false,
  "source_state": "unobserved",
  "expiry_mode": "unknown"
}

공기질 warmup 중에는 sample이 있어도 source_valid=false, source_state=warming_up이므로 자율 청정 조건이나 공기질 판단 근거로 사용하지 않는다.

Cloud 사용 경계

Cloud compact context는 source별 metadata를 source_freshness에 allowlist로 투영한다.

구현 위치

MR6 DeviceAgent

Cloud A2A

검증 상태

경계 결과
Source 유형·TTL·무효·out-of-order 단위 테스트 통과
DeviceAgent 관련 집중 테스트 통과
DeviceAgent 전체 JVM 테스트 227 passed
DeviceAgent APK 빌드 성공
Cloud 영향 모듈 79 passed
Cloud 광역 회귀 596 passed, 기존 untracked 가상 E2E 상태명 불일치 1건 별도
platform-signed 실기기 source cadence·E2E 미검증

Cloud 전체 collection에는 Windows 전용 key 경로와 현재 없는 모듈을 참조하는 기존 테스트 5개가 있어 제외했다. 위 수치는 해당 collection blocker를 제외한 결과다.

남은 범위

  1. 실기기에서 배터리와 공기질 producer 주기를 측정해 TTL 운영값을 검증한다.
  2. 위치, Map revision, Security, Streaming에도 source별 신뢰 계약이 필요한지 같은 기준으로 감사한다.
  3. Console에서 source freshness와 차단 이유를 내부 진단용으로 표시하되 사용자 TTS에는 노출하지 않는다.
  4. platform-signed 빌드에서 오래된 값 차단과 새 sample 복구를 E2E 검증한다.

관련 문서

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date