feat: prepare 2.2.0 with UI and execution fixes
Add dark theme, richer Markdown and readable plugin results. Improve Android input evidence, response integrity and diagnostics. Unify lifecycle, guidance receipts and evidence sources across clients. Keep direct action dispatch without an added AI quota approval layer. Align version metadata at 2.2.0 and bundle Helper 1.2.2. Validation: 3063 backend tests before the version bump; 44 after. Frontend: 317 tests and production build passed.
This commit is contained in:
1 parent
83bcfd54d5
commit
fac4ccb760
146 files changed
+5689
-2033
No files matched your search
@@ -14,6 +14,47 @@ import pytest
|
||||
import artemis.runtime.task_control as task_control
|
||||
|
||||
|
||||
def test_transition_timing_keeps_repeated_states_and_separates_pause_and_resource_wait(
|
||||
tmp_path, monkeypatch
|
||||
):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
clock = [10]
|
||||
monkeypatch.setattr(
|
||||
task_control,
|
||||
"time",
|
||||
SimpleNamespace(**{**vars(task_control.time), "time": lambda: clock[0]}),
|
||||
)
|
||||
for at, status in (
|
||||
(10, "queued"),
|
||||
(20, "running"),
|
||||
(25, "running"),
|
||||
(30, "task_paused"),
|
||||
(40, "resuming"),
|
||||
(50, "running"),
|
||||
):
|
||||
clock[0] = at
|
||||
task_control.write_control_state("timed-task", status)
|
||||
assert task_control.read_state("timed-task")["timing"] == {
|
||||
"started_at": 10,
|
||||
"state_started_at": 50,
|
||||
"seconds": {"queued": 10, "running": 10, "task_paused": 10, "resuming": 10},
|
||||
}
|
||||
|
||||
|
||||
def test_non_object_control_state_and_invalid_timing_can_be_replaced(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
path = task_control.control_dir("broken-state") / "task_control_state.json"
|
||||
path.parent.mkdir(parents=True)
|
||||
path.write_text("[]", encoding="utf-8")
|
||||
assert task_control.read_state("broken-state") == {}
|
||||
task_control.write_control_state("broken-state", "running")
|
||||
state = task_control.read_state("broken-state")
|
||||
state["timing"] = "invalid"
|
||||
task_control._write_atomic(path, state)
|
||||
task_control.write_control_state("broken-state", "task_paused")
|
||||
assert task_control.read_state("broken-state")["timing"]["seconds"] == {}
|
||||
|
||||
|
||||
def _windows_access_error(code: int) -> PermissionError:
|
||||
error = PermissionError(errno.EACCES, "state file is in use")
|
||||
error.winerror = code
|
||||
@@ -423,6 +464,28 @@ def test_guidance_history_distinguishes_submission_from_runner_consumption(tmp_p
|
||||
assert all(item["status"] == "consumed" and item["consumed_at"] for item in history)
|
||||
|
||||
|
||||
def test_terminal_guidance_reports_no_consumption_and_keeps_original_receipt(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
receipt = task_control.add_instruction("task-123", "检查新入口", instruction_id="guidance")
|
||||
history = task_control.list_instructions("task-123", task_status="cancelled")
|
||||
assert history[0]["status"] == "unapplied"
|
||||
assert history[0]["accepted_at"] == receipt["timestamp"]
|
||||
assert "consumed_at" not in history[0]
|
||||
assert task_control.list_instructions("task-123")[0]["status"] == "pending"
|
||||
|
||||
|
||||
def test_claimed_guidance_is_visible_and_not_falsely_reported_as_consumed(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(task_control, "TRACES_PATH", tmp_path)
|
||||
task_control.add_instruction("task-123", "检查新入口", instruction_id="guidance")
|
||||
directory = task_control.control_dir("task-123") / "instructions"
|
||||
(directory / "guidance.json").rename(directory / "guidance.reading")
|
||||
assert task_control.list_instructions("task-123")[0]["status"] == "reading"
|
||||
assert (
|
||||
task_control.list_instructions("task-123", task_status="completed")[0]["status"]
|
||||
== "unconfirmed"
|
||||
)
|
||||
|
||||
|
||||
def test_guidance_history_endpoint_returns_pending_and_consumed(tmp_path, monkeypatch):
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
Reference in new issue
Block a user