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.
97 lines
3.5 KiB
Python
97 lines
3.5 KiB
Python
from artemis.runtime.task_progress import progress_snapshot
|
|
|
|
|
|
def test_queued_time_is_not_execution_time_even_with_legacy_started_at():
|
|
value = progress_snapshot(job={"status": "queued", "created_at": 10, "started_at": 10}, now=50)
|
|
assert value["phase"] == "queued"
|
|
assert value["durations"]["queued"] == 40
|
|
assert value["durations"]["execution"] is None
|
|
|
|
|
|
def test_progress_splits_wait_pause_review_and_export_without_double_counting():
|
|
value = progress_snapshot(
|
|
job={
|
|
"status": "completed",
|
|
"created_at": 10,
|
|
"worker_started_at": 20,
|
|
"ended_at": 120,
|
|
"finalized_at": 125,
|
|
},
|
|
control={
|
|
"status": "running",
|
|
"timing": {
|
|
"started_at": 20,
|
|
"state_started_at": 80,
|
|
"seconds": {"queued": 10, "task_paused": 20, "resuming": 10, "running": 20},
|
|
},
|
|
},
|
|
reviews=[{"started_at": 90, "ended_at": 110}, {"started_at": 100, "ended_at": 115}],
|
|
now=500,
|
|
)
|
|
assert value["phase"] == "finished"
|
|
assert value["durations"] == {
|
|
"total": 115,
|
|
"queued": 10,
|
|
"resource_wait": 20,
|
|
"paused": 20,
|
|
"final_review": 25,
|
|
"execution": 35,
|
|
"report_export": 5,
|
|
}
|
|
|
|
|
|
def test_active_review_has_its_own_phase_and_terminal_review_is_not_still_active():
|
|
review = {"started_at": 30, "status": "running", "updated_at": 35}
|
|
live = progress_snapshot(job={"status": "running"}, reviews=[review], now=40)
|
|
assert live["phase"] == "final_review"
|
|
assert live["durations"]["final_review"] == 10
|
|
stopped = progress_snapshot(
|
|
job={"status": "cancelled", "ended_at": 45}, reviews=[review], now=500
|
|
)
|
|
assert stopped["phase"] == "finished"
|
|
assert stopped["durations"]["final_review"] == 5
|
|
assert not stopped["review_timing_complete"]
|
|
|
|
|
|
def test_legacy_missing_intervals_are_unknown_rather_than_zero_or_model_speed():
|
|
value = progress_snapshot(
|
|
session={"status": "completed", "start_time": 20, "end_time": 100}, now=500
|
|
)
|
|
assert value["durations"]["queued"] is None
|
|
assert value["durations"]["execution"] is None
|
|
assert value["durations"]["paused"] is None
|
|
assert value["durations"]["total"] is None
|
|
assert value["observed_seconds"] == 80
|
|
|
|
|
|
def test_waiting_for_resource_and_pause_are_not_running():
|
|
for status, phase in (
|
|
("queued", "waiting_resources"),
|
|
("resuming", "waiting_resources"),
|
|
("task_paused", "paused"),
|
|
):
|
|
value = progress_snapshot(
|
|
job={"status": "running", "worker_started_at": 10}, control={"status": status}, now=50
|
|
)
|
|
assert value["phase"] == phase
|
|
|
|
|
|
def test_terminal_without_end_timestamp_does_not_keep_increasing_or_guess_duration():
|
|
job = {"status": "completed", "created_at": 10, "worker_started_at": 20}
|
|
first = progress_snapshot(job=job, now=100)
|
|
assert first == progress_snapshot(job=job, now=500)
|
|
assert first["observed_at"] is None
|
|
assert all(first["durations"][key] is None for key in ("total", "execution", "report_export"))
|
|
|
|
|
|
def test_export_in_progress_keeps_total_current_without_extending_execution():
|
|
value = progress_snapshot(
|
|
job={"status": "finalizing", "created_at": 10, "worker_started_at": 100, "ended_at": 200},
|
|
now=230,
|
|
)
|
|
assert value["phase"] == "report_export"
|
|
assert value["observed_at"] == 230
|
|
assert value["durations"]["total"] == 220
|
|
assert value["durations"]["report_export"] == 30
|
|
assert value["worker_ended_at"] == 200
|