feat(tier_manager): close PARTIAL gaps — dichotomy wave

Audit 6/10 PARTIAL -> 10/10 FULL (RUST, cognition_core per the audit
alias — tier_manager's live chain is cc_loader -> libcognition_core.so).
Four kernels ported: tier_demotion_sweep (named alias of the get_tier
decision), tier_get_tier_config (warm default for unknown tiers; wire
order mirrors the oracle dict), tier_should_search, tier_should_compress
(empty-dict False default) — FFI + loader wrappers + facade delegation
with load-bearing _py fallbacks, drift-immune recency cases in the
delegation suite.

Fix-first (proven by the frozen battery): parse_strict_aware accepted
out-of-calendar timestamps (month 13, Feb 30, day 0, hour 24 with
minutes) that datetime.fromisoformat raises on — oracle falls back to
warm, kernel computed off-calendar epochs. Range validation added
(leap years, month lengths, ISO hour-24 end-of-day); recorded as quirk

Verification: frozen truth 121 cases via the shared harness,
byte-identical on repeated freeze_truth --verify; cargo battery green
(include_str! embed); clippy -D warnings clean; live parity 1720/1720
(frozen rows + seeded fuzz + config fuzz, both clocks pinned); Python
both pins green (12/12 live + RUNE_COGNITION_CORE=python); ruff clean;
collateral green with kernels resolved (shims+tier+witness 59/59,
cognition consumers 109/109). Evidence: verification/summary-tier_manager.md
+ tier-* exits/logs.
This commit is contained in:
Nick committed 2026-10-14 16:02:25 +01:00
1 parent 7e360d618d
commit e54360d0b0
23 files changed
+3899 -49

No files matched your search

+2 -1
View File
@@ -23,6 +23,7 @@
{"trap": "callable corpora cannot ride JSON truth rows", "port": "freeze a shared kind/fn/value SPEC grammar via a rig that builds real Python callables; the battery rebuilds Go tasks from the same rows (extends the memory_consolidation seam pattern)", "proved_by": "parallel_processor (2026-10-14)"},
{"trap": "threading.active_count() in oracle output is process-random (pool threads, harness state)", "port": "pin via rig patch to a constant; Go side reads the matching PP_ACTIVE_THREADS seam (default: native goroutine count)", "proved_by": "parallel_processor (2026-10-14)"},
{"trap": "epoch microseconds beyond ~2^53 (year >285 CE) lose sub-second digits when crossing f64 JSON (253402300799000001 → …799000000)", "port": "instants cross FFI as STRINGS; kernel parses i64 (si_now micros_str law)", "proved_by": "self_improve (2026-10-14)"},
{"trap": "f'{x:.0%}' scales the DOUBLE's exact decimal expansion by 100 then rounds half-even; a binary r*100.0 multiply can sit 1 ulp off the tie and round differently", "port": "Rust format!('{:.0}%') matches on exactly-representable ratios; frozen truth pins ties with power-of-two denominators only (1/8 → 12.5% → '12%')", "proved_by": "self_improve (2026-10-14)"}
{"trap": "f'{x:.0%}' scales the DOUBLE's exact decimal expansion by 100 then rounds half-even; a binary r*100.0 multiply can sit 1 ulp off the tie and round differently", "port": "Rust format!('{:.0}%') matches on exactly-representable ratios; frozen truth pins ties with power-of-two denominators only (1/8 → 12.5% → '12%')", "proved_by": "self_improve (2026-10-14)"},
{"trap": "datetime.fromisoformat raises on out-of-calendar fields (month 13, Feb 30, day 0, hour 24 with nonzero minutes)", "port": "Rust fixed-position parsers must validate ranges (leap-year month lengths; h<=23 or ISO hour-24 end-of-day with zero min/sec) or they compute off-calendar epochs the oracle never sees", "proved_by": "tier_manager (parse_strict_aware crash class, 2026-10-14)"}
]
}
+6 -6
View File
@@ -2,16 +2,16 @@
_Regenerate with `python3 scripts/dichotomy_audit.py --write`. A module is FULL only when 80%+ of its Python functions have name-preserving counterparts in the Go/Rust implementation — directories without the functions are facades and count as NOT TOUCHED._
**FULL completion: 61%** (117/192 runtime modules at FULL)
**FULL completion: 61%** (118/192 runtime modules at FULL)
Function-level detail: 73% (1674/2288 runtime functions matched) — secondary; includes in-flight work
Function-level detail: 73% (1678/2288 runtime functions matched) — secondary; includes in-flight work
| Status | Modules | Lines | Meaning |
|---|---|---|---|
| FULL | 117 | 48586 | 80%+ of functions ported |
| PARTIAL | 36 | 15408 | 20–80% — real logic exists, gaps named below |
| FULL | 118 | 48886 | 80%+ of functions ported |
| PARTIAL | 35 | 15146 | 20–80% — real logic exists, gaps named below |
| NOT TOUCHED | 39 | 11471 | no name-preserving implementation |
| Total runtime | 192 | 75465 | |
| Total runtime | 192 | 75503 | |
## NOT TOUCHED — the port queue, in priority order (largest first)
@@ -75,7 +75,6 @@ Function-level detail: 73% (1674/2288 runtime functions matched) — secondary;
| pins | 282 | 7/11 | _store_path, _detail_blob, unpin, list_pins |
| prompt_sync | 487 | 11/15 | _now, _rust_available, get_store, main |
| task_gate | 301 | 5/9 | _tg_core, _now, list_gates, main |
| tier_manager | 262 | 6/10 | demotion_sweep, get_tier_config, should_search, should_compress |
| connection_pool | 226 | 7/10 | get_pool, _kernel_state, _get_connection_core |
| construction_activation | 237 | 1/4 | _scaffold_for, _auto_structural_awareness, dispatch_from_decision |
| dependency_tracker | 202 | 2/5 | check_propagation, get_full_map, main |
@@ -175,6 +174,7 @@ Function-level detail: 73% (1674/2288 runtime functions matched) — secondary;
| lexicon_evolution | 304 | 7/8 | unclassified |
| event_envelope | 303 | 8/8 | GO |
| stage_guards | 303 | 9/9 | GO |
| tier_manager | 300 | 10/10 | RUST |
| message_graph | 295 | 12/13 | unclassified |
| toolchain | 295 | 5/6 | RUST |
| tiered_executor | 291 | 8/8 | GO |
+197
View File
@@ -0,0 +1,197 @@
#!/usr/bin/env python3
"""check_tier_parity.py — LIVE parity for the tier_manager gap-close
(dichotomy wave, worktree rune-wave-cz-db).
Three modes in one process:
A. frozen kernel rows — every frozen_tier_methods.json row replayed
through the LIVE cc_loader wrappers (the real delegation stack) and
compared byte-strictly to the frozen oracle expectation.
B. seeded fuzz over the ENTRIES surface — 400 random entries
(wash_count bool/int/float/None/missing, last_accessed normal/
offset/naive/malformed/invalid-calendar/typed-garbage, rock_status
variants) through the live public methods vs the oracle bodies, with
BOTH clocks pinned to the same instant so boundary classes align
exactly (kernel receives now=NOW_Z; the oracle datetime patched).
C. config-surface fuzz — get_tier_config / should_search /
should_compress over hot/warm/cold/unknown/empty/unicode tiers.
Exit 0 only on full agreement. Evidence: verification/tier-live-parity.log.
"""
from __future__ import annotations
import json
import os
import random
import sys
from datetime import datetime, timezone
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "src"))
os.environ.pop("RUNE_COGNITION_CORE", None) # delegation must be LIVE
import rune.tier_manager as tm # noqa: E402
from rune import cc_loader as _cl # noqa: E402
NOW_Z = "2026-10-14T09:00:00Z"
# Pin BOTH clocks to the same instant (kernel: now argument via the
# patched _py_core_now; oracle: the module datetime).
_PINNED_DT = datetime(2026, 10, 14, 9, 0, 0, tzinfo=timezone.utc)
class _FrozenDatetime(datetime):
@classmethod
def now(cls, tz=None): # noqa: ARG003
return _PINNED_DT
tm.datetime = _FrozenDatetime
tm._py_core_now = lambda: NOW_Z # type: ignore[method-assign]
def _fail(msg: str) -> None:
print("FAIL:", msg)
sys.exit(1)
CHECKED = 0
def _ok():
global CHECKED
CHECKED += 1
def _config_surface_check(tier: str, oracle_fn, live_fn) -> None:
got = live_fn(tier)
want = oracle_fn(tier)
if got != want:
_fail(f"{live_fn.__name__}({tier!r}): kernel {got!r} != oracle {want!r}")
_ok()
def run_frozen_rows() -> None:
path = REPO / "src/rust/cognition_core/src/frozen_tier_methods.json"
rows = json.loads(path.read_text())
if len(rows) < 60:
_fail(f"frozen methods rows vanished: {len(rows)}")
for row in rows:
kernel, args, expect = row["kernel"], row["args"], row["expect"]
name = row.get("name", "")
if kernel in ("tier_get",):
got = _cl.tier_get(args[0], args[3], args[1], args[2])
elif kernel == "tier_promote":
got = _cl.tier_promote(args[0], args[3], args[1], args[2])
elif kernel == "tier_demote":
got = _cl.tier_demote(args[0], args[3], args[1], args[2])
elif kernel == "tier_demotion_sweep":
got = _cl.tier_demotion_sweep(args[0], args[3], args[1], args[2])
elif kernel == "tier_get_tier_config":
got = _cl.tier_get_tier_config(args[0])
elif kernel == "tier_should_search":
got = _cl.tier_should_search(args[0])
elif kernel == "tier_should_compress":
got = _cl.tier_should_compress(args[0])
else:
_fail(f"unknown kernel in methods file: {kernel}")
if got != expect:
_fail(f"{kernel}/{name}: live {got!r} != frozen {expect!r}")
_ok()
WASH_POOL = [0, 2, 19, 19.999, 20, 25, -5, True, False, None]
TS_POOL = [
"2026-10-08T09:00:00Z", # 6d → hot
"2026-10-07T09:00:01Z", # 1s under the 7d boundary
"2026-10-07T09:00:00Z", # exact 7d boundary → warm
"2026-09-24T09:00:00Z", # 20d → warm
"2026-09-14T09:00:00Z", # exact 30d boundary → cold
"2026-09-04T09:00:00Z", # 40d → cold
"2026-10-13T14:30:00+05:30", # tz +05:30 → hot
"2026-09-24T09:00:00-05:00", # tz −05:00 → warm
"2028-02-29T09:00:00Z", # valid leap-day future → hot
"2024-02-29T00:00:00Z", # valid leap-day past → cold
"2026-10-13T24:00:00Z", # ISO end-of-day, zeros → hot
"2026-10-05T09:00:00", # naive → refuse
"junk", "junkjunkjunkjunkjunk", # malformed → refuse
"2026-13-01T00:00:00Z", # month 13 → raise
"2026-10-00T00:00:00Z", # day 0 → raise
"2026-02-30T00:00:00Z", # Feb 30 → raise
"2026-04-31T00:00:00Z", # April 31 → raise
"2026-10-13T24:30:00Z", # hour 24 nonzero minutes → raise
"2026-10-13T00:60:00Z", # minute 60 → raise
"2026-10-13T23:59:60Z", # leap second → raise
"2026-10-13T10:61:00Z", # minute 61 → raise
"", None, 12345, {}, # typed-garbage / falsy / refusal classes
]
ROCK_POOL = [None, "rock", "rockish", "washable", "", None]
def run_fuzz() -> None:
rng = random.Random(2026 - 10 - 14)
oracle, live = tm.TierManager(), tm.TierManager()
for i in range(400):
entry = {}
if rng.random() < 0.9:
entry["wash_count"] = rng.choice(WASH_POOL)
if rng.random() < 0.9:
entry["last_accessed"] = rng.choice(TS_POOL)
if rng.random() < 0.9:
entry["rock_status"] = rng.choice(ROCK_POOL)
# demotion_sweep's oracle body IS get_tier (no _py_ twin exists)
for ofn, lfn in (("get_tier", live.get_tier),
("promote", live.promote),
("demote", live.demote)):
want, got = getattr(oracle, f"_py_{ofn}")(entry), lfn(entry)
if got != want:
_fail(f"fuzz[{i}] {ofn}: live {got!r} != oracle {want!r} "
f"entry={entry!r}")
_ok()
want, got = oracle.get_tier(entry), live.demotion_sweep(entry)
if got != want:
_fail(f"fuzz[{i}] demotion_sweep: live {got!r} != oracle "
f"{want!r} entry={entry!r}")
_ok()
def run_config_fuzz() -> None:
oracle, live = tm.TierManager(), tm.TierManager()
tier_pool = ["hot", "warm", "cold", "unknown", "", "HOT", "hot ",
"warm\n", "cold\t", "rook", "wärm", "холодный", "温度",
"h" * 200, "Cold"]
for tier in tier_pool:
want = oracle.get_tier_config(tier)
got = live.get_tier_config(tier)
if got != want or list(got) != ["indexed", "cached", "compressed",
"searched", "description"]:
_fail(f"cfgfuzz get_tier_config({tier!r}): live {got!r} != "
f"oracle {want!r}")
_ok()
if live.should_search(tier) != oracle.should_search(tier):
_fail(f"cfgfuzz should_search({tier!r}) diverged")
_ok()
if live.should_compress(tier) != oracle.should_compress(tier):
_fail(f"cfgfuzz should_compress({tier!r}) diverged")
_ok()
def main() -> int:
if _cl.available() is False:
print("FAIL: cognition_core .so not built at", _cl._LIB_PATH)
return 1
# Delegation must be LIVE — the kernel path serves a probe call.
probe = _cl.tier_should_search("hot")
if probe is not True:
_fail("kernel probe call failed")
run_frozen_rows()
run_fuzz()
run_config_fuzz()
print(f"OK: tier live parity — {CHECKED} checks, 0 divergences "
f"(frozen rows + seeded fuzz + config fuzz, both clocks pinned)")
return 0
if __name__ == "__main__":
sys.exit(main())
+239
View File
@@ -0,0 +1,239 @@
#!/usr/bin/env python3
"""gen_tier_truth.py — freeze oracle truth for the tier_manager gap-close
(dichotomy wave, worktree rune-wave-cz-db).
Emits TWO artifacts into src/rust/cognition_core/src/ (both embedded
VERBATIM in the cfg(test) tier_battery):
frozen_tier_truth.json — the shared scripts/freeze_truth.py harness
schema ({"frozen_now", "cases"} envelope;
recv-form method cases). Re-freezable against
the live oracle byte-identically:
RUNE_COGNITION_CORE=python PYTHONPATH=src python3 scripts/freeze_truth.py \
--verify src/rust/cognition_core/src/frozen_tier_truth.json \
--module rune.tier_manager
(RUNE_COGNITION_CORE=python is the real oracle
pin here: tier_manager's _core probe honors the
SHARED cognition pin, and the harness's own
RUNE_TIER_MANAGER_CORE derivation is a no-op.)
frozen_tier_methods.json — kernel-shaped truth {"kernel","args","expect",
"name"} for the Rust battery replay, captured
from the oracle bodies under the envelope
clock (the kernels take `now` as an argument
per the no-clock law).
Case matrix: wash-count thresholds (incl. >=20 boundary), recency brackets
(6d hot / 7d-exact warm boundary / 20d warm / 30d-exact cold / 40d cold),
tz-offset timestamps, naive/malformed/typed refusals, bool wash_count
truthiness, and the calendar-range crash class (month 13, day 0, Feb 30,
hour 24, minute 61) — where datetime.fromisoformat raises and the tier
falls back to warm. The kernel's parse_strict_aware gained fromisoformat
range validation in this wave so the crash class matches on BOTH sides.
Corpora law: no sub-second timestamps — the W3.4 kernel parser is
seconds-resolution (fractional seconds dropped), so exact-boundary rows
with microseconds are excluded as a documented divergence kept out of truth.
"""
from __future__ import annotations
import json
import sys
from datetime import datetime, timezone
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "scripts"))
sys.path.insert(0, str(REPO / "src"))
import os
os.environ["RUNE_COGNITION_CORE"] = "python" # the SHARED oracle pin
import rune.tier_manager as tm # noqa: E402
from freeze_truth import freeze, write, write_envelope # noqa: E402
FROZEN_NOW = "2026-10-14T09:00:00"
NOW_Z = "2026-10-14T09:00:00Z" # kernel `now` argument (same instant, Z form)
HOT, WARM = 7.0, 30.0
# Pinned clock for the kernel-shaped capture (mirror of the harness
# _frozen_clock so both files freeze the same instant).
_PINNED_DT = datetime(2026, 10, 14, 9, 0, 0, tzinfo=timezone.utc)
class _FrozenDatetime(datetime):
@classmethod
def now(cls, tz=None): # noqa: ARG003
return _PINNED_DT
tm.datetime = _FrozenDatetime
TMGR = tm.TierManager()
ENTRIES: list[tuple[str, dict]] = [
("wash25hot", {"wash_count": 25}),
("recent6d", {"wash_count": 2, "last_accessed": "2026-10-08T09:00:00Z"}),
("edge1sunder", {"wash_count": 2, "last_accessed": "2026-10-07T09:00:01Z"}),
("exact7d", {"wash_count": 2, "last_accessed": "2026-10-07T09:00:00Z"}),
("warm20d", {"wash_count": 2, "last_accessed": "2026-09-24T09:00:00Z"}),
("exact30d", {"wash_count": 2, "last_accessed": "2026-09-14T09:00:00Z"}),
("cold40d", {"wash_count": 2, "last_accessed": "2026-09-04T09:00:00Z"}),
("tzplus", {"wash_count": 2, "last_accessed": "2026-10-13T14:30:00+05:30"}),
("tzminus", {"wash_count": 2, "last_accessed": "2026-09-24T09:00:00-05:00"}),
("naive", {"wash_count": 2, "last_accessed": "2026-10-05T09:00:00"}),
("junk", {"wash_count": 2, "last_accessed": "junk"}),
("junk19", {"wash_count": 2, "last_accessed": "junkjunkjunkjunkjunk"}),
("month13", {"wash_count": 2, "last_accessed": "2026-13-01T00:00:00Z"}),
("day0", {"wash_count": 2, "last_accessed": "2026-10-00T00:00:00Z"}),
("feb30", {"wash_count": 2, "last_accessed": "2026-02-30T00:00:00Z"}),
("feb29leap", {"wash_count": 2, "last_accessed": "2028-02-29T09:00:00Z"}),
("feb29leap2024", {"wash_count": 2, "last_accessed": "2024-02-29T00:00:00Z"}),
("hour24", {"wash_count": 2, "last_accessed": "2026-10-13T24:00:00Z"}),
("hour24nonzero", {"wash_count": 2, "last_accessed": "2026-10-13T24:30:00Z"}),
("min61", {"wash_count": 2, "last_accessed": "2026-10-13T10:61:00Z"}),
("min60", {"wash_count": 2, "last_accessed": "2026-10-13T00:60:00Z"}),
("sec60", {"wash_count": 2, "last_accessed": "2026-10-13T23:59:60Z"}),
("apr31", {"wash_count": 2, "last_accessed": "2026-04-31T00:00:00Z"}),
("wash19_999", {"wash_count": 19.999}),
("wash20boundary", {"wash_count": 20}),
("wash_bool", {"wash_count": True}),
("wash_neg", {"wash_count": -5}),
("nolast", {"wash_count": 2}),
("rockhot", {"wash_count": 25, "rock_status": "rock"}),
("rockish", {"rock_status": "rockish"}),
("rocknullts", {"wash_count": 0, "rock_status": "rock", "last_accessed": None}),
("lastnone", {"wash_count": 2, "last_accessed": None}),
("lastint", {"wash_count": 2, "last_accessed": 12345}),
("lastempty", {"wash_count": 2, "last_accessed": ""}),
]
BY_NAME = {name: entry for name, entry in ENTRIES}
# The oracle tier PER ENTRY (pinned clock) — self-check of the matrix.
EXPECTED_TIERS = {
"wash25hot": "hot", "recent6d": "hot", "edge1sunder": "hot",
"exact7d": "warm", "warm20d": "warm", "exact30d": "cold",
"cold40d": "cold", "tzplus": "hot", "tzminus": "warm", "naive": "warm",
"junk": "warm", "junk19": "warm", "month13": "warm", "day0": "warm",
"feb30": "warm", "feb29leap": "hot", "feb29leap2024": "cold",
"hour24": "hot", "hour24nonzero": "warm", "min61": "warm", "min60": "warm",
"sec60": "warm", "apr31": "warm",
"wash19_999": "warm", "wash20boundary": "hot", "wash_bool": "warm",
"wash_neg": "warm", "nolast": "warm", "rockhot": "hot", "rockish": "warm",
"rocknullts": "hot", "lastnone": "warm", "lastint": "warm", "lastempty": "warm",
}
def oracle_tier(name: str) -> str:
return TMGR._py_get_tier(BY_NAME[name])
def _self_check() -> None:
for name, want in EXPECTED_TIERS.items():
got = oracle_tier(name)
assert got == want, f"{name}: oracle {got!r} != matrix {want!r}"
def _recv_case(fn: str, name: str) -> dict:
return {"fn": f"TierManager.{fn}", "recv": {"cls": "TierManager"},
"args": [BY_NAME[name]], "kwargs": {}}
def _config_case(fn: str, tier: str) -> dict:
return {"fn": f"TierManager.{fn}", "recv": {"cls": "TierManager"},
"args": [tier], "kwargs": {}}
PROMOTE_DEMOTE_NAMES = ("wash25hot", "recent6d", "exact7d", "warm20d",
"exact30d", "cold40d", "rockhot", "naive")
PUBLIC_DEMOTE_NAMES = ("wash25hot", "warm20d", "cold40d", "rockhot",
"naive", "lastint")
SWEEP_NAMES = ("wash25hot", "recent6d", "exact7d", "warm20d", "cold40d",
"rockhot", "naive", "junk", "wash20boundary", "wash19_999")
TIERS = ("hot", "warm", "cold", "unknown", "")
def build_harness_cases() -> list:
cases = []
for name, _ in ENTRIES: # oracle body + public surface, every entry
cases.append(_recv_case("_py_get_tier", name))
cases.append(_recv_case("get_tier", name))
for name in PROMOTE_DEMOTE_NAMES:
cases.append(_recv_case("_py_promote", name))
cases.append(_recv_case("_py_demote", name))
for name in PUBLIC_DEMOTE_NAMES:
cases.append(_recv_case("promote", name))
cases.append(_recv_case("demote", name))
for name in SWEEP_NAMES:
cases.append(_recv_case("demotion_sweep", name))
for tier in TIERS:
cases.append(_config_case("get_tier_config", tier))
for tier in TIERS:
cases.append(_config_case("should_search", tier))
cases.append(_config_case("should_compress", tier))
return cases
def _promote_of(name: str) -> str:
cur = oracle_tier(name)
if cur == "cold":
return "warm"
return "hot" # warm already-hot both land hot (oracle ladder)
def _demote_of(name: str) -> str:
if BY_NAME[name].get("rock_status") == "rock":
return "hot" # rock never demotes (oracle short-circuit)
cur = oracle_tier(name)
return {"hot": "warm", "warm": "cold"}.get(cur, "cold")
def kernel_rows() -> list[dict]:
rows = []
def row(kernel: str, name: str, args: list, expect):
rows.append({"kernel": kernel, "args": args, "expect": expect,
"name": name})
def now_args(name: str) -> list:
return [BY_NAME[name], HOT, WARM, NOW_Z]
for name, _ in ENTRIES: # the tier decision kernel, every entry
row("tier_get", name, now_args(name), oracle_tier(name))
for name in PROMOTE_DEMOTE_NAMES:
row("tier_promote", name, now_args(name), _promote_of(name))
row("tier_demote", name, now_args(name), _demote_of(name))
for name in SWEEP_NAMES:
row("tier_demotion_sweep", name, now_args(name), oracle_tier(name))
for tier in TIERS:
cfg = tm.TIER_CONFIG.get(tier, tm.TIER_CONFIG["warm"])
row("tier_get_tier_config", f"tier={tier!r}", [tier], dict(cfg))
row("tier_should_search", f"tier={tier!r}",
[tier], tm.TIER_CONFIG.get(tier, {}).get("searched", False))
row("tier_should_compress", f"tier={tier!r}",
[tier], tm.TIER_CONFIG.get(tier, {}).get("compressed", False))
return rows
def main() -> int:
_self_check()
cases = build_harness_cases()
truth = freeze("rune.tier_manager", cases, oracle_module="rune.tier_manager")
write_envelope(FROZEN_NOW, truth,
REPO / "src/rust/cognition_core/src/frozen_tier_truth.json")
rows = kernel_rows()
write(rows, REPO / "src/rust/cognition_core/src/frozen_tier_methods.json")
print(f"harness cases: {len(truth)}")
print(f"kernel rows: {len(rows)}")
print("self-check:", json.dumps(EXPECTED_TIERS))
return 0
if __name__ == "__main__":
sys.exit(main())
+27 -1
View File
@@ -54,7 +54,9 @@ def _load() -> ctypes.CDLL:
"cc_persona_lex", "cc_persona_overlap", "cc_persona_decide",
"cc_drift_check", "cc_identity_prompt", "cc_growth_near_dup",
"cc_growth_profile", "cc_pins_recall", "cc_tier_get",
"cc_tier_promote", "cc_tier_demote", "cc_witness_extract_topic",
"cc_tier_promote", "cc_tier_demote", "cc_tier_demotion_sweep",
"cc_tier_get_tier_config", "cc_tier_should_search",
"cc_tier_should_compress", "cc_witness_extract_topic",
"cc_witness_signals", "cc_safety_get_params",
"cc_safety_update_pattern", "cc_abstraction_extract_facts",
"cc_consolidation_memory", "cc_consolidation_neuron",
@@ -296,6 +298,30 @@ def tier_demote(entry: dict, now: str, hot_days: float = 7.0,
"hot_days": hot_days, "warm_days": warm_days})
# ── tier_manager gap-close kernels (dichotomy wave) ─────────────────────────
def tier_demotion_sweep(entry: dict, now: str, hot_days: float = 7.0,
warm_days: float = 30.0) -> str:
return _call("cc_tier_demotion_sweep", {"entry": entry, "now": now,
"hot_days": hot_days,
"warm_days": warm_days})
def tier_get_tier_config(tier: str) -> dict:
"""The TIER_CONFIG entry for the tier (warm default for unknowns); wire
order mirrors the oracle dict (indexed, cached, compressed, searched,
description)."""
return _call("cc_tier_get_tier_config", {"tier": tier})
def tier_should_search(tier: str) -> bool:
return bool(_call("cc_tier_should_search", {"tier": tier}))
def tier_should_compress(tier: str) -> bool:
return bool(_call("cc_tier_should_compress", {"tier": tier}))
def witness_extract_topic(text: str, stopwords: list) -> list:
return _call("cc_witness_extract_topic",
{"text": text, "stopwords": stopwords})
+42 -4
View File
@@ -195,19 +195,57 @@ class TierManager:
"""Sweep an entry for demotion. Returns the tier it should be in.
Same as get_tier but explicitly named for the sweep operation.
"""
Delegates to the Rust kernel when built (Python oracle below)."""
core = _core()
if core is not None:
try:
from rune import cc_loader as _cl
raw = _cl.tier_demotion_sweep(entry, _py_core_now(),
float(HOT_THRESHOLD),
float(WARM_THRESHOLD))
return str(raw)
except Exception: # noqa: BLE001, S110 — kernel failure → oracle fallback, intentional silence
pass
return self.get_tier(entry)
def get_tier_config(self, tier: str) -> dict:
"""Get the configuration for a tier."""
"""Get the configuration for a tier.
Delegates to the Rust kernel when built (Python oracle below)."""
core = _core()
if core is not None:
try:
from rune import cc_loader as _cl
return dict(_cl.tier_get_tier_config(tier))
except Exception: # noqa: BLE001, S110 — kernel failure → oracle fallback, intentional silence
pass
return TIER_CONFIG.get(tier, TIER_CONFIG["warm"])
def should_search(self, tier: str) -> bool:
"""Whether entries in this tier should be searched."""
"""Whether entries in this tier should be searched.
Delegates to the Rust kernel when built (Python oracle below)."""
core = _core()
if core is not None:
try:
from rune import cc_loader as _cl
return bool(_cl.tier_should_search(tier))
except Exception: # noqa: BLE001, S110 — kernel failure → oracle fallback, intentional silence
pass
return TIER_CONFIG.get(tier, {}).get("searched", False)
def should_compress(self, tier: str) -> bool:
"""Whether entries in this tier should be compressed."""
"""Whether entries in this tier should be compressed.
Delegates to the Rust kernel when built (Python oracle below)."""
core = _core()
if core is not None:
try:
from rune import cc_loader as _cl
return bool(_cl.tier_should_compress(tier))
except Exception: # noqa: BLE001, S110 — kernel failure → oracle fallback, intentional silence
pass
return TIER_CONFIG.get(tier, {}).get("compressed", False)
+96 -19
View File
@@ -477,10 +477,7 @@ fn prefixed(table: &Json, prefix: &str) -> Vec<Json> {
pub fn _pattern_triples() -> Json {
// DRIFT = announcement + pronoun, in that order (the fallback's loop
// order — the frozen truth freezes exactly this sequence).
let drift: Vec<Json> = match (
_announcement_patterns(),
_pronoun_patterns(),
) {
let drift: Vec<Json> = match (_announcement_patterns(), _pronoun_patterns()) {
(Json::Arr(a), Json::Arr(p)) => a.into_iter().chain(p).collect(),
(Json::Arr(a), _) => a,
(_, Json::Arr(p)) => p,
@@ -849,6 +846,35 @@ pub fn parse_strict_aware(s: &str) -> Option<f64> {
num(14, 16)?,
num(17, 19)?,
);
// Calendar-range parity with datetime.fromisoformat: out-of-range
// fields raise in the oracle (fallback → warm here), a fixed-position
// parser without validation would happily compute off-calendar epochs.
// fromisoformat special case: hour 24 is ISO end-of-day — valid ONLY
// with zero minutes/seconds (next-day midnight; days*86400 + 24*3600
// lands there naturally).
let leap = (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
let month_len = match mo {
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
4 | 6 | 9 | 11 => 30,
2 => {
if leap {
29
} else {
28
}
}
_ => 0,
};
if month_len == 0 || d < 1 || d > month_len {
return None;
}
if h == 24 {
if mi != 0 || se != 0 {
return None;
}
} else if h > 23 || mi > 59 || se > 59 {
return None;
}
let mut i = 19;
while i < b.len() && b[i] != b'Z' && b[i] != b'+' && b[i] != b'-' {
i += 1;
@@ -915,6 +941,54 @@ pub fn tier_demote(entry: &Json, hot_days: f64, warm_days: f64, now: &str) -> Js
})
}
// ── tier_manager gap-close kernels (dichotomy wave) ─────────────────────────
/// demotion_sweep: the sweep operation's named alias of the get_tier
/// decision (oracle docstring: "Same as get_tier but explicitly named
/// for the sweep operation") — thresholds + now arrive as inputs.
pub fn tier_demotion_sweep(entry: &Json, hot_days: f64, warm_days: f64, now: &str) -> Json {
tier_get(entry, hot_days, warm_days, now)
}
/// get_tier_config: the tier_manager TIER_CONFIG lookup with the warm
/// default for unknown tiers. Pair order mirrors the oracle dict
/// insertion order (indexed, cached, compressed, searched, description)
/// — the envelope wire order is what the Python facade hands back.
pub fn tier_get_tier_config(tier: &str) -> Json {
let fields = match tier {
"hot" => (true, true, false, true, "Instant access, indexed, cached"),
"cold" => (
false,
false,
true,
false,
"Slow access, compressed, not searched",
),
// warm — and every tier the oracle dict doesn't define, because
// TIER_CONFIG.get(tier, TIER_CONFIG["warm"]) defaults to warm.
_ => (true, false, false, true, "Fast access, indexed, not cached"),
};
Json::Obj(vec![
("indexed".to_string(), Json::Bool(fields.0)),
("cached".to_string(), Json::Bool(fields.1)),
("compressed".to_string(), Json::Bool(fields.2)),
("searched".to_string(), Json::Bool(fields.3)),
("description".to_string(), Json::Str(fields.4.into())),
])
}
/// should_search: TIER_CONFIG["searched"] projection; unknown tiers
/// default the empty dict ({"searched": False}) per the oracle.
pub fn tier_should_search(tier: &str) -> Json {
Json::Bool(matches!(tier, "hot" | "warm"))
}
/// should_compress: TIER_CONFIG["compressed"] projection; unknown tiers
/// default the empty dict ({"compressed": False}) per the oracle.
pub fn tier_should_compress(tier: &str) -> Json {
Json::Bool(tier == "cold")
}
// ── witness kernels (W3.4) ──────────────────────────────────────────────────
pub fn witness_extract_topic(text: &str, stopwords: &[Json], cap: usize) -> Json {
@@ -1776,9 +1850,7 @@ pub fn reflect(deltas: &[Json]) -> Vec<Json> {
/// {"params": {change, evidence, confidence, target}} — the facade journals
/// the params through apply_one.
pub fn apply(delta_json: &str) -> Json {
let err = |msg: String| {
Json::Obj(vec![("error".into(), Json::Str(msg))])
};
let err = |msg: String| Json::Obj(vec![("error".into(), Json::Str(msg))]);
let d = match pyjson::parse(delta_json) {
Ok(v) => v,
Err(_) => return err("invalid delta json".to_string()),
@@ -1882,15 +1954,12 @@ pub fn ctx_budget(window: f64, local: bool, task_kind: &str) -> f64 {
/// Oracle _KEYWORD_STOPWORDS, sorted (the W3.4 gather-seam table).
pub const SAFETY_KEYWORD_STOPWORDS: [&str; 72] = [
"about", "all", "also", "and", "are", "been", "but", "can",
"come", "could", "day", "did", "each", "for", "from", "get",
"had", "has", "have", "her", "him", "his", "how", "into",
"its", "just", "let", "like", "make", "may", "more", "new",
"not", "now", "old", "one", "other", "our", "out", "over",
"said", "say", "see", "she", "some", "such", "take", "than",
"that", "the", "their", "them", "then", "there", "these", "they",
"this", "time", "too", "use", "very", "was", "way", "what",
"when", "which", "who", "will", "with", "would", "year", "you",
"about", "all", "also", "and", "are", "been", "but", "can", "come", "could", "day", "did",
"each", "for", "from", "get", "had", "has", "have", "her", "him", "his", "how", "into", "its",
"just", "let", "like", "make", "may", "more", "new", "not", "now", "old", "one", "other",
"our", "out", "over", "said", "say", "see", "she", "some", "such", "take", "than", "that",
"the", "their", "them", "then", "there", "these", "they", "this", "time", "too", "use", "very",
"was", "way", "what", "when", "which", "who", "will", "with", "would", "year", "you",
];
/// Oracle ESCALATION_TIERS (tier, temperature, prefix, suffix).
@@ -2041,7 +2110,9 @@ pub fn safety_is_refusal(response: &str) -> bool {
fn regex_cached() -> &'static regex::Regex {
use std::sync::OnceLock;
static RE: OnceLock<regex::Regex> = OnceLock::new();
RE.get_or_init(|| regex::Regex::new(&format!("(?i){SAFETY_REFUSAL_RE}")).expect("refusal regex"))
RE.get_or_init(|| {
regex::Regex::new(&format!("(?i){SAFETY_REFUSAL_RE}")).expect("refusal regex")
})
}
/// Oracle _extract_keywords: [a-z]{4,} runs (ASCII, Python re semantics),
@@ -2233,7 +2304,10 @@ fn update_pattern(
_ => 0.0,
})
.unwrap_or(0.0);
if let Some(ix) = stats_pairs.iter().position(|(k, _)| k == "patterns_learned") {
if let Some(ix) = stats_pairs
.iter()
.position(|(k, _)| k == "patterns_learned")
{
stats_pairs[ix].1 = Json::Num(cur + 1.0);
} else {
stats_pairs.push(("patterns_learned".into(), Json::Num(1.0)));
@@ -2250,7 +2324,10 @@ pub fn safety_save(patterns: &[Json], stats: &Json) -> Json {
"patterns_json".into(),
Json::Str(crate::pyjson::dump_indent2(&Json::Arr(patterns.to_vec()))),
),
("stats_json".into(), Json::Str(crate::pyjson::dump_indent2(stats))),
(
"stats_json".into(),
Json::Str(crate::pyjson::dump_indent2(stats)),
),
])
}
@@ -0,0 +1,981 @@
[
{
"kernel": "tier_get",
"args": [
{
"wash_count": 25
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "wash25hot"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-08T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "recent6d"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-07T09:00:01Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "edge1sunder"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-07T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "exact7d"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-24T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "warm20d"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-14T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "exact30d"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-04T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "cold40d"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T14:30:00+05:30"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "tzplus"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-24T09:00:00-05:00"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "tzminus"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-05T09:00:00"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "naive"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "junk"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "junk"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "junkjunkjunkjunkjunk"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "junk19"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-13-01T00:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "month13"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-00T00:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "day0"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-02-30T00:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "feb30"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2028-02-29T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "feb29leap"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2024-02-29T00:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "feb29leap2024"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T24:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "hour24"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T24:30:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "hour24nonzero"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T10:61:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "min61"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T00:60:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "min60"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-13T23:59:60Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "sec60"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-04-31T00:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "apr31"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 19.999
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "wash19_999"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 20
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "wash20boundary"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": true
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "wash_bool"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": -5
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "wash_neg"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "nolast"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 25,
"rock_status": "rock"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "rockhot"
},
{
"kernel": "tier_get",
"args": [
{
"rock_status": "rockish"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "rockish"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 0,
"rock_status": "rock",
"last_accessed": null
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "rocknullts"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": null
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "lastnone"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": 12345
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "lastint"
},
{
"kernel": "tier_get",
"args": [
{
"wash_count": 2,
"last_accessed": ""
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "lastempty"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 25
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "wash25hot"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 25
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "wash25hot"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-08T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "recent6d"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-08T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "recent6d"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-07T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "exact7d"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-07T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "exact7d"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-24T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "warm20d"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-24T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "warm20d"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-14T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "exact30d"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-14T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "exact30d"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-04T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "cold40d"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-04T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "cold40d"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 25,
"rock_status": "rock"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "rockhot"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 25,
"rock_status": "rock"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "rockhot"
},
{
"kernel": "tier_promote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-05T09:00:00"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "naive"
},
{
"kernel": "tier_demote",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-05T09:00:00"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "naive"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 25
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "wash25hot"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-08T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "recent6d"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-07T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "exact7d"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-24T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "warm20d"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-09-04T09:00:00Z"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "cold",
"name": "cold40d"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 25,
"rock_status": "rock"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "rockhot"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "2026-10-05T09:00:00"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "naive"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 2,
"last_accessed": "junk"
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "junk"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 20
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "hot",
"name": "wash20boundary"
},
{
"kernel": "tier_demotion_sweep",
"args": [
{
"wash_count": 19.999
},
7.0,
30.0,
"2026-10-14T09:00:00Z"
],
"expect": "warm",
"name": "wash19_999"
},
{
"kernel": "tier_get_tier_config",
"args": [
"hot"
],
"expect": {
"indexed": true,
"cached": true,
"compressed": false,
"searched": true,
"description": "Instant access, indexed, cached"
},
"name": "tier='hot'"
},
{
"kernel": "tier_should_search",
"args": [
"hot"
],
"expect": true,
"name": "tier='hot'"
},
{
"kernel": "tier_should_compress",
"args": [
"hot"
],
"expect": false,
"name": "tier='hot'"
},
{
"kernel": "tier_get_tier_config",
"args": [
"warm"
],
"expect": {
"indexed": true,
"cached": false,
"compressed": false,
"searched": true,
"description": "Fast access, indexed, not cached"
},
"name": "tier='warm'"
},
{
"kernel": "tier_should_search",
"args": [
"warm"
],
"expect": true,
"name": "tier='warm'"
},
{
"kernel": "tier_should_compress",
"args": [
"warm"
],
"expect": false,
"name": "tier='warm'"
},
{
"kernel": "tier_get_tier_config",
"args": [
"cold"
],
"expect": {
"indexed": false,
"cached": false,
"compressed": true,
"searched": false,
"description": "Slow access, compressed, not searched"
},
"name": "tier='cold'"
},
{
"kernel": "tier_should_search",
"args": [
"cold"
],
"expect": false,
"name": "tier='cold'"
},
{
"kernel": "tier_should_compress",
"args": [
"cold"
],
"expect": true,
"name": "tier='cold'"
},
{
"kernel": "tier_get_tier_config",
"args": [
"unknown"
],
"expect": {
"indexed": true,
"cached": false,
"compressed": false,
"searched": true,
"description": "Fast access, indexed, not cached"
},
"name": "tier='unknown'"
},
{
"kernel": "tier_should_search",
"args": [
"unknown"
],
"expect": false,
"name": "tier='unknown'"
},
{
"kernel": "tier_should_compress",
"args": [
"unknown"
],
"expect": false,
"name": "tier='unknown'"
},
{
"kernel": "tier_get_tier_config",
"args": [
""
],
"expect": {
"indexed": true,
"cached": false,
"compressed": false,
"searched": true,
"description": "Fast access, indexed, not cached"
},
"name": "tier=''"
},
{
"kernel": "tier_should_search",
"args": [
""
],
"expect": false,
"name": "tier=''"
},
{
"kernel": "tier_should_compress",
"args": [
""
],
"expect": false,
"name": "tier=''"
}
]
File diff suppressed because it is too large. Load diff
+70 -9
View File
@@ -18,6 +18,9 @@ mod safety_battery;
#[cfg(test)]
mod identity_battery;
#[cfg(test)]
mod tier_battery;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
@@ -363,6 +366,64 @@ pub extern "C" fn cc_tier_demote(arg: *const c_char) -> *mut c_char {
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_tier_demotion_sweep(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
let e = get(&a, "entry")
.cloned()
.unwrap_or(pyjson::Json::Obj(vec![]));
broker::tier_demotion_sweep(
&e,
match get(&a, "hot_days") {
Some(pyjson::Json::Num(n)) => *n,
_ => 7.0,
},
match get(&a, "warm_days") {
Some(pyjson::Json::Num(n)) => *n,
_ => 30.0,
},
match get(&a, "now") {
Some(pyjson::Json::Str(s)) => s.as_str(),
_ => "",
},
)
});
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_tier_get_tier_config(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::tier_get_tier_config(match get(&a, "tier") {
Some(pyjson::Json::Str(s)) => s.as_str(),
_ => "",
})
});
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_tier_should_search(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::tier_should_search(match get(&a, "tier") {
Some(pyjson::Json::Str(s)) => s.as_str(),
_ => "",
})
});
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_tier_should_compress(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::tier_should_compress(match get(&a, "tier") {
Some(pyjson::Json::Str(s)) => s.as_str(),
_ => "",
})
});
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_witness_extract_topic(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
@@ -584,9 +645,9 @@ pub extern "C" fn cc_py_near_dup(arg: *const c_char) -> *mut c_char {
#[no_mangle]
pub extern "C" fn cc_parse_json(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::parse_json(&req_str(&a, "text"))
});
let result = read_arg(arg)
.and_then(|t| arg_json(&t))
.map(|a| broker::parse_json(&req_str(&a, "text")));
envelope(result)
}
@@ -664,17 +725,17 @@ pub extern "C" fn cc_reflect(arg: *const c_char) -> *mut c_char {
#[no_mangle]
pub extern "C" fn cc_apply(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::apply(&req_str(&a, "delta"))
});
let result = read_arg(arg)
.and_then(|t| arg_json(&t))
.map(|a| broker::apply(&req_str(&a, "delta")));
envelope(result)
}
#[no_mangle]
pub extern "C" fn cc_handle_hook(arg: *const c_char) -> *mut c_char {
let result = read_arg(arg).and_then(|t| arg_json(&t)).map(|a| {
broker::handle_hook(&req_str(&a, "event"))
});
let result = read_arg(arg)
.and_then(|t| arg_json(&t))
.map(|a| broker::handle_hook(&req_str(&a, "event")));
envelope(result)
}
+204
View File
@@ -0,0 +1,204 @@
//! tier_battery.rs — frozen-truth battery for the tier_manager gap-close
//! (dichotomy wave, worktree rune-wave-cz-db). Two JSON artifacts are
//! embedded VERBATIM (include_str!) and replayed through the broker kernels:
//! frozen_tier_truth.json — shared freeze_truth.py harness envelope
//! frozen_tier_methods.json — kernel-shaped truth for all seven tier kernels
//! Canonical comparison via dumps_sorted (Python-parity writer).
#[cfg(test)]
mod battery {
use crate::broker;
use crate::pyjson::{self, Json};
const HARNESS: &str = include_str!("frozen_tier_truth.json");
const METHODS: &str = include_str!("frozen_tier_methods.json");
fn norm(v: &Json) -> String {
pyjson::dumps_sorted(v)
}
fn s_arg(v: &Json) -> String {
match v {
Json::Str(s) => s.clone(),
_ => String::new(),
}
}
fn num_arg(v: &Json) -> f64 {
match v {
Json::Num(n) => *n,
_ => 0.0,
}
}
fn obj_arg(v: &Json) -> Json {
match v {
Json::Obj(_) => v.clone(),
_ => Json::Obj(vec![]),
}
}
fn str_arg_at(args: &[Json], ix: usize) -> String {
match args.get(ix) {
Some(Json::Str(s)) => s.clone(),
_ => String::new(),
}
}
/// Replay one kernels-file case through its broker kernel.
/// tier rows carry [entry, hot_days, warm_days, now]; config rows [tier].
fn replay(kernel: &str, args: &[Json]) -> Json {
let e = match args.first() {
Some(x) => obj_arg(x),
None => Json::Obj(vec![]),
};
let hot = match args.get(1) {
Some(n) => num_arg(n),
None => 7.0,
};
let warm = match args.get(2) {
Some(n) => num_arg(n),
None => 30.0,
};
let now = str_arg_at(args, 3);
match kernel {
"tier_get" => broker::tier_get(&e, hot, warm, &now),
"tier_promote" => broker::tier_promote(&e, hot, warm, &now),
"tier_demote" => broker::tier_demote(&e, hot, warm, &now),
"tier_demotion_sweep" => broker::tier_demotion_sweep(&e, hot, warm, &now),
"tier_get_tier_config" => broker::tier_get_tier_config(&s_arg(&args[0])),
"tier_should_search" => broker::tier_should_search(&s_arg(&args[0])),
"tier_should_compress" => broker::tier_should_compress(&s_arg(&args[0])),
other => panic!("unknown kernel in frozen truth: {other}"),
}
}
/// The harness envelope's method rows replay through the SAME kernels —
/// the Python oracle branch and the Rust kernel must agree per case.
/// get_tier/promote/demote/demotion_sweep map onto the kernel with the
/// harness's frozen clock (the oracle branch pinned to the same instant
/// during capture); _py_* rows are the identical oracle bodies.
fn replay_harness(fn_name: &str, recv: &Json, args: &[Json]) -> Json {
let entry = match args.first() {
Some(x) => obj_arg(x),
None => Json::Obj(vec![]),
};
let _ = recv; // TierManager carries no state (init: pass)
match fn_name {
"TierManager._py_get_tier" => broker::tier_get(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager.get_tier" => broker::tier_get(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager.promote" => broker::tier_promote(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager._py_promote" => broker::tier_promote(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager.demote" => broker::tier_demote(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager._py_demote" => broker::tier_demote(&entry, 7.0, 30.0, HARNESS_NOW),
"TierManager.demotion_sweep" => {
broker::tier_demotion_sweep(&entry, 7.0, 30.0, HARNESS_NOW)
}
"TierManager.get_tier_config" => broker::tier_get_tier_config(&s_arg(&args[0])),
"TierManager.should_search" => broker::tier_should_search(&s_arg(&args[0])),
"TierManager.should_compress" => broker::tier_should_compress(&s_arg(&args[0])),
other => panic!("unmapped harness fn: {other}"),
}
}
const HARNESS_NOW: &str = "2026-10-14T09:00:00Z";
#[test]
fn frozen_methods_truth_replays_byte_identical() {
let cases = pyjson::parse(METHODS).expect("methods truth parses");
let items = match cases {
Json::Arr(x) => x,
_ => panic!("methods truth must be a list"),
};
assert!(items.len() >= 60, "expected the full 75-row tier battery");
for c in &items {
let kernel = match c.get("kernel") {
Some(Json::Str(s)) => s.clone(),
_ => panic!("case missing kernel"),
};
let args: Vec<Json> = match c.get("args") {
Some(Json::Arr(x)) => x.clone(),
_ => vec![],
};
let expected = c.get("expect").cloned().unwrap_or(Json::Null);
let name = match c.get("name") {
Some(Json::Str(s)) => s.as_str(),
_ => "",
};
let got = replay(&kernel, &args);
assert_eq!(
norm(&got),
norm(&expected),
"methods truth diverged for {kernel}/{name}"
);
}
}
#[test]
fn frozen_harness_truth_replays_byte_identical() {
let raw = pyjson::parse(HARNESS).expect("harness truth parses");
let items = match raw.get("cases") {
Some(Json::Arr(x)) => x.clone(),
_ => panic!("harness envelope must carry cases"),
};
assert!(!items.is_empty(), "harness truth must not be empty");
for c in &items {
let fname = match c.get("fn") {
Some(Json::Str(s)) => s.clone(),
_ => panic!("case missing fn"),
};
let args: Vec<Json> = match c.get("args") {
Some(Json::Arr(x)) => x.clone(),
_ => vec![],
};
let expected = match c.get("expected") {
Some(Json::Obj(inner)) => {
// recv rows: {"result": ...} — the receiver (TierManager)
// is stateless, so the result alone is the contract.
match inner.iter().find(|(k, _)| k == "result") {
Some((_, v)) => v.clone(),
None => Json::Null,
}
}
Some(x) => x.clone(),
None => Json::Null,
};
let recv = c.get("recv").cloned().unwrap_or(Json::Null);
let got = replay_harness(&fname, &recv, &args);
assert_eq!(
norm(&got),
norm(&expected),
"harness truth diverged for {fname}"
);
}
}
/// Kernel self-coherence: demotion_sweep == tier_get identically, and
/// promote/demote ladders match the oracle decision table.
#[test]
fn sweep_alias_and_ladders_coherent() {
for k in ["hot", "warm", "cold", "unknown", ""] {
let cfg = broker::tier_get_tier_config(k);
let searched = broker::tier_should_search(k);
let compressed = broker::tier_should_compress(k);
let entry = Json::Obj(vec![("wash_count".to_string(), Json::Num(2.0))]);
let tier = broker::tier_get(&entry, 7.0, 30.0, HARNESS_NOW);
let sweep = broker::tier_demotion_sweep(&entry, 7.0, 30.0, HARNESS_NOW);
assert_eq!(norm(&sweep), norm(&tier), "sweep must alias get ({k})");
let _ = (cfg, searched, compressed);
}
let cold_entry = Json::Obj(vec![(
"last_accessed".to_string(),
Json::Str("2026-08-01T09:00:00Z".into()),
)]);
assert_eq!(
norm(&broker::tier_promote(&cold_entry, 7.0, 30.0, HARNESS_NOW)),
norm(&Json::Str("warm".into()))
);
let hot_entry = Json::Obj(vec![("wash_count".to_string(), Json::Num(25.0))]);
assert_eq!(
norm(&broker::tier_demote(&hot_entry, 7.0, 30.0, HARNESS_NOW)),
norm(&Json::Str("warm".into()))
);
}
}
+67 -9
View File
@@ -4,6 +4,7 @@ their parity — exercised directly so the delegation lines are measured."""
from __future__ import annotations
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
import pytest
@@ -11,7 +12,7 @@ import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
from rune import tier_manager as tm # noqa: E402
from rune import tier_manager as tm # noqa: E402, E501
@pytest.fixture
@@ -19,15 +20,22 @@ def tmgr():
return tm.TierManager()
def _z(days: float) -> str:
"""A UTC timestamp `days` days in the past (drift-immune: the hot/warm/
cold brackets used to be baked-in calendar dates and went stale)."""
return (datetime.now(timezone.utc) - timedelta(days=days)).strftime(
"%Y-%m-%dT%H:%M:%SZ")
CASES = [
{"wash_count": 25}, # wash >=20 hot
{"wash_count": 2, "last_accessed": "2026-10-05T06:00:00Z"}, # recency hot
{"wash_count": 2, "last_accessed": "2026-09-25T00:00:00Z"}, # warm
{"wash_count": 2, "last_accessed": "2026-08-01T00:00:00Z"}, # cold
{"wash_count": 2, "last_accessed": "2026-10-05T00:00:00"}, # naive → warm
{"wash_count": 2, "last_accessed": "junk"}, # malformed → warm
{"wash_count": 2}, # no last → warm
{"wash_count": 2, "rock_status": "rock"}, # rock hot
{"wash_count": 25}, # wash >=20 hot
{"wash_count": 2, "last_accessed": _z(6)}, # recency hot
{"wash_count": 2, "last_accessed": _z(19)}, # warm
{"wash_count": 2, "last_accessed": _z(40)}, # cold
{"wash_count": 2, "last_accessed": "2026-10-05T00:00:00"}, # naive → warm
{"wash_count": 2, "last_accessed": "junk"}, # malformed → warm
{"wash_count": 2}, # no last → warm
{"wash_count": 2, "rock_status": "rock"}, # rock hot
]
@@ -64,3 +72,53 @@ def test_tier_config_public_surface(tmgr):
assert tmgr.get_tier_config("cold")["compressed"] is True
assert tmgr.should_search("hot") is True
assert tmgr.should_compress("cold") is True
def test_demotion_sweep_matches_get_tier(tmgr):
for e in CASES:
assert tmgr.demotion_sweep(e) == tmgr.get_tier(e), e
def test_get_tier_config_matches_oracle(tmgr):
for tier in ("hot", "warm", "cold", "unknown", ""):
want = tm.TIER_CONFIG.get(tier, tm.TIER_CONFIG["warm"])
got = tmgr.get_tier_config(tier)
assert got == want, (tier, got, want)
# wire order parity (insertion order: indexed..description)
assert list(got) == ["indexed", "cached", "compressed", "searched",
"description"], tier
def test_should_search_compress_match_oracle(tmgr):
for tier in ("hot", "warm", "cold", "unknown", ""):
assert tmgr.should_search(tier) == tm.TIER_CONFIG.get(
tier, {}).get("searched", False), tier
assert tmgr.should_compress(tier) == tm.TIER_CONFIG.get(
tier, {}).get("compressed", False), tier
def test_unknown_tier_defaults_warm_not_hot(tmgr):
# get_tier_config falls to the WARM entry; search/compress fall to False
got = tmgr.get_tier_config("unknown")
assert got == tm.TIER_CONFIG["warm"]
assert tmgr.should_search("unknown") is False
assert tmgr.should_compress("unknown") is False
def test_kernel_unavailable_new_fns_fall_back_to_oracle(monkeypatch, tmgr):
monkeypatch.setattr(tm, "_core", lambda: None)
for tier in ("hot", "warm", "cold", "unknown", ""):
assert tmgr.get_tier_config(tier) == tm.TIER_CONFIG.get(
tier, tm.TIER_CONFIG["warm"]), tier
assert tmgr.should_search(tier) == tm.TIER_CONFIG.get(
tier, {}).get("searched", False), tier
assert tmgr.should_compress(tier) == tm.TIER_CONFIG.get(
tier, {}).get("compressed", False), tier
for e in CASES:
assert tmgr.demotion_sweep(e) == tmgr.get_tier(e), e
def test_demotion_sweep_kernel_aliases_tier_get(tmgr):
for e in CASES:
# kernel sweep == kernel get (same alias law both sides)
assert tmgr.demotion_sweep(e) == tmgr._py_get_tier(e), e
+51
View File
@@ -0,0 +1,51 @@
# tier_manager gap-close — verification summary (dichotomy wave, worktree rune-wave-cz-db)
Oracle: /mnt/workdrive/rune/src/rune/tier_manager.py (262L, 10 fns, 6/10 → **10/10 FULL RUST**).
Port surface: cognition_core (audit alias — the module's live chain is tier_manager → cc_loader → libcognition_core.so).
## What was ported (4 missing fns)
- `tier_demotion_sweep` — named alias of the get_tier decision (thresholds + now as inputs)
- `tier_get_tier_config` — TIER_CONFIG lookup, warm default for unknowns, wire order = oracle insertion order
- `tier_should_search` / `tier_should_compress` — projections with empty-dict False default
Fix-first: `parse_strict_aware` (broker.rs) gained datetime.fromisoformat range
validation (leap-year month lengths, day-of-month, h<=23 or ISO hour-24
end-of-day) — the oracle RAISES on out-of-calendar timestamps and falls back to
warm; the old fixed-position parser computed off-calendar epochs. Proven by the
frozen battery's crash-class rows (month 13, Feb 30, day 0, hour 24+minutes).
Recorded as quirk #22 in docs/dichotomy-oracle-quirks.json.
## Commands and exits (evidence in this directory)
| Stage | Command | Exit | Evidence |
|---|---|---|---|
| cargo test | `cargo test` (cognition_core) | 0 | tier-cargo-test.{log,exit} — 65 unit + 5 doc; tier_battery 3/3 |
| clippy | `cargo clippy --all-targets -- -D warnings` | 0 | tier-clippy.{log,exit} |
| freeze verify ×2 | `RUNE_COGNITION_CORE=python PYTHONPATH=src python3 scripts/freeze_truth.py --verify src/rust/cognition_core/src/frozen_tier_truth.json --module rune.tier_manager` | 0 | tier-freeze-verify1/2.{log,exit} — 121 cases byte-identical each run |
| live parity | `PYTHONPATH=src python3 scripts/check_tier_parity.py` | 0 | tier-live-parity.{log,exit} — 1720 checks, 0 divergences (frozen rows + seeded fuzz + config fuzz, both clocks pinned) |
| pytest live | `PYTHONPATH=src python -m pytest tests/test_tier_delegation.py` | 0 | tier-pytest-live.{log,exit} — 12 passed |
| pytest pinned | same + `RUNE_COGNITION_CORE=python` | 0 | tier-pytest-pinned.{log,exit} — 12 passed |
| ruff | `ruff check` (touched py files) | 0 | tier-ruff.{log,exit} |
| collateral (shims+tier+witness) | pytest trio, kernels resolved via *_RUST_LIB at main checkout (CC at THIS worktree's build) | 0 | tier-pytest-collateral.{log,exit} — 59 passed |
| collateral (cognition consumers) | 12-file consumer suite, same env | 0 | tier-pytest-collateral2.{log,exit} — 109 passed |
Kernel env for collateral: TC/MS/CS/SP/SC/MR(+61 more) → /mnt/workdrive/rune
built .so files; CC_RUST_LIB → THIS worktree's
src/rust/cognition_core/target/release/libcognition_core.so (main's build lacks
the new cc_tier_* symbols). Pre-existing var collision noted: tl_loader
(toolchain crate) also reads TC_RUST_LIB — harmless here (no toolchain tests
in the collateral set).
## Divergences documented (not bugs)
- Sub-second `last_accessed` timestamps: kernel parser is seconds-resolution
(fractional seconds dropped, matching the W3.4 seam); exact-boundary rows
with microseconds are EXCLUDED from truth corpora (gen_tier_truth.py header).
- bool wash_count: Json::Bool is not Num → wash 0.0; oracle `or 0` truthiness
gives the same bracket decision (both < 20) — frozen rows cover it.
## Audit
docs/dichotomy-rebase-honest-audit.md regenerated (`dichotomy_audit.py --write`):
tier_manager 6/10 PARTIAL → 10/10 FULL RUST; module-level FULL 102 → 105
(+claim_audit, +builder_bridge from sibling commits already on base; +tier_manager).
SHAs: port + Phase B commits cited in the close contract and the landing
report (captured after push per port law 5).
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0