Fields every concrete task-state subclass carries. Mirrors ``typescript/src/Task.ts:45-57``. TS uses ``startTime``/``endTime`` in milliseconds; Python convention here is float seconds (``time.time()``) for natural arithmetic. ``output_offset`` is the read cursor for incremental disk
| 103 | |
| 104 | @dataclass(kw_only=True) |
| 105 | class TaskStateBase: |
| 106 | """Fields every concrete task-state subclass carries. |
| 107 | |
| 108 | Mirrors ``typescript/src/Task.ts:45-57``. TS uses ``startTime``/``endTime`` |
| 109 | in milliseconds; Python convention here is float seconds (``time.time()``) |
| 110 | for natural arithmetic. ``output_offset`` is the read cursor for |
| 111 | incremental disk-output reads (Phase 2 transcript writer + Phase 3 |
| 112 | notification XML); kept here on the base because every type writes to a |
| 113 | file, even if the path/format differs. |
| 114 | |
| 115 | ``notified`` is the duplicate-completion-message guard — once the parent |
| 116 | has been told a task finished, the flag flips to True via the atomic |
| 117 | check-and-set in WI-3.1's ``enqueue_agent_notification``. |
| 118 | |
| 119 | ``kw_only=True`` is set so subclasses can override fields like ``type`` |
| 120 | with a Literal default without hitting Python's "non-default argument |
| 121 | follows default argument" rule. All call sites already pass everything |
| 122 | by name (refactor plan WI-1.1 specifies keyword construction). |
| 123 | """ |
| 124 | |
| 125 | id: str |
| 126 | type: TaskType |
| 127 | status: TaskStatus |
| 128 | description: str |
| 129 | start_time: float |
| 130 | output_file: str |
| 131 | output_offset: int = 0 |
| 132 | notified: bool = False |
| 133 | tool_use_id: str | None = None |
| 134 | end_time: float | None = None |
| 135 | total_paused_seconds: float = 0.0 |
| 136 | # Per-type extension fields land in subclasses (LocalShellTaskState, |
| 137 | # LocalAgentTaskState, InProcessTeammateTaskState). |
| 138 | |
| 139 | |
| 140 | def create_task_state_base( |
no outgoing calls