"""A work item's place in the loop (L1), kept in its row in the state store. The row's ``position`` is the item's state; what the loop needs besides (the thread its conversation lives in, the revision of what is put up for agreement, what it is waiting for) is in ``data["loop"]``. """ from dataclasses import asdict, dataclass from typing import Any from nisse_dev.state import StateStore, WorkItem READY = "ready" RUNNING = "running" # a driver run is under way; on boot it means interrupted WAITING = "waiting" CLOSED = "closed" # What a waiting item waits for. GO_AHEAD = "go-ahead" # a go on the restatement up (L3, D1) ANSWER = "answer" # an answer to a question MERGE = "merge" # the PR's review and merge (D4, D5) @dataclass(frozen=True) class Loop: thread: str = "" # the root of the item's Matrix thread (L5) issue: int = 0 # its record issue (D1) wait: str = "" # GO_AHEAD / ANSWER, when waiting rev: int = 0 # the latest proposal put up (L3) started: bool = False # scope agreed: a go-ahead was given (D1) note: str = "" # what a waiting item said it is waiting on prepared: bool = False # its fresh workspace was made (D3) milestone: int = 0 # the current milestone (D4) branch: str = "" # the current milestone's branch, while one is open pr: int = 0 # the current milestone's PR, once published pr_url: str = "" comments: int = 0 # the last PR conversation comment taken (L8) notes: tuple[str, ...] = () # review notes taken (#69) fixes: int = 0 # review fixes pushed, for follow-up branch names def to_data(self) -> dict[str, Any]: return asdict(self) def loop_of(item: WorkItem) -> Loop: data = dict(item.data.get("loop", {})) data["notes"] = tuple(data.get("notes", ())) return Loop(**data) def save( store: StateStore, item_id: str, state: str, loop: Loop, *, cause: str ) -> None: item = store.work_item(item_id) assert item is not None store.update_work_item( item_id, position=state, data={**item.data, "loop": loop.to_data()}, cause=cause, ) def item_for_thread(store: StateStore, thread: str) -> WorkItem | None: for item in store.work_items("open"): if loop_of(item).thread == thread: return item return None def item_for_issue(store: StateStore, issue: int) -> WorkItem | None: """Any item, open or closed, recorded by this issue: intake never takes an issue twice (D1).""" for item in store.work_items(): if loop_of(item).issue == issue: return item return None