"""The sak_status command line, and what it is allowed to write (plan Step 20). Two properties are asserted here that no unit test can reach, because both are about the process rather than the function. **Byte-stability.** The golden file is only evidence if the same workspace and the same `--today` produce the same bytes every time, including under a different `PYTHONHASHSEED`. Python randomises string hashing per process, so a dictionary or a set that reached stdout would reorder between runs and the golden would fail intermittently -- the worst way for a determinism bug to present itself. Running the CLI twice under two seeds and comparing bytes is what turns "no dict iteration order reaches stdout" from an intention into a measurement. **The write boundary.** The read paths write nothing, and `--oppdater` is the one exception -- not a caveat, a named mode. So there are two digest tests, not one: a run without the flag leaves every byte in the workspace where it was, and a run with it changes exactly the four cached frontmatter keys and leaves `logg.jsonl`, the `sak.md` body and every other file byte-identical. Saying "the script writes nothing" without that second test is what let the write-back go unnoticed in the first place. Style note: this file follows tests/test_sak_status_silence.py. """ import hashlib import json import os import subprocess import sys import pytest import sak_status from jobbsok_lib import frontmatter as frontmatter_lib REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) CLI = os.path.join(REPO, "scripts", "sak_status.py") KORPUS = os.path.join(REPO, "tests", "fixtures", "workspace") GOLDEN = os.path.join(REPO, "tests", "golden", "sak-status-2026-09-15.json") TODAY = "2026-09-15" #: The case whose cached frontmatter is deliberately wrong (Step 19). UENIG = "2026-09-havbris-energi-as-losningsarkitekt" def kjor(*argv, **kwargs): """Run the CLI as a process and return (exit code, stdout, stderr) bytes.""" env = dict(os.environ) env.pop("JOBBSOK_WORKSPACE", None) env.pop("CLAUDE_PLUGIN_DATA", None) env.update(kwargs.get("env", {})) proc = subprocess.run( [sys.executable, CLI] + list(argv), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, ) return proc.returncode, proc.stdout, proc.stderr def digest(root): """Every file under ``root`` mapped to the sha256 of its bytes.""" ut = {} for dirpath, dirnames, filenames in os.walk(root): dirnames.sort() for navn in sorted(filenames): full = os.path.join(dirpath, navn) with open(full, "rb") as handle: ut[os.path.relpath(full, root)] = hashlib.sha256(handle.read()).hexdigest() return ut def test_the_json_output_matches_the_golden_file(golden): kode, ut, feil = kjor("--workspace", KORPUS, "--today", TODAY, "--format", "json") assert kode == 0, feil.decode("utf-8") golden(GOLDEN, ut.decode("utf-8")) def test_two_consecutive_runs_are_byte_identical(): _kode, forste, _ = kjor("--workspace", KORPUS, "--today", TODAY, "--format", "json") _kode, andre, _ = kjor("--workspace", KORPUS, "--today", TODAY, "--format", "json") assert forste == andre def test_two_different_hash_seeds_produce_the_same_bytes(): kwargs = ("--workspace", KORPUS, "--today", TODAY, "--format", "json") _kode, null, _ = kjor(*kwargs, env={"PYTHONHASHSEED": "0"}) _kode, mange, _ = kjor(*kwargs, env={"PYTHONHASHSEED": "1048573"}) assert null == mange, ( "output moved with PYTHONHASHSEED, so a dict or a set reached stdout" ) # And the text form too, which is the one the operator actually reads. tekst = ("--workspace", KORPUS, "--today", TODAY) _kode, a, _ = kjor(*tekst, env={"PYTHONHASHSEED": "0"}) _kode, b, _ = kjor(*tekst, env={"PYTHONHASHSEED": "1048573"}) assert a == b def test_omitting_workspace_is_an_error_and_never_a_guess_at_home(): kode, ut, feil = kjor("--today", TODAY) assert kode != 0 assert b"--workspace" in feil assert os.path.expanduser("~").encode("utf-8") not in ut + feil, ( "the refusal leaked a home directory; there is no default workspace" ) def test_a_traversing_case_identifier_is_refused(): kode, _ut, feil = kjor( "--workspace", KORPUS, "--today", TODAY, "--sak", "../../etc/passwd" ) assert kode != 0 assert b"../../etc/passwd" in feil def test_a_run_without_oppdater_leaves_every_byte_where_it_was(workspace): forst = digest(workspace) kode, _ut, feil = kjor("--workspace", workspace, "--today", TODAY, "--format", "json") assert kode == 0, feil.decode("utf-8") assert digest(workspace) == forst, "the read path wrote something" def test_a_run_with_oppdater_changes_only_the_four_cached_keys(workspace): sti = os.path.join(workspace, "saker", UENIG, "sak.md") with open(sti, "r", encoding="utf-8") as handle: for_meta, for_body = frontmatter_lib.parse(handle.read()) forst = digest(workspace) kode, _ut, feil = kjor("--workspace", workspace, "--today", TODAY, "--oppdater") assert kode == 0, feil.decode("utf-8") etter = digest(workspace) endrede = sorted(navn for navn in forst if forst[navn] != etter[navn]) assert endrede == [os.path.join("saker", UENIG, "sak.md")], ( "--oppdater touched %r; only the diverging case's sak.md may move" % (endrede,) ) assert sorted(etter) == sorted(forst), "--oppdater added or removed a file" with open(sti, "r", encoding="utf-8") as handle: etter_meta, etter_body = frontmatter_lib.parse(handle.read()) assert etter_body == for_body flyttet = sorted(k for k in for_meta if for_meta[k] != etter_meta.get(k)) assert flyttet == ["status", "ventende_part"] assert set(flyttet) <= set(sak_status.CACHE_KEYS) def test_check_exits_non_zero_on_the_deliberately_divergent_fixture(workspace): kode, ut, _feil = kjor("--workspace", KORPUS, "--today", TODAY, "--check") assert kode != 0 assert UENIG.encode("utf-8") in ut, "the check must name the case that diverged" kjor("--workspace", workspace, "--today", TODAY, "--oppdater") kode, _ut, _feil = kjor("--workspace", workspace, "--today", TODAY, "--check") assert kode == 0, "a workspace that has just been refreshed must check clean"