Initial commit

This commit is contained in:
LZH-YS1998
2026-07-01 17:56:31 +08:00
commit d78931979d
731 changed files with 311088 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
from __future__ import annotations
import unittest
from unittest.mock import AsyncMock
from opc.core.models import ExecutionCheckpoint, Task, TaskStatus
from opc.plugins.cli_board.services.actions import BoardActions
class _StubStore:
def __init__(self) -> None:
self.tasks: dict[str, Task] = {}
self.checkpoints: list[ExecutionCheckpoint] = []
self.resolved: list[tuple[str, str]] = []
async def save_task(self, task: Task) -> None:
self.tasks[task.id] = task
async def get_task(self, task_id: str) -> Task | None:
return self.tasks.get(task_id)
async def get_tasks(self, **_kw):
return list(self.tasks.values())
async def get_pending_checkpoints(self, **_kw):
return [checkpoint for checkpoint in self.checkpoints if checkpoint.status == "pending"]
async def resolve_execution_checkpoint(self, checkpoint_id: str, status: str = "resolved") -> None:
self.resolved.append((checkpoint_id, status))
for checkpoint in self.checkpoints:
if checkpoint.checkpoint_id == checkpoint_id:
checkpoint.status = status
class _StubMemory:
def __init__(self) -> None:
self.ensure_session = AsyncMock()
class _StubEngine:
def __init__(self) -> None:
self.store = _StubStore()
self.memory = _StubMemory()
self.process_message = AsyncMock(return_value="ok")
class _StubFacade:
def __init__(self, engine: _StubEngine) -> None:
self.project_id = "demo"
self._engine = engine
async def ensure_ready(self):
return self._engine
class BoardActionsTests(unittest.IsolatedAsyncioTestCase):
async def test_create_task_creates_session_backed_placeholder(self) -> None:
engine = _StubEngine()
actions = BoardActions(_StubFacade(engine), project_id="demo")
task = await actions.create_task(title="Draft feature", description="Initial plan")
self.assertIn(task.id, engine.store.tasks)
engine.memory.ensure_session.assert_awaited()
self.assertEqual(engine.store.tasks[task.id].title, "Draft feature")
self.assertEqual(engine.store.tasks[task.id].metadata["source"], "cli_board")
async def test_send_session_message_routes_through_origin_task(self) -> None:
engine = _StubEngine()
task = Task(
id="task-1",
title="Feature task",
description="Implement the feature",
status=TaskStatus.PENDING,
session_id="session-1",
project_id="demo",
)
await engine.store.save_task(task)
actions = BoardActions(_StubFacade(engine), project_id="demo")
response = await actions.send_session_message("task-1", "please continue")
self.assertEqual(response, "ok")
engine.process_message.assert_awaited_once()
kwargs = engine.process_message.await_args.kwargs
self.assertEqual(kwargs["session_id"], "session-1")
self.assertEqual(kwargs["origin_task_id"], "task-1")
self.assertEqual(engine.store.tasks["task-1"].status, TaskStatus.IDLE)
async def test_cancel_task_marks_related_tasks_and_checkpoints_cancelled(self) -> None:
engine = _StubEngine()
root = Task(
id="root",
title="Root task",
description="Run runtime",
status=TaskStatus.RUNNING,
session_id="session-root",
project_id="demo",
)
linked = Task(
id="child",
title="Child task",
description="Background child",
status=TaskStatus.RUNNING,
session_id="session-child",
project_id="demo",
metadata={"origin_task_id": "root"},
)
await engine.store.save_task(root)
await engine.store.save_task(linked)
engine.store.checkpoints.append(
ExecutionCheckpoint(
checkpoint_id="cp-root",
project_id="demo",
session_id="session-root",
task_id="root",
)
)
actions = BoardActions(_StubFacade(engine), project_id="demo")
await actions.cancel_task("root")
self.assertEqual(engine.store.tasks["root"].status, TaskStatus.CANCELLED)
self.assertEqual(engine.store.tasks["child"].status, TaskStatus.CANCELLED)
self.assertEqual(engine.store.resolved, [("cp-root", "cancelled")])
+127
View File
@@ -0,0 +1,127 @@
from __future__ import annotations
import unittest
from opc.plugins.cli_board.state.models import BoardSnapshot, BoardTaskView, PendingCheckpointView
from opc.plugins.cli_board.state.store import BoardStateStore
def _task(task_id: str, title: str, column_id: str, *, status: str | None = None) -> BoardTaskView:
return BoardTaskView(
task_id=task_id,
title=title,
description=f"{title} description",
status=status or ("pending" if column_id == "todo" else "running"),
column_id=column_id,
priority="medium",
created_at=1.0,
updated_at=1.0,
)
class BoardStateStoreTests(unittest.TestCase):
def setUp(self) -> None:
self.store = BoardStateStore()
self.store.replace_snapshot(
BoardSnapshot(
project_id="demo",
tasks=[
_task("todo-1", "Todo 1", "todo"),
_task("todo-2", "Todo 2", "todo"),
_task("run-1", "Run 1", "in-progress"),
_task("done-1", "Done 1", "done", status="done"),
],
)
)
def test_initial_selection_uses_first_visible_task(self) -> None:
selected = self.store.selected_task()
self.assertIsNotNone(selected)
self.assertEqual(selected.task_id, "todo-1")
def test_move_selection_crosses_columns_and_rows(self) -> None:
self.store.move_selection(row_delta=1)
self.assertEqual(self.store.selected_task().task_id, "todo-2")
self.store.move_selection(column_delta=1)
self.assertEqual(self.store.selected_task().task_id, "run-1")
self.store.move_selection(column_delta=1)
self.assertEqual(self.store.selected_task().task_id, "done-1")
def test_toggle_done_hides_done_column_tasks(self) -> None:
showing = self.store.toggle_show_done()
self.assertFalse(showing)
counts = self.store.board_counts()
self.assertEqual(counts["done"], 0)
def test_search_filter_updates_selection(self) -> None:
self.store.set_search_query("run")
selected = self.store.selected_task()
self.assertIsNotNone(selected)
self.assertEqual(selected.task_id, "run-1")
def test_runtime_updates_and_progress_are_tracked(self) -> None:
self.store.apply_runtime_update(
"run-1",
status="tool_active",
current_tool="shell_exec",
iteration=2,
tool_elapsed_ms=420,
last_tool_summary="pytest -q completed",
context_tokens=1200,
context_window=4000,
context_remaining_pct=70,
turn_cost_usd=0.0123,
session_cost_usd=0.0456,
pending_permission_count=1,
drain_mode="smooth",
)
self.store.append_progress("run-1", "[Tool: shell_exec] pytest -q")
runtime = self.store.runtime_for("run-1")
self.assertIsNotNone(runtime)
self.assertEqual(runtime.status, "tool_active")
self.assertEqual(runtime.current_tool, "shell_exec")
self.assertEqual(runtime.iteration, 2)
self.assertEqual(runtime.tool_elapsed_ms, 420)
self.assertEqual(runtime.last_tool_summary, "pytest -q completed")
self.assertEqual(runtime.context_remaining_pct, 70)
self.assertEqual(runtime.turn_cost_usd, 0.0123)
self.assertEqual(runtime.pending_permission_count, 1)
self.assertEqual(runtime.drain_mode, "smooth")
self.assertEqual(len(runtime.progress_entries), 1)
def test_metrics_and_alerts_include_snapshot_and_runtime_state(self) -> None:
self.store.snapshot.hidden_task_count = 2
self.store.snapshot.pending_checkpoint_count = 1
self.store.snapshot.tasks[2].pending_checkpoint = PendingCheckpointView(
checkpoint_id="cp-1",
checkpoint_type="task_user_input",
status="pending",
session_id="session-run-1",
task_id="run-1",
summary="Need approval",
prompt="Approve this step",
)
self.store.apply_runtime_update("run-1", status="tool_active", current_tool="shell_exec")
metrics = self.store.metrics()
alerts = self.store.alerts()
self.assertEqual(metrics.total_tasks, 6)
self.assertEqual(metrics.pending_checkpoint_count, 1)
self.assertEqual(metrics.running_count, 1)
self.assertGreaterEqual(metrics.alert_count, 1)
self.assertTrue(any(alert.task_id == "run-1" for alert in alerts))
def test_session_navigation_and_view_state_controls(self) -> None:
self.store.select_task("run-1")
self.store.set_pane_focus("session-rail")
self.store.move_session_selection(1)
self.assertEqual(self.store.selected_task().task_id, "todo-1")
self.store.set_view_mode("list")
self.assertEqual(self.store.view_mode, "list")
self.assertEqual(self.store.toggle_density(), "comfortable")
self.assertEqual(self.store.cycle_context_tab(1), "session")
+365
View File
@@ -0,0 +1,365 @@
from __future__ import annotations
import unittest
from datetime import datetime
from opc.core.models import (
DelegationRun,
DelegationWorkItem,
ExecutionCheckpoint,
Phase,
SessionMessageRecord,
SessionPartRecord,
Task,
TaskStatus,
)
from opc.plugins.cli_board.services.board_repository import BoardRepository
from opc.layer2_organization.work_item_links import set_linked_work_item_id
class _StubStore:
def __init__(
self,
tasks,
checkpoints,
transcripts,
*,
delegation_runs=None,
work_items_by_run=None,
) -> None:
self._tasks = tasks
self._checkpoints = checkpoints
self._transcripts = transcripts
self._delegation_runs = list(delegation_runs or [])
self._work_items_by_run = dict(work_items_by_run or {})
async def get_tasks(self, **_kw):
return list(self._tasks)
async def get_pending_checkpoints(self, **_kw):
return list(self._checkpoints)
async def get_session_transcript(self, session_id):
return list(self._transcripts.get(session_id, []))
# The company-mode branch in BoardRepository feature-detects these methods.
# Only present them when the test wires a delegation run, so the standard
# tests above keep exercising the Task path.
async def list_open_delegation_runs(self, *, project_id=None):
return list(self._delegation_runs)
async def list_delegation_work_items(self, run_id):
return list(self._work_items_by_run.get(run_id, []))
class _StubFacade:
def __init__(self, store) -> None:
self.project_id = "demo"
self._engine = type("Engine", (), {"store": store})()
async def ensure_ready(self):
return self._engine
class BoardRepositoryTests(unittest.IsolatedAsyncioTestCase):
async def test_snapshot_hides_internal_origin_tasks(self) -> None:
visible = Task(
id="visible-1",
title="Visible task",
description="Board-visible task",
status=TaskStatus.PENDING,
session_id="session-visible",
project_id="demo",
)
hidden = Task(
id="hidden-1",
title="Internal task",
description="Background execution",
status=TaskStatus.RUNNING,
session_id="session-hidden",
project_id="demo",
metadata={"origin_task_id": "visible-1"},
)
checkpoint = ExecutionCheckpoint(
checkpoint_id="cp-1",
project_id="demo",
session_id="session-visible",
checkpoint_type="company_delivery_feedback",
status="pending",
payload={"prompt": "Approve delivery?"},
)
repo = BoardRepository(_StubFacade(_StubStore([visible, hidden], [checkpoint], {})), project_id="demo")
snapshot = await repo.load_snapshot()
self.assertEqual(len(snapshot.tasks), 1)
self.assertEqual(snapshot.hidden_task_count, 1)
self.assertEqual(snapshot.tasks[0].task_id, "visible-1")
self.assertIsNotNone(snapshot.tasks[0].pending_checkpoint)
self.assertEqual(len(snapshot.session_summaries), 1)
self.assertEqual(snapshot.metrics.visible_tasks, 1)
self.assertEqual(snapshot.metrics.pending_checkpoint_count, 1)
self.assertTrue(any(alert.task_id == "visible-1" for alert in snapshot.alerts))
async def test_load_task_detail_includes_transcript_and_linked_executions(self) -> None:
task = Task(
id="task-1",
title="Primary task",
description="Do the work",
status=TaskStatus.RUNNING,
session_id="session-1",
project_id="demo",
metadata={"progress_log": ["planning", "running"]},
)
linked = Task(
id="task-2",
title="Linked task",
description="Hidden execution",
status=TaskStatus.RUNNING,
session_id="session-2",
project_id="demo",
metadata={"origin_task_id": "task-1"},
)
transcript = {
"session-1": [
{
"message": SessionMessageRecord(
message_id="m1",
session_id="session-1",
role="user",
created_at=datetime.now(),
),
"parts": [
SessionPartRecord(
message_id="m1",
session_id="session-1",
part_type="text",
payload={"text": "Please implement the feature"},
)
],
},
{
"message": SessionMessageRecord(
message_id="m2",
session_id="session-1",
role="assistant",
created_at=datetime.now(),
),
"parts": [
SessionPartRecord(
message_id="m2",
session_id="session-1",
part_type="text",
payload={"text": "Working on it"},
)
],
},
]
}
repo = BoardRepository(_StubFacade(_StubStore([task, linked], [], transcript)), project_id="demo")
detail = await repo.load_task_detail("task-1")
self.assertIsNotNone(detail)
assert detail is not None
self.assertEqual(detail.task.task_id, "task-1")
self.assertEqual(len(detail.transcript), 2)
self.assertEqual(len(detail.linked_executions), 1)
self.assertEqual(detail.linked_executions[0].task_id, "task-2")
self.assertEqual(detail.progress_entries, ["planning", "running"])
self.assertEqual(detail.task.display_id, "OPC-1")
async def test_company_mode_snapshot_uses_work_items_as_cards(self) -> None:
"""In company mode, kanban cards come from DelegationWorkItem (not Task).
Asserts: card task_id == work_item_id; canonical four-state column
mapping (todo / in-progress / in-review / done); session_id remains
only as an audit reference; column_order includes "in-review".
"""
run = DelegationRun(
run_id="run-1",
project_id="demo",
company_profile="corporate",
lifecycle_status="active",
)
# Synthetic root work item — must be hidden (no parent_work_item_id).
root_item = DelegationWorkItem(
work_item_id="wi-root",
run_id="run-1",
title="Root",
summary="root",
phase=Phase.READY,
)
wi_todo = DelegationWorkItem(
work_item_id="wi-todo",
run_id="run-1",
parent_work_item_id="wi-root",
role_id="researcher",
title="Investigate API",
summary="Find current rate-limit behavior.",
phase=Phase.READY,
kind="execute",
metadata={"dependency_work_item_ids": []},
)
wi_running = DelegationWorkItem(
work_item_id="wi-running",
run_id="run-1",
parent_work_item_id="wi-root",
role_id="engineer",
title="Implement fix",
summary="Patch the throttle.",
phase=Phase.RUNNING,
kind="execute",
claimed_by_role_runtime_session_id="role-rt-1",
metadata={"activation_state": "active"},
)
wi_review = DelegationWorkItem(
work_item_id="wi-review",
run_id="run-1",
parent_work_item_id="wi-root",
role_id="qa",
title="Verify deliverable",
summary="Check the test plan.",
phase=Phase.AWAITING_MANAGER_REVIEW,
kind="review",
metadata={"review_state": "pending_manager"},
)
wi_done = DelegationWorkItem(
work_item_id="wi-done",
run_id="run-1",
parent_work_item_id="wi-root",
role_id="engineer",
title="Earlier patch",
summary="Already shipped.",
phase=Phase.APPROVED,
kind="execute",
)
# A runtime Task linked to wi-running for audit/transcript only.
linked_task = Task(
id="task-running",
title="Implement fix",
description="runtime execution",
status=TaskStatus.RUNNING,
session_id="session-running",
project_id="demo",
metadata={},
)
set_linked_work_item_id(linked_task, "wi-running")
store = _StubStore(
tasks=[linked_task],
checkpoints=[],
transcripts={},
delegation_runs=[run],
work_items_by_run={"run-1": [root_item, wi_todo, wi_running, wi_review, wi_done]},
)
repo = BoardRepository(_StubFacade(store), project_id="demo")
snapshot = await repo.load_snapshot()
self.assertEqual(snapshot.mode, "company")
self.assertEqual(snapshot.column_order, ["todo", "in-progress", "in-review", "done"])
# Root item is filtered; the four leaf work items become cards.
self.assertEqual([t.task_id for t in snapshot.tasks], ["wi-todo", "wi-running", "wi-review", "wi-done"])
# Card identity is the work_item_id, not Task.id.
self.assertEqual(snapshot.tasks[0].work_item_id, "wi-todo")
# Four-state canonical column mapping.
column_by_id = {t.task_id: t.column_id for t in snapshot.tasks}
self.assertEqual(column_by_id["wi-todo"], "todo")
self.assertEqual(column_by_id["wi-running"], "in-progress")
self.assertEqual(column_by_id["wi-review"], "in-review")
self.assertEqual(column_by_id["wi-done"], "done")
# session_id is an audit reference only (populated for the linked card).
running_card = next(t for t in snapshot.tasks if t.task_id == "wi-running")
self.assertEqual(running_card.session_id, "session-running")
self.assertEqual(running_card.runtime_task_id, "task-running")
self.assertEqual(running_card.execution_turn_id, "task-running")
todo_card = next(t for t in snapshot.tasks if t.task_id == "wi-todo")
self.assertIsNone(todo_card.session_id)
self.assertIsNone(todo_card.runtime_task_id)
self.assertIsNone(todo_card.execution_turn_id)
# Metrics surface the new in_review_count.
self.assertEqual(snapshot.metrics.in_review_count, 1)
self.assertEqual(snapshot.metrics.in_progress_count, 1)
self.assertEqual(snapshot.metrics.todo_count, 1)
self.assertEqual(snapshot.metrics.done_count, 1)
# Hidden count = synthetic root item.
self.assertEqual(snapshot.hidden_task_count, 1)
async def test_company_mode_load_task_detail_resolves_work_item_id(self) -> None:
run = DelegationRun(run_id="run-2", project_id="demo", lifecycle_status="active")
wi = DelegationWorkItem(
work_item_id="wi-x",
run_id="run-2",
parent_work_item_id="wi-root",
role_id="engineer",
title="Detail target",
summary="check detail path",
phase=Phase.RUNNING,
metadata={"handoff_context": "from upstream"},
)
linked_task = Task(
id="task-x",
title="runtime",
description="",
status=TaskStatus.RUNNING,
session_id="session-x",
project_id="demo",
metadata={"progress_log": ["start"]},
)
set_linked_work_item_id(linked_task, "wi-x")
transcript = {
"session-x": [
{
"message": SessionMessageRecord(
message_id="m1", session_id="session-x", role="assistant", created_at=datetime.now()
),
"parts": [SessionPartRecord(message_id="m1", session_id="session-x", part_type="text", payload={"text": "ok"})],
}
]
}
store = _StubStore(
tasks=[linked_task],
checkpoints=[],
transcripts=transcript,
delegation_runs=[run],
work_items_by_run={"run-2": [wi]},
)
repo = BoardRepository(_StubFacade(store), project_id="demo")
detail = await repo.load_task_detail("wi-x")
self.assertIsNotNone(detail)
assert detail is not None
self.assertEqual(detail.task.task_id, "wi-x")
self.assertEqual(detail.task.work_item_id, "wi-x")
self.assertEqual(detail.task.runtime_task_id, "task-x")
self.assertEqual(detail.task.execution_turn_id, "task-x")
self.assertEqual(detail.context_preview, "from upstream")
self.assertEqual(len(detail.transcript), 1)
self.assertEqual(detail.progress_entries, ["start"])
async def test_snapshot_preserves_adaptive_metadata_for_widgets(self) -> None:
task = Task(
id="task-adaptive",
title="Adaptive task",
description="Blocked on signals",
status=TaskStatus.BLOCKED,
session_id="session-adaptive",
project_id="demo",
metadata={
"adaptive": {
"normalized_state": "waiting_for_gate",
"blocked_reason": "Waiting for required signals: implementation_ready",
"work_item_profile": {"gate_owner_role_id": "cto"},
"signals": [
{"name": "implementation_ready", "required": True, "satisfied": False},
],
"confidence": 0.72,
}
},
)
repo = BoardRepository(_StubFacade(_StubStore([task], [], {})), project_id="demo")
snapshot = await repo.load_snapshot()
self.assertEqual(snapshot.tasks[0].metadata["adaptive"]["normalized_state"], "waiting_for_gate")
self.assertEqual(snapshot.tasks[0].metadata["adaptive"]["work_item_profile"]["gate_owner_role_id"], "cto")
+108
View File
@@ -0,0 +1,108 @@
from __future__ import annotations
import unittest
from opc.plugins.cli_board.state.models import BoardSnapshot, BoardTaskView, TaskDetailView
try: # pragma: no cover - optional dependency
from opc.plugins.cli_board.tui.app import CliBoardApp
from opc.plugins.cli_board.tui.screens.help import HelpScreen
from opc.plugins.cli_board.tui.screens.palette import CommandPaletteScreen
from opc.plugins.cli_board.tui.screens.prompt import PromptScreen
except ImportError: # pragma: no cover - optional dependency
CliBoardApp = None
HelpScreen = None
CommandPaletteScreen = None
PromptScreen = None
class _StubRepository:
def __init__(self) -> None:
self.snapshot = BoardSnapshot(
project_id="demo",
tasks=[
BoardTaskView(
task_id="todo-1",
title="Todo task",
description="Pending task",
status="pending",
column_id="todo",
priority="medium",
created_at=1.0,
updated_at=1.0,
),
BoardTaskView(
task_id="run-1",
title="Running task",
description="In progress",
status="running",
column_id="in-progress",
priority="high",
created_at=2.0,
updated_at=2.0,
),
BoardTaskView(
task_id="done-1",
title="Done task",
description="Completed",
status="done",
column_id="done",
priority="low",
created_at=3.0,
updated_at=3.0,
),
],
)
async def load_snapshot(self) -> BoardSnapshot:
return self.snapshot
async def load_task_detail(self, task_id: str):
task = next((task for task in self.snapshot.tasks if task.task_id == task_id), None)
return TaskDetailView(task=task) if task else None
@unittest.skipIf(CliBoardApp is None, "textual is not installed")
class CliBoardAppPilotTests(unittest.IsolatedAsyncioTestCase):
async def test_keyboard_navigation_view_switching_and_modals(self) -> None:
app = CliBoardApp(project_id="demo", refresh_interval=60.0, bootstrap_services=False)
app.repository = _StubRepository()
async with app.run_test() as pilot:
app.state.replace_snapshot(await app.repository.load_snapshot())
await app._load_selected_detail()
app.status_widget.set_message("Harness ready.")
self.assertEqual(app.state.selected_task().task_id, "todo-1")
await pilot.press("right")
self.assertEqual(app.state.selected_task().task_id, "run-1")
await pilot.press("2")
self.assertEqual(app.state.view_mode, "list")
await pilot.press("3")
self.assertEqual(app.state.view_mode, "focus")
app.action_focus_next_pane()
await pilot.pause()
self.assertEqual(app.state.pane_focus, "context")
await pilot.press("right")
self.assertEqual(app.state.context_tab, "session")
await pilot.press("f")
self.assertFalse(app.state.show_done)
await pilot.press("n")
self.assertIsInstance(app.screen, PromptScreen)
await pilot.press("escape")
app.action_open_palette()
await pilot.pause()
self.assertIsInstance(app.screen, CommandPaletteScreen)
await pilot.press("escape")
await pilot.press("?")
self.assertIsInstance(app.screen, HelpScreen)
await pilot.press("escape")