SKIX 도메인 정책 사양 카탈로그
왜 별도 카탈로그가 필요한가
현재 제품 조건은 TiltingManager, CmdPolicyManager, WssPolicyChecker,
AirCleaningPolicy, SKMLauncherApp와 여러 도메인 Manager에 분산되어 있다. 단순히 클래스를
ManagerService로 이동하면 스파게티의 위치만 바뀐다. 따라서 사양의 소유권은 도메인에 두고,
서로 다른 도메인의 충돌 판정은 하나의 PolicyManagerService가 담당하도록 분리한다.
- 이 그림이 답하는 질문: 주행·대화·청정처럼 서로 다른 기능 요구가 충돌하면 누가 최종 결정을 내리는가?
- 읽는 순서: 왼쪽 기능별 요구에서 시작해 가운데 공통 정책 판단을 거쳐 오른쪽 작업 실행으로 읽는다.
- 현재 검증 범위: 정책 우선순위와 틸팅 첫 사례는 JVM 검증 범위다. 전체 정책 목록과 실제 모터 동작은 실기기 검증 전이다.
정책 처리 원칙
도메인 상태
→ 도메인 소유 PolicyRequirement
→ PolicyManagerService의 RESOLVED / CONFLICT / NO_REQUIREMENT
→ WorkflowManagerService의 선행조건 순서화
→ ResourceManagerService의 공유 자원 lease
→ DeviceAgent privileged adapter의 단일 물리 명령
→ EvidenceManagerService의 실제 완료 확인
- Mobility는
MOVING이라는 자기 상태로부터TILT_DOWN요구만 생성하며 MCU를 직접 호출하지 않는다. - LLM·Streaming·WSS는 interaction 상태로부터
TILT_UP요구만 생성하며 주행 상태를 읽지 않는다. - 우선순위는
SAFETY > PRODUCT_INVARIANT > USER_INTENT > OPTIMIZATION으로 명시한다. - 같은 tier의 상반된 필수 요구는 코드 등록 순서로 결정하지 않고
CONFLICT로 fail-closed 처리한다. - Launcher는 결정과 reason code를 표시할 뿐, 별도 정책 권위가 되지 않는다.
- 정상 정책과 ICT·SelfTest·MCU test의 privileged override를 같은 경로로 섞지 않는다.
첫 구현: 주행 중 틸트 DOWN
| Rule ID | 소유 도메인 | 요구 | Tier / enforcement | 현재 판정 |
|---|---|---|---|---|
mobility.driving-tilt-down |
Mobility | 주행 전·주행 중 TILT_DOWN |
Product invariant / precondition + continuous | NORMALIZED, JVM 검증 |
interaction.llm-active-tilt-up |
Interaction / LLM | LLM 활성 중 TILT_UP 요청 |
User intent / continuous | NORMALIZED, JVM 검증 |
interaction.streaming-active-tilt-up |
Interaction / Streaming | Streaming 활성 중 TILT_UP 요청 |
User intent / continuous | NORMALIZED, JVM 검증 |
interaction.wss-active-tilt-up |
Security interaction / WSS | WSS 활성 중 TILT_UP 요청 |
User intent / continuous | NORMALIZED, JVM 검증 |
MOVING + LLM_ACTIVE 통합 JVM 계약에서는 Mobility의 DOWN이 선택되고 LLM의 UP 요구가
suppressed evidence로 남는다. 구현 커밋은 5c52c66이다. 이 단계는 새 evaluator만 추가했으며
기존 TiltingManager의 물리 명령권은 바꾸지 않았다.
추가 발견 후보
DISCOVERED 항목은 레거시 위치를 확인한 것이며 최종 우선순위나 동작을 확정했다는 뜻이 아니다.
사양 원문과 오류·취소·재시작 조건을 확인한 뒤 NORMALIZED로 올린다.
| 후보 Rule | 영역 | 현재 분산 지점 | 반드시 정리할 충돌 |
|---|---|---|---|
mobility.low-battery-return |
AMR / Power | CmdPolicyManager, RobotMovementController, ErrorHandler |
S02/S03, station, docking 실패, cleaning, schedule |
cleaning.start-admission |
Cleaning | AirCleaningPolicy, CmdPolicyManager, cleaning managers |
battery, lock, error, 다른 작업, 부분 시작 rollback |
execution.schedule-admission |
Task / Scheduler | CmdPolicyManager, WssPolicyChecker, Launcher |
update, self-test, WSS, cleaning, movement, 재부팅 복구 |
update.global-command-block |
Update | WssPolicyChecker, CmdPolicyManager, Launcher |
허용 예외, 종료 evidence, stale update flag |
camera.exclusive-lease |
Vision / Camera | CameraAccessPolicy, camera handlers |
shared/exclusive, owner death, timeout, 중복 acquire |
security.schedule-admission |
Security / WSS | WssPolicyChecker, WssManager, Launcher |
battery, station, camera, schedule slot |
ui.error-presentation-priority |
UI | SKMLauncherApp, UI state classes |
error/update/security/cleaning/interaction 표시 우선순위 |
test.privileged-tilt-override |
Diagnostics | ICTState, SelfTestState, MCUTestActivity |
인증, TTL, owner death, 정상 정책 복귀 |
framework.service-ready-admission |
Framework lifecycle | 신규 lifecycle supervisor | owner가 READY가 아니면 operation 거부, dependency 장애 전파 |
mobility.single-state-authority |
Mobility | MovingController, CleaningTransaction, streaming AMR state |
movement/docking 상태의 writer 단일화 |
cleaning.operation-state-normalization |
Cleaning | CleaningTransaction, AirCleaningPolicy |
mode/action/pause/fan/movement 분리, 고정 return characterization |
interaction.pause-hold |
Workflow / Task | InterScheduleManager |
owner death·timeout·cancel·resume의 hold release |
security.warning-vs-blocker |
Security / Policy | WssPolicyChecker |
informational bit를 admission blocker로 승격하지 않음 |
schedule.trigger-admission |
Schedule | ScheduleAlarmReceiver |
duplicate/due detection과 admission/Task submission 분리 |
iot.connection-lifecycle |
IoT | IotAgent service·handler·connection callback | connection recovery와 delivery completion 분리 |
llm.processing-state |
LLM | LlmManager |
listen/think/speak와 component health 분리 |
task.server-owned-policy |
Task | MR6 TaskPolicyRegistry와 caller/resource policy |
caller Bundle의 bypass·priority·resource flag를 권위로 사용 금지 |
전체 행과 발견 기준은 소스 저장소의 docs/refactor/skix-product-policy-catalog.md에서 관리한다.
후보는 도메인 간 상태 직접 읽기, 전역 flag set/clear, 긴 조건문의 숨은 우선순위, UI와 DeviceAgent의
중복 검증, handler delay·polling, HAL/MCU 직접 호출을 검색해 계속 추가한다.
서비스 라이프사이클과 도메인 상태 감사는
이 후보들이 어떤 state owner와 lifecycle gate로 이동하는지 코드 근거별로 정리한다.
이관 상태 Gate
| 단계 | 판정 조건 |
|---|---|
DISCOVERED |
레거시 동작과 소스 위치 확인 |
NORMALIZED |
stable ID·owner·trigger·desired state·tier·release/evidence 계약과 JVM 테스트 보유 |
SHADOW_VERIFIED |
물리 명령 없이 기존 판정과 새 판정을 비교하고 차이 검수 |
ENFORCED |
새 서비스가 유일한 production 판단 권위이고 레거시 판단을 제거 또는 우회 |
DEVICE_VERIFIED |
재시작·취소·timeout·오류·센서/모터 완료를 실기기에서 통과 |
안전·공유 자원 영향이 큰 Motion/Tilt/Docking/Charging부터 진행하고, 그 다음 Task admission·OTA·WSS, Camera/Mic/Speaker 등 resource lease, 마지막으로 UI 표시 정책을 이관한다. 큰 Manager 전체를 한 번에 옮기지 않고 정책 하나의 수직 slice를 Gate 끝까지 통과시킨다.
상태 판정
| 설계 완료 | 소스 반영 | JVM 검증 | APK 빌드 | 실기기 검증 |
|---|---|---|---|---|
| 분산 소유 + 중앙 조정 확정 | Policy core와 Mobility/Interaction rule factory | arbitration·domain·통합 계약 PASS | SkixFrameworkService.apk PASS |
실기기 미검증 |
- 소스 커밋:
5c52c6681a4ef3c43205d6978f8a3b6bd19db086 SkixFrameworkService.apkSHA-256:a23df7537ae0222dab68708ca71102eb2f6c97f65a0955953a8adf527d198966- 아직 Binder facade, shadow comparison, Workflow/Resource/Evidence 연결, legacy cutover는 없다.