102 lines
3.1 KiB
GDScript
102 lines
3.1 KiB
GDScript
class_name OperationsOSObserver
|
|
extends RefCounted
|
|
|
|
## Passive actual Main/runtime observer for P24-02 operations and notification evidence.
|
|
## Captures OS process environment, screen scale, bubble state, and modal identity
|
|
## without modifying the active simulation model.
|
|
## Local unit fixture observations are strictly separated from candidate normal OS
|
|
## input evidence (which requires formal native OS capture receipts).
|
|
|
|
var pid := 0
|
|
var platform := ""
|
|
var window_size := Vector2i.ZERO
|
|
var observations: Array[Dictionary] = []
|
|
var bubble_records: Dictionary = {} # Maps actor_id -> latest bubble record
|
|
var bubble_history: Array[Dictionary] = [] # Chronological history of all bubble state transition events
|
|
var modal_records: Array[Dictionary] = []
|
|
var cutin_records: Array[Dictionary] = []
|
|
var save_records: Array[Dictionary] = []
|
|
|
|
|
|
func _init() -> void:
|
|
pid = OS.get_process_id()
|
|
platform = OS.get_name()
|
|
|
|
|
|
func capture_environment(tree: SceneTree, main: Control) -> Dictionary:
|
|
var root: Window = tree.root if tree != null else null
|
|
window_size = root.size if root != null else Vector2i.ZERO
|
|
var report := {
|
|
&"pid": pid,
|
|
&"platform": platform,
|
|
&"window_size": [window_size.x, window_size.y],
|
|
&"main_present": is_instance_valid(main),
|
|
&"captured_at_msec": Time.get_ticks_msec(),
|
|
&"fixture_scope": &"local_unit_fixture_only_not_native_os_input_evidence",
|
|
}
|
|
observations.append(report)
|
|
return report
|
|
|
|
|
|
func record_bubble(actor_id: StringName, kind: StringName, source_state: int) -> void:
|
|
var record := {
|
|
&"actor_id": actor_id,
|
|
&"kind": kind,
|
|
&"source_state": source_state,
|
|
&"recorded_at": Time.get_ticks_msec(),
|
|
}
|
|
bubble_records[actor_id] = record
|
|
bubble_history.append(record)
|
|
|
|
|
|
func get_latest_bubble(actor_id: StringName) -> Dictionary:
|
|
return bubble_records.get(actor_id, {})
|
|
|
|
|
|
func get_bubble_history() -> Array[Dictionary]:
|
|
return bubble_history.duplicate(true)
|
|
|
|
|
|
func record_modal_event(dialog_name: String, action: String, details: Dictionary = {}) -> void:
|
|
modal_records.append({
|
|
&"dialog_name": dialog_name,
|
|
&"action": action,
|
|
&"details": details.duplicate(true),
|
|
&"recorded_at": Time.get_ticks_msec(),
|
|
})
|
|
|
|
|
|
func record_cutin(kind: StringName, heading: String, message: String) -> void:
|
|
cutin_records.append({
|
|
&"kind": kind,
|
|
&"heading": heading,
|
|
&"message": message,
|
|
&"recorded_at": Time.get_ticks_msec(),
|
|
})
|
|
|
|
|
|
func record_save_label(path: String, display_name: String, is_fresh: bool) -> void:
|
|
save_records.append({
|
|
&"path": path,
|
|
&"display_name": display_name,
|
|
&"is_fresh": is_fresh,
|
|
&"recorded_at": Time.get_ticks_msec(),
|
|
})
|
|
|
|
|
|
func get_summary() -> Dictionary:
|
|
return {
|
|
&"pid": pid,
|
|
&"platform": platform,
|
|
&"window_size": [window_size.x, window_size.y],
|
|
&"observations_count": observations.size(),
|
|
&"unique_actors_tracked": bubble_records.size(),
|
|
&"bubbles_tracked": bubble_history.size(),
|
|
&"bubble_history_count": bubble_history.size(),
|
|
&"bubble_events_count": bubble_history.size(),
|
|
&"modals_tracked": modal_records.size(),
|
|
&"cutins_tracked": cutin_records.size(),
|
|
&"saves_tracked": save_records.size(),
|
|
&"fixture_scope": &"local_unit_fixture_only_not_native_os_input_evidence",
|
|
}
|