gabriel / muse public
test_harmony_phase4.py python
692 lines 25.6 KB
Raw
sha256:b636f72dcba9e190afb980bece906fa5b717fbde014b76ef023df8cb96e01eb9 docs: expand cache plan with all seven testing tiers and do… Sonnet 4.6 133 days ago
1 """Tests for Phase 4 — Escalation Records.
2
3 New additions to ``muse/core/harmony.py``:
4
5 ``EscalationStatus`` — open string constants: OPEN, RESOLVED
6 ``AuditEventType.ESCALATION_RESOLVED``
7 ``EscalationRecord`` — frozen dataclass
8 ``compute_escalation_id`` — deterministic hex64 from (pattern_id, reason)
9 ``escalations_dir`` — ``.muse/harmony/escalations/``
10 ``record_escalation`` — atomic write; idempotent
11 ``load_escalation`` — read by ID
12 ``list_escalations`` — filtered list (status filter)
13 ``resolve_escalation`` — transition open → resolved, atomic
14
15 Coverage tiers
16 --------------
17 I Unit — EscalationStatus constants, EscalationRecord fields,
18 compute_escalation_id determinism + collision resistance
19 II Integration — record / load / list / resolve_escalation CRUD
20 III End-to-end — escalate → list → resolve → audit trail
21 IV Stress — 200-escalation list, concurrent record (same ID idempotency)
22 V Data integrity — JSON round-trip, all fields always present, frozen
23 VI Security — ID validation, path traversal rejected, size cap respected
24 VII Performance — all ops <50 ms
25 """
26 from __future__ import annotations
27
28 import concurrent.futures
29 import dataclasses
30 import datetime
31 import json
32 import pathlib
33 import time
34
35 import pytest
36
37 import muse.core.harmony as h
38 from muse.core._types import fake_id, long_id, split_id
39 from muse.core.harmony import (
40 AgentProvenance,
41 AuditEventType,
42 EscalationRecord,
43 EscalationStatus,
44 append_audit,
45 blob_fingerprint,
46 compute_escalation_id,
47 compute_pattern_id,
48 compute_resolution_id,
49 escalation_path,
50 escalations_dir,
51 list_audit,
52 list_escalations,
53 load_escalation,
54 record_escalation,
55 resolve_escalation,
56 save_resolution,
57 Resolution,
58 )
59
60
61 # ---------------------------------------------------------------------------
62 # Shared helpers
63 # ---------------------------------------------------------------------------
64
65
66 def _utc_now() -> datetime.datetime:
67 return datetime.datetime.now(datetime.timezone.utc)
68
69
70 @pytest.fixture()
71 def repo(tmp_path: pathlib.Path) -> pathlib.Path:
72 (tmp_path / ".muse").mkdir()
73 return tmp_path
74
75
76 def _make_record(
77 pattern_id: str | None = None,
78 reason: str = "No match found",
79 agent_id: str | None = None,
80 ) -> EscalationRecord:
81 pid = pattern_id or fake_id("pat1")
82 eid = compute_escalation_id(pid, reason)
83 return EscalationRecord(
84 escalation_id=eid,
85 pattern_id=pid,
86 reason=reason,
87 escalated_at=_utc_now(),
88 escalated_by=(
89 AgentProvenance.agent(agent_id) if agent_id else AgentProvenance.human()
90 ),
91 )
92
93
94 # ===========================================================================
95 # Tier I — Unit
96 # ===========================================================================
97
98
99 class TestEscalationStatusConstants:
100 """I: EscalationStatus is an open string-constant namespace."""
101
102 def test_open_value(self) -> None:
103 assert EscalationStatus.OPEN == "open"
104
105 def test_resolved_value(self) -> None:
106 assert EscalationStatus.RESOLVED == "resolved"
107
108 def test_constants_are_strings(self) -> None:
109 assert isinstance(EscalationStatus.OPEN, str)
110 assert isinstance(EscalationStatus.RESOLVED, str)
111
112
113 class TestAuditEventTypeEscalationResolved:
114 """I: AuditEventType.ESCALATION_RESOLVED constant exists."""
115
116 def test_escalation_resolved_constant(self) -> None:
117 assert AuditEventType.ESCALATION_RESOLVED == "escalation_resolved"
118
119 def test_escalation_recorded_still_present(self) -> None:
120 assert AuditEventType.ESCALATION_RECORDED == "escalation_recorded"
121
122
123 class TestEscalationRecordFields:
124 """I: EscalationRecord dataclass shape and defaults."""
125
126 def test_required_fields_present(self) -> None:
127 pid = fake_id("p")
128 eid = compute_escalation_id(pid, "reason")
129 r = EscalationRecord(
130 escalation_id=eid,
131 pattern_id=pid,
132 reason="test reason",
133 escalated_at=_utc_now(),
134 escalated_by=AgentProvenance.human(),
135 )
136 assert r.escalation_id == eid
137 assert r.pattern_id == pid
138 assert r.reason == "test reason"
139 assert r.status == EscalationStatus.OPEN
140
141 def test_status_defaults_to_open(self) -> None:
142 r = _make_record()
143 assert r.status == EscalationStatus.OPEN
144
145 def test_optional_fields_default_none(self) -> None:
146 r = _make_record()
147 assert r.resolved_at is None
148 assert r.resolved_by is None
149 assert r.resolution_id is None
150
151 def test_frozen(self) -> None:
152 r = _make_record()
153 with pytest.raises((dataclasses.FrozenInstanceError, AttributeError)):
154 r.status = EscalationStatus.RESOLVED # type: ignore[misc]
155
156 def test_is_dataclass(self) -> None:
157 assert dataclasses.is_dataclass(EscalationRecord)
158
159
160 class TestComputeEscalationId:
161 """I: compute_escalation_id is deterministic and collision-resistant."""
162
163 def test_deterministic_same_inputs(self) -> None:
164 pid = fake_id("p")
165 eid1 = compute_escalation_id(pid, "reason")
166 eid2 = compute_escalation_id(pid, "reason")
167 assert eid1 == eid2
168
169 def test_different_pattern_ids_differ(self) -> None:
170 pid1 = fake_id("p1")
171 pid2 = fake_id("p2")
172 assert compute_escalation_id(pid1, "reason") != compute_escalation_id(pid2, "reason")
173
174 def test_different_reasons_differ(self) -> None:
175 pid = fake_id("p")
176 assert compute_escalation_id(pid, "reason A") != compute_escalation_id(pid, "reason B")
177
178 def test_returns_sha256_id(self) -> None:
179 eid = compute_escalation_id(fake_id("p"), "reason")
180 assert eid.startswith("sha256:")
181 assert len(eid) == 71
182 assert all(c in "0123456789abcdef" for c in split_id(eid)[1])
183
184
185 # ===========================================================================
186 # Tier II — Integration: CRUD
187 # ===========================================================================
188
189
190 class TestEscalationsDir:
191 """II: escalations_dir returns the correct path."""
192
193 def test_path_structure(self, repo: pathlib.Path) -> None:
194 d = escalations_dir(repo)
195 assert d == repo / ".muse" / "harmony" / "escalations"
196
197 def test_does_not_create_dir(self, repo: pathlib.Path) -> None:
198 d = escalations_dir(repo)
199 assert not d.exists()
200
201
202 class TestRecordEscalation:
203 """II: record_escalation writes a JSON file; idempotent."""
204
205 def test_creates_escalation_file(self, repo: pathlib.Path) -> None:
206 rec = _make_record()
207 record_escalation(repo, rec)
208 dest = escalation_path(repo, rec.escalation_id)
209 assert dest.exists()
210
211 def test_idempotent_second_write_no_error(self, repo: pathlib.Path) -> None:
212 rec = _make_record()
213 record_escalation(repo, rec)
214 record_escalation(repo, rec) # should not raise
215 dest = escalation_path(repo, rec.escalation_id)
216 assert dest.exists()
217
218 def test_idempotent_returns_false_on_second_write(self, repo: pathlib.Path) -> None:
219 rec = _make_record()
220 first = record_escalation(repo, rec)
221 second = record_escalation(repo, rec)
222 assert first is True
223 assert second is False
224
225 def test_json_contains_expected_keys(self, repo: pathlib.Path) -> None:
226 rec = _make_record()
227 record_escalation(repo, rec)
228 dest = escalation_path(repo, rec.escalation_id)
229 data = json.loads(dest.read_text())
230 for key in ("escalation_id", "pattern_id", "reason", "escalated_at",
231 "escalated_by", "status"):
232 assert key in data
233
234 def test_status_stored_as_open(self, repo: pathlib.Path) -> None:
235 rec = _make_record()
236 record_escalation(repo, rec)
237 dest = escalation_path(repo, rec.escalation_id)
238 data = json.loads(dest.read_text())
239 assert data["status"] == EscalationStatus.OPEN
240
241 def test_atomic_write_no_temp_files(self, repo: pathlib.Path) -> None:
242 rec = _make_record()
243 record_escalation(repo, rec)
244 esc_dir = escalations_dir(repo)
245 tmp_files = list(esc_dir.glob("*.tmp"))
246 assert tmp_files == []
247
248
249 class TestLoadEscalation:
250 """II: load_escalation retrieves a stored record."""
251
252 def test_returns_none_for_missing(self, repo: pathlib.Path) -> None:
253 eid = fake_id("missing")
254 assert load_escalation(repo, eid) is None
255
256 def test_round_trips_required_fields(self, repo: pathlib.Path) -> None:
257 rec = _make_record()
258 record_escalation(repo, rec)
259 loaded = load_escalation(repo, rec.escalation_id)
260 assert loaded is not None
261 assert loaded.escalation_id == rec.escalation_id
262 assert loaded.pattern_id == rec.pattern_id
263 assert loaded.reason == rec.reason
264 assert loaded.status == EscalationStatus.OPEN
265
266 def test_escalated_by_human_round_trips(self, repo: pathlib.Path) -> None:
267 rec = _make_record()
268 record_escalation(repo, rec)
269 loaded = load_escalation(repo, rec.escalation_id)
270 assert loaded is not None
271 assert loaded.escalated_by.type == "human"
272
273 def test_escalated_by_agent_round_trips(self, repo: pathlib.Path) -> None:
274 rec = _make_record(agent_id="claude-code")
275 record_escalation(repo, rec)
276 loaded = load_escalation(repo, rec.escalation_id)
277 assert loaded is not None
278 assert loaded.escalated_by.agent_id == "claude-code"
279
280 def test_validates_id_rejects_traversal(self, repo: pathlib.Path) -> None:
281 with pytest.raises(ValueError):
282 load_escalation(repo, "../../evil")
283
284
285 class TestListEscalations:
286 """II: list_escalations returns sorted list with optional status filter."""
287
288 def test_empty_store_returns_empty(self, repo: pathlib.Path) -> None:
289 assert list_escalations(repo) == []
290
291 def test_returns_all_by_default(self, repo: pathlib.Path) -> None:
292 pid1, pid2 = fake_id("p1"), fake_id("p2")
293 record_escalation(repo, _make_record(pid1, "r1"))
294 record_escalation(repo, _make_record(pid2, "r2"))
295 assert len(list_escalations(repo)) == 2
296
297 def test_filter_open_only(self, repo: pathlib.Path) -> None:
298 pid1, pid2 = fake_id("p1"), fake_id("p2")
299 rec1 = _make_record(pid1, "r1")
300 rec2 = _make_record(pid2, "r2")
301 record_escalation(repo, rec1)
302 record_escalation(repo, rec2)
303 resolve_escalation(
304 repo, rec2.escalation_id, fake_id("res"),
305 AgentProvenance.human(), _utc_now()
306 )
307 results = list_escalations(repo, status=EscalationStatus.OPEN)
308 assert len(results) == 1
309 assert results[0].escalation_id == rec1.escalation_id
310
311 def test_filter_resolved_only(self, repo: pathlib.Path) -> None:
312 pid1, pid2 = fake_id("p1"), fake_id("p2")
313 rec1 = _make_record(pid1, "r1")
314 rec2 = _make_record(pid2, "r2")
315 record_escalation(repo, rec1)
316 record_escalation(repo, rec2)
317 resolve_escalation(
318 repo, rec2.escalation_id, fake_id("res"),
319 AgentProvenance.human(), _utc_now()
320 )
321 results = list_escalations(repo, status=EscalationStatus.RESOLVED)
322 assert len(results) == 1
323 assert results[0].escalation_id == rec2.escalation_id
324
325 def test_sorted_newest_first(self, repo: pathlib.Path) -> None:
326 pids = [fake_id(f"p{i}") for i in range(3)]
327 for i, pid in enumerate(pids):
328 rec = _make_record(pid, f"reason {i}")
329 record_escalation(repo, rec)
330 results = list_escalations(repo)
331 timestamps = [r.escalated_at for r in results]
332 assert timestamps == sorted(timestamps, reverse=True)
333
334 def test_skips_symlinks(self, repo: pathlib.Path) -> None:
335 rec = _make_record()
336 record_escalation(repo, rec)
337 esc_dir = escalations_dir(repo)
338 link = esc_dir / ("a" * 64 + ".json")
339 link.symlink_to(esc_dir / f"{long_id(rec.escalation_id, strip=True)}.json")
340 results = list_escalations(repo)
341 assert len(results) == 1 # symlink skipped
342
343
344 class TestResolveEscalation:
345 """II: resolve_escalation transitions open → resolved atomically."""
346
347 def test_returns_true_when_found(self, repo: pathlib.Path) -> None:
348 rec = _make_record()
349 record_escalation(repo, rec)
350 result = resolve_escalation(
351 repo, rec.escalation_id, fake_id("res"),
352 AgentProvenance.human(), _utc_now()
353 )
354 assert result is True
355
356 def test_returns_false_when_not_found(self, repo: pathlib.Path) -> None:
357 eid = fake_id("missing")
358 result = resolve_escalation(
359 repo, eid, fake_id("res"),
360 AgentProvenance.human(), _utc_now()
361 )
362 assert result is False
363
364 def test_status_updated_to_resolved(self, repo: pathlib.Path) -> None:
365 rec = _make_record()
366 record_escalation(repo, rec)
367 resolve_escalation(
368 repo, rec.escalation_id, fake_id("res"),
369 AgentProvenance.human(), _utc_now()
370 )
371 loaded = load_escalation(repo, rec.escalation_id)
372 assert loaded is not None
373 assert loaded.status == EscalationStatus.RESOLVED
374
375 def test_resolution_id_stored(self, repo: pathlib.Path) -> None:
376 rec = _make_record()
377 record_escalation(repo, rec)
378 res_id = fake_id("resolution")
379 resolve_escalation(
380 repo, rec.escalation_id, res_id,
381 AgentProvenance.human(), _utc_now()
382 )
383 loaded = load_escalation(repo, rec.escalation_id)
384 assert loaded is not None
385 assert loaded.resolution_id == res_id
386
387 def test_resolved_by_stored(self, repo: pathlib.Path) -> None:
388 rec = _make_record()
389 record_escalation(repo, rec)
390 actor = AgentProvenance.agent("claude-code", "claude-sonnet-4-6")
391 resolve_escalation(repo, rec.escalation_id, fake_id("res"), actor, _utc_now())
392 loaded = load_escalation(repo, rec.escalation_id)
393 assert loaded is not None
394 assert loaded.resolved_by is not None
395 assert loaded.resolved_by.agent_id == "claude-code"
396
397 def test_resolved_at_stored(self, repo: pathlib.Path) -> None:
398 rec = _make_record()
399 record_escalation(repo, rec)
400 now = _utc_now()
401 resolve_escalation(repo, rec.escalation_id, fake_id("res"),
402 AgentProvenance.human(), now)
403 loaded = load_escalation(repo, rec.escalation_id)
404 assert loaded is not None
405 assert loaded.resolved_at is not None
406
407 def test_validates_escalation_id(self, repo: pathlib.Path) -> None:
408 with pytest.raises(ValueError):
409 resolve_escalation(
410 repo, "bad-id", fake_id("res"),
411 AgentProvenance.human(), _utc_now()
412 )
413
414 def test_no_temp_files_after_resolve(self, repo: pathlib.Path) -> None:
415 rec = _make_record()
416 record_escalation(repo, rec)
417 resolve_escalation(
418 repo, rec.escalation_id, fake_id("res"),
419 AgentProvenance.human(), _utc_now()
420 )
421 esc_dir = escalations_dir(repo)
422 assert list(esc_dir.glob("*.tmp")) == []
423
424
425 # ===========================================================================
426 # Tier III — End-to-end
427 # ===========================================================================
428
429
430 class TestEndToEnd:
431 """III: full lifecycle: escalate → list → resolve → audit."""
432
433 def test_escalate_list_resolve_audit(self, repo: pathlib.Path) -> None:
434 pid = fake_id("track.mid:content")
435 reason = "No policy or resolution found for pattern"
436 actor = AgentProvenance.agent("claude-code")
437
438 # 1. record escalation
439 rec = EscalationRecord(
440 escalation_id=compute_escalation_id(pid, reason),
441 pattern_id=pid,
442 reason=reason,
443 escalated_at=_utc_now(),
444 escalated_by=actor,
445 )
446 record_escalation(repo, rec)
447
448 # 2. audit escalation event
449 append_audit(repo, AuditEventType.ESCALATION_RECORDED, actor, pattern_id=pid)
450
451 # 3. list shows 1 open escalation
452 open_esc = list_escalations(repo, status=EscalationStatus.OPEN)
453 assert len(open_esc) == 1
454
455 # 4. resolve it
456 res_id = fake_id("resolution")
457 resolve_escalation(repo, rec.escalation_id, res_id, actor, _utc_now())
458 append_audit(
459 repo, AuditEventType.ESCALATION_RESOLVED, actor,
460 pattern_id=pid, metadata={"escalation_id": rec.escalation_id}
461 )
462
463 # 5. now 0 open, 1 resolved
464 assert list_escalations(repo, status=EscalationStatus.OPEN) == []
465 resolved = list_escalations(repo, status=EscalationStatus.RESOLVED)
466 assert len(resolved) == 1
467
468 # 6. audit log has both events
469 entries = list_audit(repo)
470 event_types = {e["event_type"] for e in entries}
471 assert AuditEventType.ESCALATION_RECORDED in event_types
472 assert AuditEventType.ESCALATION_RESOLVED in event_types
473
474 def test_multiple_patterns_independent_escalations(self, repo: pathlib.Path) -> None:
475 pids = [fake_id(f"track{i}.mid") for i in range(5)]
476 recs = []
477 for pid in pids:
478 rec = _make_record(pid, "no match")
479 record_escalation(repo, rec)
480 recs.append(rec)
481
482 assert len(list_escalations(repo)) == 5
483
484 # resolve two of them
485 for rec in recs[:2]:
486 resolve_escalation(repo, rec.escalation_id, fake_id("res"),
487 AgentProvenance.human(), _utc_now())
488
489 assert len(list_escalations(repo, status=EscalationStatus.OPEN)) == 3
490 assert len(list_escalations(repo, status=EscalationStatus.RESOLVED)) == 2
491
492
493 # ===========================================================================
494 # Tier IV — Stress
495 # ===========================================================================
496
497
498 class TestStress:
499 """IV: 200 escalations; concurrent record idempotency."""
500
501 def test_list_200_escalations(self, repo: pathlib.Path) -> None:
502 pids = [fake_id(f"stress-{i}") for i in range(200)]
503 for pid in pids:
504 record_escalation(repo, _make_record(pid, "stress"))
505 results = list_escalations(repo)
506 assert len(results) == 200
507
508 def test_concurrent_record_same_id_idempotent(self, repo: pathlib.Path) -> None:
509 """Concurrent writes of the same escalation_id must not corrupt data."""
510 rec = _make_record()
511 n = 20
512
513 def _write() -> bool:
514 return record_escalation(repo, rec)
515
516 with concurrent.futures.ThreadPoolExecutor(max_workers=n) as ex:
517 futures = [ex.submit(_write) for _ in range(n)]
518 results = [f.result() for f in futures]
519
520 # File must exist and be valid JSON
521 dest = escalation_path(repo, rec.escalation_id)
522 assert dest.exists()
523 data = json.loads(dest.read_text())
524 assert data["escalation_id"] == rec.escalation_id
525 # At least one write must have succeeded
526 assert any(results)
527
528
529 # ===========================================================================
530 # Tier V — Data integrity
531 # ===========================================================================
532
533
534 class TestDataIntegrity:
535 """V: JSON round-trip; all fields present; frozen records."""
536
537 def test_json_round_trip_open(self, repo: pathlib.Path) -> None:
538 rec = _make_record()
539 record_escalation(repo, rec)
540 loaded = load_escalation(repo, rec.escalation_id)
541 assert loaded is not None
542 assert loaded.escalation_id == rec.escalation_id
543 assert loaded.pattern_id == rec.pattern_id
544 assert loaded.reason == rec.reason
545 assert loaded.status == EscalationStatus.OPEN
546 assert loaded.resolved_at is None
547 assert loaded.resolved_by is None
548 assert loaded.resolution_id is None
549
550 def test_json_round_trip_resolved(self, repo: pathlib.Path) -> None:
551 rec = _make_record()
552 record_escalation(repo, rec)
553 res_id = fake_id("res")
554 actor = AgentProvenance.agent("claude-code", "claude-sonnet-4-6")
555 now = _utc_now()
556 resolve_escalation(repo, rec.escalation_id, res_id, actor, now)
557 loaded = load_escalation(repo, rec.escalation_id)
558 assert loaded is not None
559 assert loaded.status == EscalationStatus.RESOLVED
560 assert loaded.resolution_id == res_id
561 assert loaded.resolved_by is not None
562 assert loaded.resolved_by.agent_id == "claude-code"
563 assert loaded.resolved_by.model_id == "claude-sonnet-4-6"
564 assert loaded.resolved_at is not None
565
566 def test_escalation_record_is_frozen(self) -> None:
567 rec = _make_record()
568 assert dataclasses.is_dataclass(rec)
569 with pytest.raises((dataclasses.FrozenInstanceError, AttributeError)):
570 rec.reason = "mutated" # type: ignore[misc]
571
572 def test_no_temp_files_in_escalations_dir(self, repo: pathlib.Path) -> None:
573 for i in range(5):
574 record_escalation(repo, _make_record(fake_id(f"p{i}"), "r"))
575 esc_dir = escalations_dir(repo)
576 assert list(esc_dir.glob("*.tmp")) == []
577
578 def test_escalated_at_is_utc_aware(self, repo: pathlib.Path) -> None:
579 rec = _make_record()
580 record_escalation(repo, rec)
581 loaded = load_escalation(repo, rec.escalation_id)
582 assert loaded is not None
583 assert loaded.escalated_at.tzinfo is not None
584
585
586 # ===========================================================================
587 # Tier VI — Security
588 # ===========================================================================
589
590
591 class TestSecurity:
592 """VI: ID validation; path traversal rejected; size cap."""
593
594 def test_load_traversal_rejected(self, repo: pathlib.Path) -> None:
595 with pytest.raises(ValueError):
596 load_escalation(repo, "../../etc/passwd")
597
598 def test_resolve_traversal_rejected(self, repo: pathlib.Path) -> None:
599 with pytest.raises(ValueError):
600 resolve_escalation(
601 repo, "../evil", fake_id("r"),
602 AgentProvenance.human(), _utc_now()
603 )
604
605 def test_load_null_byte_rejected(self, repo: pathlib.Path) -> None:
606 with pytest.raises(ValueError):
607 load_escalation(repo, "a" * 63 + "\x00")
608
609 def test_load_too_short_rejected(self, repo: pathlib.Path) -> None:
610 with pytest.raises(ValueError):
611 load_escalation(repo, "abc")
612
613 def test_load_uppercase_hex_rejected(self, repo: pathlib.Path) -> None:
614 with pytest.raises(ValueError):
615 load_escalation(repo, "A" * 64)
616
617 def test_list_skips_non_json_files(self, repo: pathlib.Path) -> None:
618 rec = _make_record()
619 record_escalation(repo, rec)
620 # Plant a non-JSON file
621 esc_dir = escalations_dir(repo)
622 (esc_dir / "not-a-real-file.txt").write_text("noise")
623 results = list_escalations(repo)
624 assert len(results) == 1
625
626 def test_oversized_escalation_file_skipped(self, repo: pathlib.Path) -> None:
627 """Files exceeding _MAX_ESCALATION_BYTES must be silently skipped."""
628 rec = _make_record()
629 record_escalation(repo, rec)
630 dest = escalation_path(repo, rec.escalation_id)
631 # Bloat the file beyond 16 KiB
632 bloated = dest.read_text() + " " * 20_000
633 dest.write_text(bloated)
634 results = list_escalations(repo)
635 assert results == []
636
637 def test_symlinks_in_escalations_dir_skipped(self, repo: pathlib.Path) -> None:
638 rec = _make_record()
639 record_escalation(repo, rec)
640 esc_dir = escalations_dir(repo)
641 link = esc_dir / f"{'b' * 64}.json"
642 link.symlink_to(esc_dir / f"{long_id(rec.escalation_id, strip=True)}.json")
643 results = list_escalations(repo)
644 assert len(results) == 1 # only real file
645
646
647 # ===========================================================================
648 # Tier VII — Performance
649 # ===========================================================================
650
651
652 class TestPerformance:
653 """VII: all ops complete within 50 ms."""
654
655 def test_record_escalation_under_50ms(self, repo: pathlib.Path) -> None:
656 rec = _make_record()
657 start = time.monotonic()
658 record_escalation(repo, rec)
659 elapsed = (time.monotonic() - start) * 1000
660 assert elapsed < 50, f"record_escalation took {elapsed:.1f}ms"
661
662 def test_load_escalation_under_50ms(self, repo: pathlib.Path) -> None:
663 rec = _make_record()
664 record_escalation(repo, rec)
665 start = time.monotonic()
666 load_escalation(repo, rec.escalation_id)
667 elapsed = (time.monotonic() - start) * 1000
668 assert elapsed < 50, f"load_escalation took {elapsed:.1f}ms"
669
670 def test_resolve_escalation_under_50ms(self, repo: pathlib.Path) -> None:
671 rec = _make_record()
672 record_escalation(repo, rec)
673 start = time.monotonic()
674 resolve_escalation(repo, rec.escalation_id, fake_id("r"),
675 AgentProvenance.human(), _utc_now())
676 elapsed = (time.monotonic() - start) * 1000
677 assert elapsed < 50, f"resolve_escalation took {elapsed:.1f}ms"
678
679 def test_list_100_escalations_under_50ms(self, repo: pathlib.Path) -> None:
680 for i in range(100):
681 record_escalation(repo, _make_record(fake_id(f"p{i}"), "r"))
682 start = time.monotonic()
683 list_escalations(repo)
684 elapsed = (time.monotonic() - start) * 1000
685 assert elapsed < 50, f"list_escalations(100) took {elapsed:.1f}ms"
686
687 def test_compute_escalation_id_under_1ms(self) -> None:
688 pid = fake_id("p")
689 start = time.monotonic()
690 compute_escalation_id(pid, "reason")
691 elapsed = (time.monotonic() - start) * 1000
692 assert elapsed < 1, f"compute_escalation_id took {elapsed:.2f}ms"
File History 2 commits
sha256:b636f72dcba9e190afb980bece906fa5b717fbde014b76ef023df8cb96e01eb9 docs: expand cache plan with all seven testing tiers and do… Sonnet 4.6 133 days ago
sha256:7f9e2ef5286aedad9c1e6011b4c46ca27f39dbdad6e3409357e36b26e46b3b7c docs: docstring sprint for-each-ref→hotspots — idiomatic ru… Sonnet 4.6 patch 139 days ago