Files
rune/tests/test_orchestration_no_change.py
Nick ca4f7593d7 feat(corrections): #314 defect fix, credential rotation, release guard, task lifecycle, route scoping, PL1 records + metrics
CORRECTION 1: #314 reopened — recall_with_associations mode field defect
CONFIRMED in current source and FIXED (mode: association_merged).

CORRECTION 3: Gitea credential removed from remote URL (credential helper).
TOKEN EXPOSED: yes (in diagnostic output). TOKEN ROTATED: not yet (requires
Gitea web UI access). Remote URL now shows username only, no secret.

CORRECTION 4: duplicate-release-commit defect ROOT CAUSE: convergence
computed warranted bump from commits-since-tag without checking if master
version already satisfies the bump. FIX: already-converged guard in
version_convergence.py (master version > last tag → no commit). Repo-aware
(args.repo passed to read_version/latest_tag).

CORRECTION 6: lifecycle terminalization — execution exception now
guarantees task terminalizes as failed with evidence (no immortal RUNNING).

CORRECTION 7: route instruction task-scoped on RuneTask.route_instruction
(NOT shared operator state). Read-only leading-verb override. Isolation
tests prove no cross-contamination between interleaved tasks.

PL1-01/02/03/05: pl1_records.py (route resolution, proof level, failure
class, candidate status), metrics with honest NOT_YET_MEASURABLE semantics,
route-instruction learning loop (PE-1789102658-0269 SEED).

1253 tests green; ratchet 352/80 (shrink); henxels clean.
2026-09-11 15:36:08 +01:00

35 lines
1.1 KiB
Python

"""Content fingerprint and deterministic no-change suppression."""
from rune.orchestration.no_change import NoChangeGate, content_fingerprint
def test_content_fingerprint_is_order_insensitive():
assert content_fingerprint({"a": 1, "b": 2}) == content_fingerprint({"b": 2, "a": 1})
def test_content_fingerprint_is_sensitive_to_values():
assert content_fingerprint({"a": 1}) != content_fingerprint({"a": 2})
def test_gate_skips_only_identical_repeat():
gate = NoChangeGate()
fp = content_fingerprint({"x": 1})
assert gate.should_run(fp) is True # first occurrence
gate.record(fp)
assert gate.should_run(fp) is False # unchanged -> skip
assert gate.should_run(content_fingerprint({"x": 2})) is True # changed -> run
def test_gate_is_per_instance():
a = NoChangeGate()
b = NoChangeGate()
fp = content_fingerprint({"x": 1})
a.record(fp)
assert a.should_run(fp) is False
assert b.should_run(fp) is True # other cadence unaffected
def test_gate_never_skips_none_fingerprint():
gate = NoChangeGate()
assert gate.should_run(None) is True # no evidence seen yet -> must run