gabriel / muse public
test_cmd_verify_commit.py python
1,054 lines 47.1 KB
Raw
sha256:b636f72dcba9e190afb980bece906fa5b717fbde014b76ef023df8cb96e01eb9 docs: expand cache plan with all seven testing tiers and do… Sonnet 4.6 132 days ago
1 """Tests for ``muse verify-commit`` — verify Ed25519 signatures on commits.
2
3 Coverage tiers
4 --------------
5 Unit:
6 _resolve_ref — HEAD→tip, HEAD→missing branch, sha256:-prefixed passthrough,
7 branch name→ref file, missing branch ref→None
8 _verify_one — valid sig, unsigned, missing commit, missing pubkey, bit-flip
9 in signature, unknown sig
10 algo, unknown pubkey algo, committed_at tamper, model_id tamper,
11 wrong keypair, decode_pubkey ValueError, signed_at non-empty,
12 error None on success, key_status cache hit
13 _fetch_key_status — active, revoked, unknown status value, network error
14
15 Integration:
16 Text output: OK/BAD/ERR lines, (unsigned) signer, key= part present/absent
17 JSON output: all schema fields, error field stripped, signed_at non-empty,
18 signer matches agent_id
19 --strict: unsigned exits nonzero; without --strict exits 0
20 --check-key-status: unknown without hub; caches per key_id
21 HEAD shorthand, branch name ref
22 Batch: all valid exits 0; one invalid exits nonzero; result order preserved
23 Nonexistent sha256:- ref → USER_ERROR
24 --json flag accepted (shorthand alias)
25
26 Security:
27 ANSI escape in ref → rejected, error to stderr, stdout empty
28 Null byte in ref → rejected
29 Path traversal ref → rejected
30 Bare hex ref → rejected with clear message, error to stderr, stdout empty
31 No traceback on bad ref or bad format
32
33 Data integrity:
34 committed_at tamper → invalid through full CLI flow
35 model_id tamper → invalid through full CLI flow
36 Wrong keypair → invalid (public key doesn't match signing key)
37
38 Stress:
39 100 signed commits all verify correctly (unit)
40 Batch of 50 commits via CLI → all results emitted
41 key_status_cache: N commits with same key → exactly 1 network call
42 """
43
44 from __future__ import annotations
45 from collections.abc import Mapping
46
47 import datetime
48 import json
49 import pathlib
50 from unittest.mock import MagicMock, patch
51
52 import pytest
53
54 from muse.core._types import blob_id, decode_sig, encode_sig, split_id
55 from muse.core.object_store import write_object
56 from muse.core.provenance import (
57 encode_public_key,
58 provenance_payload,
59 sign_commit_record,
60 verify_commit_ed25519,
61 )
62 from muse.core.snapshot import compute_commit_id, compute_snapshot_id
63 from muse.core.store import CommitRecord, SnapshotRecord, commit_path, write_commit, write_snapshot
64 from muse.core._types import Manifest
65 from tests.cli_test_helper import CliRunner
66
67 runner = CliRunner()
68
69 _REPO_ID = "verify-commit-test"
70 _counter = 0
71
72
73 # ---------------------------------------------------------------------------
74 # Helpers
75 # ---------------------------------------------------------------------------
76
77
78 def _init_repo(path: pathlib.Path) -> pathlib.Path:
79 muse = path / ".muse"
80 for d in ("commits", "snapshots", "objects", "refs/heads", "code"):
81 (muse / d).mkdir(parents=True, exist_ok=True)
82 (muse / "HEAD").write_text("ref: refs/heads/main", encoding="utf-8")
83 (muse / "repo.json").write_text(
84 json.dumps({"repo_id": _REPO_ID, "domain": "code"}), encoding="utf-8"
85 )
86 return path
87
88
89 def _env(repo: pathlib.Path) -> Mapping[str, str]:
90 return {"MUSE_REPO_ROOT": str(repo)}
91
92
93 def _make_key():
94 """Generate a fresh Ed25519 private key."""
95 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
96 return Ed25519PrivateKey.generate()
97
98
99 def _commit_files(
100 root: pathlib.Path,
101 files: Mapping[str, bytes],
102 branch: str = "main",
103 message: str | None = None,
104 sign: bool = False,
105 private_key=None,
106 agent_id: str = "test-agent",
107 model_id: str = "",
108 ) -> tuple[str, CommitRecord]:
109 """Create a commit; optionally sign it. Returns (commit_id, CommitRecord)."""
110 global _counter
111 _counter += 1
112 manifest: Manifest = {}
113 for rel_path, content in files.items():
114 obj_id = blob_id(content)
115 write_object(root, obj_id, content)
116 manifest[rel_path] = obj_id
117 abs_path = root / rel_path
118 abs_path.parent.mkdir(parents=True, exist_ok=True)
119 abs_path.write_bytes(content)
120 snap_id = compute_snapshot_id(manifest)
121 write_snapshot(root, SnapshotRecord(snapshot_id=snap_id, manifest=manifest))
122 committed_at = datetime.datetime.now(datetime.timezone.utc)
123 ref_path = root / ".muse" / "refs" / "heads" / branch
124 parent_id = ref_path.read_text(encoding="utf-8").strip() if ref_path.exists() else None
125 parents = [parent_id] if parent_id else []
126 msg = message or f"commit {_counter}"
127
128 # Resolve public key before compute_commit_id so signer_public_key is
129 # bound into the v2 hash (matching what _verify_commit_id expects).
130 sig = ""
131 pub_b64 = ""
132 key_id = ""
133 if sign and private_key is not None:
134 from muse.core.provenance import encode_public_key
135 _, pub_b64 = encode_public_key(private_key)
136
137 commit_id = compute_commit_id(
138 repo_id=_REPO_ID,
139 parent_ids=parents,
140 snapshot_id=snap_id,
141 message=msg,
142 committed_at_iso=committed_at.isoformat(),
143 signer_public_key=pub_b64,
144 )
145
146 if sign and private_key is not None:
147 result = sign_commit_record(
148 commit_id,
149 agent_id,
150 private_key,
151 model_id=model_id,
152 committed_at=committed_at.isoformat(),
153 )
154 if result:
155 sig, pub_b64, key_id = result
156
157 record = CommitRecord(
158 commit_id=commit_id,
159 repo_id=_REPO_ID,
160 created_on_branch=branch,
161 snapshot_id=snap_id,
162 message=msg,
163 committed_at=committed_at,
164 parent_commit_id=parent_id,
165 agent_id=agent_id if sign else "",
166 model_id=model_id if sign else "",
167 signature=sig,
168 signer_public_key=pub_b64,
169 signer_key_id=key_id,
170 )
171 write_commit(root, record)
172 ref_path.write_text(commit_id, encoding="utf-8")
173 return commit_id, record
174
175
176 def _invoke(repo: pathlib.Path, *args: str):
177 from muse.cli.app import main as cli
178 return runner.invoke(cli, ["verify-commit", *args], env=_env(repo))
179
180
181 def _force_write_commit(root: pathlib.Path, record: CommitRecord) -> None:
182 """Overwrite a commit file unconditionally (bypasses write_commit idempotency)."""
183 import msgpack
184 commit_file = commit_path(root, record.commit_id)
185 commit_file.write_bytes(msgpack.packb(record.to_dict(), use_bin_type=True))
186
187
188 # ---------------------------------------------------------------------------
189 # Unit — _resolve_ref
190 # ---------------------------------------------------------------------------
191
192
193 class TestResolveRef:
194 def test_head_resolves_to_branch_tip(self, tmp_path: pathlib.Path) -> None:
195 from muse.cli.commands.verify_commit import _resolve_ref
196 root = _init_repo(tmp_path)
197 key = _make_key()
198 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
199 resolved = _resolve_ref(root, "HEAD")
200 assert resolved == commit_id
201
202 def test_head_returns_none_when_branch_has_no_commits(self, tmp_path: pathlib.Path) -> None:
203 from muse.cli.commands.verify_commit import _resolve_ref
204 root = _init_repo(tmp_path)
205 # HEAD points to main but main ref file doesn't exist yet
206 resolved = _resolve_ref(root, "HEAD")
207 assert resolved is None
208
209 def test_sha256_prefixed_id_passthrough(self, tmp_path: pathlib.Path) -> None:
210 """sha256:-prefixed IDs are returned as-is (no ref-file lookup)."""
211 from muse.cli.commands.verify_commit import _resolve_ref
212 root = _init_repo(tmp_path)
213 key = _make_key()
214 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
215 resolved = _resolve_ref(root, commit_id)
216 assert resolved == commit_id
217
218 def test_bare_hex_normalised_to_sha256_prefix(self, tmp_path: pathlib.Path) -> None:
219 """A 64-char bare hex is normalised to sha256: prefix."""
220 from muse.cli.commands.verify_commit import _resolve_ref
221 root = _init_repo(tmp_path)
222 key = _make_key()
223 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
224 bare = split_id(commit_id)[1]
225 resolved = _resolve_ref(root, bare)
226 assert resolved == commit_id
227
228 def test_branch_name_resolves_via_ref_file(self, tmp_path: pathlib.Path) -> None:
229 from muse.cli.commands.verify_commit import _resolve_ref
230 root = _init_repo(tmp_path)
231 key = _make_key()
232 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, branch="dev")
233 resolved = _resolve_ref(root, "dev")
234 assert resolved == commit_id
235
236 def test_missing_branch_ref_returns_none(self, tmp_path: pathlib.Path) -> None:
237 from muse.cli.commands.verify_commit import _resolve_ref
238 root = _init_repo(tmp_path)
239 resolved = _resolve_ref(root, "nonexistent-branch")
240 assert resolved is None
241
242
243 # ---------------------------------------------------------------------------
244 # Unit — _verify_one
245 # ---------------------------------------------------------------------------
246
247
248 class TestVerifyOne:
249 def test_valid_signature(self, tmp_path: pathlib.Path) -> None:
250 from muse.cli.commands.verify_commit import _verify_one
251 root = _init_repo(tmp_path)
252 key = _make_key()
253 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
254 result = _verify_one(root, commit_id)
255 assert result["valid"] is True
256 assert result["commit_id"] == commit_id
257 assert len(result["key_id"]) > 0
258
259 def test_unsigned_commit_valid_false_no_error(self, tmp_path: pathlib.Path) -> None:
260 from muse.cli.commands.verify_commit import _verify_one
261 root = _init_repo(tmp_path)
262 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
263 result = _verify_one(root, commit_id)
264 assert result["valid"] is False
265 assert result["error"] is None
266 assert result["signer"] == ""
267
268 def test_missing_commit_returns_error(self, tmp_path: pathlib.Path) -> None:
269 from muse.cli.commands.verify_commit import _verify_one
270 root = _init_repo(tmp_path)
271 result = _verify_one(root, blob_id(b"nonexistent commit"))
272 assert result["valid"] is False
273 assert "not found" in (result["error"] or "")
274
275 def test_missing_public_key_valid_false(self, tmp_path: pathlib.Path) -> None:
276 from muse.cli.commands.verify_commit import _verify_one
277 root = _init_repo(tmp_path)
278 key = _make_key()
279 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
280 tampered = CommitRecord(
281 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
282 snapshot_id=record.snapshot_id, message=record.message,
283 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
284 agent_id=record.agent_id, signature=record.signature,
285 signer_public_key="", # stripped
286 signer_key_id=record.signer_key_id,
287 )
288 _force_write_commit(root, tampered)
289 result = _verify_one(root, commit_id)
290 assert result["valid"] is False
291
292 def test_bit_flip_in_signature(self, tmp_path: pathlib.Path) -> None:
293 """A single bit flip in the stored signature must invalidate it."""
294 from muse.cli.commands.verify_commit import _verify_one
295 root = _init_repo(tmp_path)
296 key = _make_key()
297 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
298 algo, sig_bytes = decode_sig(record.signature)
299 flipped = bytes([sig_bytes[0] ^ 0xFF]) + sig_bytes[1:]
300 bad_sig = encode_sig(algo, flipped)
301 tampered = CommitRecord(
302 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
303 snapshot_id=record.snapshot_id, message=record.message,
304 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
305 agent_id=record.agent_id, signature=bad_sig,
306 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
307 )
308 _force_write_commit(root, tampered)
309 result = _verify_one(root, commit_id)
310 assert result["valid"] is False
311
312 def test_unknown_signature_algorithm(self, tmp_path: pathlib.Path) -> None:
313 """A commit whose signature carries an unknown algorithm prefix returns valid=False."""
314 from muse.cli.commands.verify_commit import _verify_one
315 root = _init_repo(tmp_path)
316 key = _make_key()
317 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
318 _, raw_sig_bytes = decode_sig(record.signature)
319 unknown_sig = encode_sig("mldsa65", raw_sig_bytes)
320 tampered = CommitRecord(
321 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
322 snapshot_id=record.snapshot_id, message=record.message,
323 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
324 agent_id=record.agent_id, signature=unknown_sig,
325 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
326 )
327 _force_write_commit(root, tampered)
328 result = _verify_one(root, commit_id)
329 assert result["valid"] is False
330 assert "mldsa65" in (result.get("error") or "")
331
332 def test_unknown_public_key_algorithm(self, tmp_path: pathlib.Path) -> None:
333 """A commit with an unknown pubkey algorithm prefix returns valid=False with error."""
334 from muse.cli.commands.verify_commit import _verify_one
335 from muse.core._types import encode_pubkey, encode_sig
336 from muse.core.snapshot import compute_snapshot_id
337 from muse.core.store import write_snapshot, SnapshotRecord
338 root = _init_repo(tmp_path)
339
340 # Build commit with mldsa65 key from scratch so commit_id is consistent.
341 fake_mldsa_key = encode_pubkey("mldsa65", b"\xab" * 32)
342 fake_sig = encode_sig("ed25519", b"\x00" * 64)
343 snap_id = compute_snapshot_id({"a.py": blob_id(b"x = 1\n")})
344 write_snapshot(root, SnapshotRecord(snapshot_id=snap_id, manifest={"a.py": blob_id(b"x = 1\n")}))
345 import datetime
346 committed_at = datetime.datetime(2026, 1, 1, tzinfo=datetime.timezone.utc)
347 commit_id = compute_commit_id(
348 repo_id=_REPO_ID, parent_ids=[], snapshot_id=snap_id,
349 message="mldsa-test", committed_at_iso=committed_at.isoformat(),
350 signer_public_key=fake_mldsa_key,
351 )
352 record = CommitRecord(
353 commit_id=commit_id, repo_id=_REPO_ID, created_on_branch="main",
354 snapshot_id=snap_id, message="mldsa-test", committed_at=committed_at,
355 agent_id="test-agent", signature=fake_sig,
356 signer_public_key=fake_mldsa_key,
357 )
358 commit_path(root, commit_id).parent.mkdir(parents=True, exist_ok=True)
359 _force_write_commit(root, record)
360 (root / ".muse" / "refs" / "heads" / "main").write_text(commit_id, encoding="utf-8")
361
362 result = _verify_one(root, commit_id)
363 assert result["valid"] is False
364 assert "mldsa65" in (result.get("error") or "")
365
366 def test_committed_at_tamper_invalidates_signature(self, tmp_path: pathlib.Path) -> None:
367 """Mutating committed_at in the stored record must invalidate the signature."""
368 from muse.cli.commands.verify_commit import _verify_one
369 root = _init_repo(tmp_path)
370 key = _make_key()
371 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
372 # Shift committed_at by one day.
373 original_ts = record.committed_at
374 tampered_ts = original_ts + datetime.timedelta(days=1)
375 tampered = CommitRecord(
376 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
377 snapshot_id=record.snapshot_id, message=record.message,
378 committed_at=tampered_ts, # mutated
379 parent_commit_id=record.parent_commit_id,
380 agent_id=record.agent_id, signature=record.signature,
381 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
382 )
383 _force_write_commit(root, tampered)
384 result = _verify_one(root, commit_id)
385 assert result["valid"] is False
386
387 def test_agent_id_tamper_invalidates_signature(self, tmp_path: pathlib.Path) -> None:
388 """Changing agent_id in the stored record must invalidate the signature."""
389 from muse.cli.commands.verify_commit import _verify_one
390 root = _init_repo(tmp_path)
391 key = _make_key()
392 commit_id, record = _commit_files(
393 root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, agent_id="agent-A"
394 )
395 tampered = CommitRecord(
396 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
397 snapshot_id=record.snapshot_id, message=record.message,
398 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
399 agent_id="agent-B", # tampered
400 signature=record.signature,
401 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
402 )
403 _force_write_commit(root, tampered)
404 result = _verify_one(root, commit_id)
405 assert result["valid"] is False
406
407 def test_model_id_tamper_invalidates_signature(self, tmp_path: pathlib.Path) -> None:
408 """Changing model_id in the stored record must invalidate the signature."""
409 from muse.cli.commands.verify_commit import _verify_one
410 root = _init_repo(tmp_path)
411 key = _make_key()
412 commit_id, record = _commit_files(
413 root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, model_id="claude-sonnet-4-6"
414 )
415 tampered = CommitRecord(
416 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
417 snapshot_id=record.snapshot_id, message=record.message,
418 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
419 agent_id=record.agent_id, model_id="claude-opus-4-6", # tampered
420 signature=record.signature,
421 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
422 )
423 _force_write_commit(root, tampered)
424 result = _verify_one(root, commit_id)
425 assert result["valid"] is False
426
427 def test_wrong_keypair_invalid(self, tmp_path: pathlib.Path) -> None:
428 """Public key from a different keypair must not verify the signature."""
429 from muse.cli.commands.verify_commit import _verify_one
430 root = _init_repo(tmp_path)
431 signing_key = _make_key()
432 wrong_key = _make_key()
433 commit_id, record = _commit_files(
434 root, {"a.py": b"x = 1\n"}, sign=True, private_key=signing_key
435 )
436 # Swap in the public key from wrong_key.
437 _, wrong_pub_b64 = encode_public_key(wrong_key)
438 tampered = CommitRecord(
439 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
440 snapshot_id=record.snapshot_id, message=record.message,
441 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
442 agent_id=record.agent_id, signature=record.signature,
443 signer_public_key=wrong_pub_b64, signer_key_id=record.signer_key_id,
444 )
445 _force_write_commit(root, tampered)
446 result = _verify_one(root, commit_id)
447 assert result["valid"] is False
448
449 def test_signed_at_populated_for_signed_commit(self, tmp_path: pathlib.Path) -> None:
450 """signed_at is a non-empty ISO string for a signed commit."""
451 from muse.cli.commands.verify_commit import _verify_one
452 root = _init_repo(tmp_path)
453 key = _make_key()
454 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
455 result = _verify_one(root, commit_id)
456 assert result["signed_at"]
457 assert "T" in result["signed_at"] # ISO 8601 format
458
459 def test_error_none_for_valid_commit(self, tmp_path: pathlib.Path) -> None:
460 """error field is None when the signature is valid."""
461 from muse.cli.commands.verify_commit import _verify_one
462 root = _init_repo(tmp_path)
463 key = _make_key()
464 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
465 result = _verify_one(root, commit_id)
466 assert result["error"] is None
467
468 def test_key_status_unknown_without_hub(self, tmp_path: pathlib.Path) -> None:
469 from muse.cli.commands.verify_commit import _verify_one
470 root = _init_repo(tmp_path)
471 key = _make_key()
472 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
473 result = _verify_one(root, commit_id, check_key_status=True, hub_url=None)
474 assert result["key_status"] == "unknown"
475
476 def test_key_status_cache_hit_skips_network(self, tmp_path: pathlib.Path) -> None:
477 """Cache hit must prevent a second _fetch_key_status call."""
478 from muse.cli.commands.verify_commit import _verify_one
479 root = _init_repo(tmp_path)
480 key = _make_key()
481 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
482 cache: dict[str, str] = {}
483 call_count = 0
484
485 def mock_fetch(hub_url, key_id):
486 nonlocal call_count
487 call_count += 1
488 return "active"
489
490 with patch("muse.cli.commands.verify_commit._fetch_key_status", side_effect=mock_fetch):
491 _verify_one(root, commit_id, check_key_status=True, hub_url="http://fake", key_status_cache=cache)
492 _verify_one(root, commit_id, check_key_status=True, hub_url="http://fake", key_status_cache=cache)
493
494 assert call_count == 1
495
496 def test_json_schema_all_keys_present(self, tmp_path: pathlib.Path) -> None:
497 from muse.cli.commands.verify_commit import _verify_one
498 root = _init_repo(tmp_path)
499 key = _make_key()
500 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
501 result = _verify_one(root, commit_id)
502 assert {"commit_id", "valid", "signer", "key_id", "signed_at", "key_status", "error"} == set(result)
503
504
505 # ---------------------------------------------------------------------------
506 # Unit — _fetch_key_status
507 # ---------------------------------------------------------------------------
508
509
510 class TestFetchKeyStatus:
511 def test_returns_active(self) -> None:
512 from muse.cli.commands.verify_commit import _fetch_key_status
513 mock_resp = MagicMock()
514 mock_resp.read.return_value = json.dumps({"status": "active"}).encode()
515 mock_resp.__enter__ = lambda s: s
516 mock_resp.__exit__ = MagicMock(return_value=False)
517 with patch("urllib.request.urlopen", return_value=mock_resp):
518 assert _fetch_key_status("http://hub", "key123") == "active"
519
520 def test_returns_revoked(self) -> None:
521 from muse.cli.commands.verify_commit import _fetch_key_status
522 mock_resp = MagicMock()
523 mock_resp.read.return_value = json.dumps({"status": "revoked"}).encode()
524 mock_resp.__enter__ = lambda s: s
525 mock_resp.__exit__ = MagicMock(return_value=False)
526 with patch("urllib.request.urlopen", return_value=mock_resp):
527 assert _fetch_key_status("http://hub", "key123") == "revoked"
528
529 def test_returns_unknown_for_unrecognised_status(self) -> None:
530 from muse.cli.commands.verify_commit import _fetch_key_status
531 mock_resp = MagicMock()
532 mock_resp.read.return_value = json.dumps({"status": "pending"}).encode()
533 mock_resp.__enter__ = lambda s: s
534 mock_resp.__exit__ = MagicMock(return_value=False)
535 with patch("urllib.request.urlopen", return_value=mock_resp):
536 assert _fetch_key_status("http://hub", "key123") == "unknown"
537
538 def test_returns_unknown_on_network_error(self) -> None:
539 from muse.cli.commands.verify_commit import _fetch_key_status
540 with patch("urllib.request.urlopen", side_effect=OSError("connection refused")):
541 assert _fetch_key_status("http://hub", "key123") == "unknown"
542
543 def test_returns_unknown_on_timeout(self) -> None:
544 from muse.cli.commands.verify_commit import _fetch_key_status
545 import socket
546 with patch("urllib.request.urlopen", side_effect=socket.timeout("timed out")):
547 assert _fetch_key_status("http://hub", "key123") == "unknown"
548
549 def test_returns_unknown_on_invalid_json(self) -> None:
550 from muse.cli.commands.verify_commit import _fetch_key_status
551 mock_resp = MagicMock()
552 mock_resp.read.return_value = b"not json"
553 mock_resp.__enter__ = lambda s: s
554 mock_resp.__exit__ = MagicMock(return_value=False)
555 with patch("urllib.request.urlopen", return_value=mock_resp):
556 assert _fetch_key_status("http://hub", "key123") == "unknown"
557
558
559 # ---------------------------------------------------------------------------
560 # Integration — text output
561 # ---------------------------------------------------------------------------
562
563
564 class TestTextOutput:
565 def test_ok_line_format(self, tmp_path: pathlib.Path) -> None:
566 """Text output: 'OK <short_id> signer=<agent_id> key=<key_id>'"""
567 root = _init_repo(tmp_path)
568 key = _make_key()
569 commit_id, _ = _commit_files(
570 root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, agent_id="claude-code"
571 )
572 result = _invoke(root, commit_id)
573 assert result.exit_code == 0
574 assert "OK" in result.output
575 assert "claude-code" in result.output
576 assert "key=" in result.output
577
578 def test_bad_line_for_invalid_signature(self, tmp_path: pathlib.Path) -> None:
579 root = _init_repo(tmp_path)
580 key = _make_key()
581 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
582 algo, sig_bytes = decode_sig(record.signature)
583 flipped = bytes([sig_bytes[0] ^ 0xFF]) + sig_bytes[1:]
584 tampered = CommitRecord(
585 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
586 snapshot_id=record.snapshot_id, message=record.message,
587 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
588 agent_id=record.agent_id, signature=encode_sig(algo, flipped),
589 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
590 )
591 _force_write_commit(root, tampered)
592 result = _invoke(root, commit_id)
593 assert result.exit_code != 0
594 assert "BAD" in result.output
595
596 def test_err_line_for_missing_commit(self, tmp_path: pathlib.Path) -> None:
597 """Text output: 'ERR <short_id> (commit not found)'"""
598 root = _init_repo(tmp_path)
599 key = _make_key()
600 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
601 # Write a ref that points to a commit that doesn't exist.
602 ghost_id = blob_id(b"ghost commit that does not exist")
603 result = _invoke(root, ghost_id)
604 assert result.exit_code != 0
605 assert "ERR" in result.output
606
607 def test_unsigned_shows_unsigned_signer(self, tmp_path: pathlib.Path) -> None:
608 """Unsigned commits show '(unsigned)' as the signer in text output."""
609 root = _init_repo(tmp_path)
610 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
611 result = _invoke(root, commit_id)
612 assert result.exit_code == 0
613 assert "(unsigned)" in result.output
614
615 def test_key_absent_from_text_output_for_unsigned(self, tmp_path: pathlib.Path) -> None:
616 """key= part must not appear in text output for unsigned commits."""
617 root = _init_repo(tmp_path)
618 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
619 result = _invoke(root, commit_id)
620 assert "key=" not in result.output
621
622 def test_short_commit_id_in_text_output(self, tmp_path: pathlib.Path) -> None:
623 """Text output uses short_id, not the full 71-char commit ID."""
624 root = _init_repo(tmp_path)
625 key = _make_key()
626 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
627 result = _invoke(root, commit_id)
628 assert commit_id not in result.output # full ID not present
629 assert commit_id[len("sha256:"):len("sha256:") + 12] in result.output # short hex present
630
631
632 # ---------------------------------------------------------------------------
633 # Integration — JSON output
634 # ---------------------------------------------------------------------------
635
636
637 class TestJsonOutput:
638 def test_valid_commit_all_fields(self, tmp_path: pathlib.Path) -> None:
639 root = _init_repo(tmp_path)
640 key = _make_key()
641 commit_id, _ = _commit_files(
642 root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, agent_id="claude-code"
643 )
644 result = _invoke(root, commit_id, "--json")
645 assert result.exit_code == 0
646 data = json.loads(result.stdout)
647 assert data["commit_id"] == commit_id
648 assert data["valid"] is True
649 assert data["signer"] == "claude-code"
650 assert data["key_id"]
651 assert data["key_status"] == "unknown"
652
653 def test_signed_at_non_empty_for_signed_commit(self, tmp_path: pathlib.Path) -> None:
654 root = _init_repo(tmp_path)
655 key = _make_key()
656 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
657 result = _invoke(root, commit_id, "--json")
658 data = json.loads(result.stdout)
659 assert data["signed_at"]
660 assert "T" in data["signed_at"]
661
662 def test_error_field_stripped_from_json_output(self, tmp_path: pathlib.Path) -> None:
663 """The internal 'error' field must not appear in emitted JSON."""
664 root = _init_repo(tmp_path)
665 key = _make_key()
666 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
667 result = _invoke(root, commit_id, "--json")
668 data = json.loads(result.stdout)
669 assert "error" not in data
670
671 def test_duration_ms_and_exit_code_in_json(self, tmp_path: pathlib.Path) -> None:
672 """duration_ms and exit_code are present in every JSON result line."""
673 root = _init_repo(tmp_path)
674 key = _make_key()
675 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
676 result = _invoke(root, commit_id, "--json")
677 data = json.loads(result.stdout)
678 assert "duration_ms" in data
679 assert isinstance(data["duration_ms"], float)
680 assert data["duration_ms"] >= 0
681 assert "exit_code" in data
682 assert data["exit_code"] == 0
683
684 def test_exit_code_nonzero_in_json_on_failure(self, tmp_path: pathlib.Path) -> None:
685 """exit_code reflects the actual exit status — non-zero when verification fails."""
686 root = _init_repo(tmp_path)
687 result = _invoke(root, blob_id(b"nonexistent commit"), "--json")
688 data = json.loads(result.stdout)
689 assert data["exit_code"] != 0
690 assert data["duration_ms"] >= 0
691
692 def test_unsigned_commit_json(self, tmp_path: pathlib.Path) -> None:
693 root = _init_repo(tmp_path)
694 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
695 result = _invoke(root, commit_id, "--json")
696 assert result.exit_code == 0
697 data = json.loads(result.stdout)
698 assert data["valid"] is False
699 assert data["signer"] == ""
700 assert "error" not in data
701
702 def test_batch_each_line_is_valid_json(self, tmp_path: pathlib.Path) -> None:
703 """Batch output: one valid JSON object per line."""
704 root = _init_repo(tmp_path)
705 key = _make_key()
706 ids = [_commit_files(root, {f"f{i}.py": f"x={i}".encode()}, sign=True, private_key=key)[0]
707 for i in range(3)]
708 result = _invoke(root, *ids, "--json")
709 assert result.exit_code == 0
710 lines = [l for l in result.stdout.strip().splitlines() if l]
711 assert len(lines) == 3
712 for line in lines:
713 obj = json.loads(line)
714 assert obj["valid"] is True
715
716 def test_batch_results_in_submission_order(self, tmp_path: pathlib.Path) -> None:
717 """Batch results must arrive in the same order as the input commit IDs."""
718 root = _init_repo(tmp_path)
719 key = _make_key()
720 ids = [_commit_files(root, {f"f{i}.py": f"x={i}".encode()}, sign=True, private_key=key)[0]
721 for i in range(5)]
722 result = _invoke(root, *ids, "--json")
723 assert result.exit_code == 0
724 lines = [l for l in result.stdout.strip().splitlines() if l]
725 returned_ids = [json.loads(l)["commit_id"] for l in lines]
726 assert returned_ids == ids
727
728 def test_json_flag_alias(self, tmp_path: pathlib.Path) -> None:
729 """--json is accepted and produces JSON output."""
730 root = _init_repo(tmp_path)
731 key = _make_key()
732 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
733 result = _invoke(root, "--json", commit_id)
734 assert result.exit_code == 0
735 assert "valid" in json.loads(result.stdout)
736
737
738 # ---------------------------------------------------------------------------
739 # Integration — HEAD and branch name refs
740 # ---------------------------------------------------------------------------
741
742
743 class TestRefResolution:
744 def test_head_shorthand(self, tmp_path: pathlib.Path) -> None:
745 root = _init_repo(tmp_path)
746 key = _make_key()
747 _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
748 result = _invoke(root, "HEAD", "--json")
749 assert result.exit_code == 0
750 assert json.loads(result.stdout)["valid"] is True
751
752 def test_branch_name_ref(self, tmp_path: pathlib.Path) -> None:
753 root = _init_repo(tmp_path)
754 key = _make_key()
755 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, branch="dev")
756 result = _invoke(root, "dev", "--json")
757 assert result.exit_code == 0
758 data = json.loads(result.stdout)
759 assert data["commit_id"] == commit_id
760 assert data["valid"] is True
761
762 def test_nonexistent_sha256_ref_exits_user_error(self, tmp_path: pathlib.Path) -> None:
763 """A sha256:-prefixed ID that doesn't exist in the store exits USER_ERROR."""
764 root = _init_repo(tmp_path)
765 key = _make_key()
766 _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
767 ghost = blob_id(b"ghost commit")
768 result = _invoke(root, ghost, "--json")
769 assert result.exit_code != 0
770 data = json.loads(result.stdout)
771 assert data["valid"] is False
772
773 def test_nonexistent_branch_exits_user_error(self, tmp_path: pathlib.Path) -> None:
774 root = _init_repo(tmp_path)
775 result = _invoke(root, "no-such-branch")
776 assert result.exit_code != 0
777 assert result.stdout_bytes == b"" # error went to stderr
778
779
780 # ---------------------------------------------------------------------------
781 # Integration — --strict
782 # ---------------------------------------------------------------------------
783
784
785 class TestStrictMode:
786 def test_unsigned_no_strict_exits_0(self, tmp_path: pathlib.Path) -> None:
787 root = _init_repo(tmp_path)
788 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
789 result = _invoke(root, commit_id, "--json")
790 assert result.exit_code == 0
791 assert json.loads(result.stdout)["valid"] is False
792
793 def test_unsigned_strict_exits_nonzero(self, tmp_path: pathlib.Path) -> None:
794 root = _init_repo(tmp_path)
795 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=False)
796 result = _invoke(root, commit_id, "--strict")
797 assert result.exit_code != 0
798
799 def test_signed_strict_exits_0(self, tmp_path: pathlib.Path) -> None:
800 root = _init_repo(tmp_path)
801 key = _make_key()
802 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
803 result = _invoke(root, commit_id, "--strict")
804 assert result.exit_code == 0
805
806 def test_batch_one_unsigned_strict_exits_nonzero(self, tmp_path: pathlib.Path) -> None:
807 root = _init_repo(tmp_path)
808 key = _make_key()
809 cid1, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
810 cid2, _ = _commit_files(root, {"a.py": b"x = 2\n"}, sign=False)
811 result = _invoke(root, cid1, cid2, "--strict")
812 assert result.exit_code != 0
813
814
815 # ---------------------------------------------------------------------------
816 # Integration — --check-key-status
817 # ---------------------------------------------------------------------------
818
819
820 class TestCheckKeyStatus:
821 def test_unknown_without_hub(self, tmp_path: pathlib.Path) -> None:
822 root = _init_repo(tmp_path)
823 key = _make_key()
824 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
825 result = _invoke(root, commit_id, "--check-key-status", "--json")
826 assert result.exit_code == 0
827 assert json.loads(result.stdout)["key_status"] == "unknown"
828
829
830
831 # ---------------------------------------------------------------------------
832 # Security
833 # ---------------------------------------------------------------------------
834
835
836 class TestSecurity:
837 def test_ansi_in_ref_rejected(self, tmp_path: pathlib.Path) -> None:
838 root = _init_repo(tmp_path)
839 result = _invoke(root, "\x1b[31mbad\x1b[0m")
840 assert result.exit_code != 0
841 assert result.stdout_bytes == b"" # error went to stderr
842
843 def test_null_byte_in_ref_rejected(self, tmp_path: pathlib.Path) -> None:
844 root = _init_repo(tmp_path)
845 result = _invoke(root, "sha256:abc\x00def")
846 assert result.exit_code != 0
847
848 def test_path_traversal_in_ref_rejected(self, tmp_path: pathlib.Path) -> None:
849 root = _init_repo(tmp_path)
850 result = _invoke(root, "../../etc/passwd")
851 assert result.exit_code != 0
852 assert result.stdout_bytes == b""
853
854 def test_bare_hex_ref_rejected_with_message(self, tmp_path: pathlib.Path) -> None:
855 """Bare hex without sha256: prefix → rejected; message mentions sha256:."""
856 root = _init_repo(tmp_path)
857 bare = "a" * 64
858 result = _invoke(root, bare)
859 assert result.exit_code != 0
860 assert result.stdout_bytes == b""
861 assert "sha256:" in result.stderr
862
863 def test_no_traceback_on_bad_ref(self, tmp_path: pathlib.Path) -> None:
864 root = _init_repo(tmp_path)
865 result = _invoke(root, "not-a-real-ref")
866 assert "Traceback" not in result.output
867 assert "Traceback" not in result.stderr
868
869
870 # ---------------------------------------------------------------------------
871 # Data integrity — full CLI flow
872 # ---------------------------------------------------------------------------
873
874
875 class TestDataIntegrity:
876 def test_committed_at_tamper_fails_cli(self, tmp_path: pathlib.Path) -> None:
877 """committed_at mutation detected through the full CLI verify-commit flow."""
878 root = _init_repo(tmp_path)
879 key = _make_key()
880 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
881 tampered_ts = record.committed_at + datetime.timedelta(seconds=1)
882 tampered = CommitRecord(
883 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
884 snapshot_id=record.snapshot_id, message=record.message,
885 committed_at=tampered_ts,
886 parent_commit_id=record.parent_commit_id,
887 agent_id=record.agent_id, signature=record.signature,
888 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
889 )
890 _force_write_commit(root, tampered)
891 result = _invoke(root, commit_id, "--json")
892 assert result.exit_code != 0
893 assert json.loads(result.stdout)["valid"] is False
894
895 def test_model_id_tamper_fails_cli(self, tmp_path: pathlib.Path) -> None:
896 root = _init_repo(tmp_path)
897 key = _make_key()
898 commit_id, record = _commit_files(
899 root, {"a.py": b"x = 1\n"}, sign=True, private_key=key, model_id="claude-sonnet-4-6"
900 )
901 tampered = CommitRecord(
902 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
903 snapshot_id=record.snapshot_id, message=record.message,
904 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
905 agent_id=record.agent_id, model_id="gpt-5", # tampered
906 signature=record.signature,
907 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
908 )
909 _force_write_commit(root, tampered)
910 result = _invoke(root, commit_id, "--json")
911 assert result.exit_code != 0
912 assert json.loads(result.stdout)["valid"] is False
913
914 def test_wrong_keypair_fails_cli(self, tmp_path: pathlib.Path) -> None:
915 """Public key from a different keypair → invalid through full CLI flow."""
916 root = _init_repo(tmp_path)
917 signing_key = _make_key()
918 wrong_key = _make_key()
919 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=signing_key)
920 _, wrong_pub_b64 = encode_public_key(wrong_key)
921 tampered = CommitRecord(
922 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
923 snapshot_id=record.snapshot_id, message=record.message,
924 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
925 agent_id=record.agent_id, signature=record.signature,
926 signer_public_key=wrong_pub_b64, signer_key_id=record.signer_key_id,
927 )
928 _force_write_commit(root, tampered)
929 result = _invoke(root, commit_id, "--json")
930 assert result.exit_code != 0
931 assert json.loads(result.stdout)["valid"] is False
932
933 def test_ed25519_prefix_survives_store_roundtrip(self, tmp_path: pathlib.Path) -> None:
934 """Signature and public key must keep 'ed25519:' prefix through write→read."""
935 from muse.core.store import read_commit
936 root = _init_repo(tmp_path)
937 key = _make_key()
938 commit_id, _ = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
939 reloaded = read_commit(root, commit_id)
940 assert reloaded is not None
941 assert reloaded.signature.startswith("ed25519:")
942 assert reloaded.signer_public_key.startswith("ed25519:")
943
944 def test_force_writecommit_path_matches_read_commit(self, tmp_path: pathlib.Path) -> None:
945 """_force_write_commit must write to the path that read_commit reads from."""
946 from muse.core.store import read_commit
947 root = _init_repo(tmp_path)
948 key = _make_key()
949 commit_id, record = _commit_files(root, {"a.py": b"x = 1\n"}, sign=True, private_key=key)
950 sentinel = CommitRecord(
951 commit_id=record.commit_id, repo_id=record.repo_id, created_on_branch=record.created_on_branch,
952 snapshot_id=record.snapshot_id, message=record.message,
953 committed_at=record.committed_at, parent_commit_id=record.parent_commit_id,
954 agent_id="sentinel-agent", signature=record.signature,
955 signer_public_key=record.signer_public_key, signer_key_id=record.signer_key_id,
956 )
957 _force_write_commit(root, sentinel)
958 reloaded = read_commit(root, commit_id)
959 assert reloaded is not None
960 assert reloaded.agent_id == "sentinel-agent"
961
962
963 # ---------------------------------------------------------------------------
964 # Stress
965 # ---------------------------------------------------------------------------
966
967
968 class TestStress:
969 def test_100_signed_commits_all_valid(self, tmp_path: pathlib.Path) -> None:
970 """100 signed commits all verify correctly (unit path)."""
971 from muse.cli.commands.verify_commit import _verify_one
972 root = _init_repo(tmp_path)
973 key = _make_key()
974 for i in range(100):
975 commit_id, _ = _commit_files(
976 root, {f"f{i}.py": f"v = {i}\n".encode()}, sign=True, private_key=key
977 )
978 result = _verify_one(root, commit_id)
979 assert result["valid"] is True, f"commit {i} failed"
980
981 def test_batch_50_commits_all_results_emitted(self, tmp_path: pathlib.Path) -> None:
982 """Batch of 50 commits → CLI emits exactly 50 JSON lines."""
983 root = _init_repo(tmp_path)
984 key = _make_key()
985 ids = [
986 _commit_files(root, {f"f{i}.py": f"x={i}".encode()}, sign=True, private_key=key)[0]
987 for i in range(50)
988 ]
989 result = _invoke(root, *ids, "--json")
990 assert result.exit_code == 0
991 lines = [l for l in result.stdout.strip().splitlines() if l]
992 assert len(lines) == 50
993 assert all(json.loads(l)["valid"] for l in lines)
994
995 def test_10_different_keys_all_valid(self, tmp_path: pathlib.Path) -> None:
996 """Each commit signed with a different key verifies independently."""
997 from muse.cli.commands.verify_commit import _verify_one
998 root = _init_repo(tmp_path)
999 for i in range(10):
1000 key = _make_key()
1001 commit_id, _ = _commit_files(
1002 root, {f"k{i}.py": f"v={i}".encode()}, sign=True, private_key=key
1003 )
1004 result = _verify_one(root, commit_id)
1005 assert result["valid"] is True, f"key {i} failed"
1006
1007 def test_key_status_cache_n_commits_same_key_one_call(self, tmp_path: pathlib.Path) -> None:
1008 """N commits sharing a key_id → exactly 1 network call via cache."""
1009 from muse.cli.commands.verify_commit import _verify_one
1010 root = _init_repo(tmp_path)
1011 key = _make_key()
1012 call_count = 0
1013
1014 def mock_fetch(hub_url, key_id):
1015 nonlocal call_count
1016 call_count += 1
1017 return "active"
1018
1019 cache: dict[str, str] = {}
1020 with patch("muse.cli.commands.verify_commit._fetch_key_status", side_effect=mock_fetch):
1021 for i in range(10):
1022 commit_id, _ = _commit_files(
1023 root, {f"f{i}.py": f"x={i}".encode()}, sign=True, private_key=key
1024 )
1025 _verify_one(root, commit_id, check_key_status=True, hub_url="http://fake", key_status_cache=cache)
1026
1027 assert call_count == 1, f"expected 1 network call, got {call_count}"
1028
1029
1030 # ---------------------------------------------------------------------------
1031 # Flag registration
1032 # ---------------------------------------------------------------------------
1033
1034
1035 class TestRegisterFlags:
1036 def _parse(self, *args: str):
1037 import argparse
1038 from muse.cli.commands.verify_commit import register
1039 p = argparse.ArgumentParser()
1040 sub = p.add_subparsers()
1041 register(sub)
1042 return p.parse_args(["verify-commit", *args])
1043
1044 def test_default_json_out_is_false(self) -> None:
1045 ns = self._parse("HEAD")
1046 assert ns.json_out is False
1047
1048 def test_json_flag_sets_json_out(self) -> None:
1049 ns = self._parse("HEAD", "--json")
1050 assert ns.json_out is True
1051
1052 def test_j_shorthand_sets_json_out(self) -> None:
1053 ns = self._parse("HEAD", "-j")
1054 assert ns.json_out is True
File History 3 commits
sha256:b636f72dcba9e190afb980bece906fa5b717fbde014b76ef023df8cb96e01eb9 docs: expand cache plan with all seven testing tiers and do… Sonnet 4.6 132 days ago
sha256:7f9e2ef5286aedad9c1e6011b4c46ca27f39dbdad6e3409357e36b26e46b3b7c docs: docstring sprint for-each-ref→hotspots — idiomatic ru… Sonnet 4.6 patch 138 days ago
sha256:a09b1b4f6838754495547f200aa0ce88e2f56ffc5b20b900f6f0cff2c3cdede9 fix(cursorignore): remove git-ism (.git/worktrees) Human minor 141 days ago