From 3d724c4d0eaedbc2efa3660bd63b967ecac4d07b Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 15:19:16 -0700
Subject: [PATCH 01/11] feat(cli): add aelf core subcommand (#439)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Implements _cmd_core with _qualifies_core and _emit_core helpers.
Composition over list_locked_beliefs(), list_belief_ids(), and
get_belief() — no new store method. Subparser registered after
p_locked with --locked-only/--no-locked as a mutually exclusive group.
Spec: docs/feature-aelf-core.md.
---
src/aelfrice/cli.py | 148 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 148 insertions(+)
diff --git a/src/aelfrice/cli.py b/src/aelfrice/cli.py
index 0a63d1579..48b3ab87d 100644
--- a/src/aelfrice/cli.py
+++ b/src/aelfrice/cli.py
@@ -1278,6 +1278,115 @@ def _cmd_confirm(args: argparse.Namespace, out: object) -> int:
return 0
+_CORE_MIN_CORROBORATION: int = 2
+_CORE_MIN_POSTERIOR: float = 2.0 / 3.0
+_CORE_MIN_ALPHA_BETA: int = 4
+
+
+def _qualifies_core(b: object, args: argparse.Namespace) -> bool:
+ """Return True if belief b meets any non-lock core signal."""
+ alpha: float = b.alpha # type: ignore[attr-defined]
+ beta: float = b.beta # type: ignore[attr-defined]
+ corr: int = b.corroboration_count # type: ignore[attr-defined]
+ if corr >= args.min_corroboration:
+ return True
+ ab = alpha + beta
+ if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ return True
+ return False
+
+
+def _emit_core(
+ locked: list[object],
+ candidates: list[object],
+ args: argparse.Namespace,
+ out: object,
+) -> None:
+ seen: set[str] = {b.id for b in locked} # type: ignore[attr-defined]
+ unlocked = [b for b in candidates if b.id not in seen] # type: ignore[attr-defined]
+
+ def _posterior(b: object) -> float:
+ a: float = b.alpha # type: ignore[attr-defined]
+ bb: float = b.beta # type: ignore[attr-defined]
+ return a / (a + bb)
+
+ unlocked.sort(key=lambda b: (-_posterior(b), b.id)) # type: ignore[attr-defined]
+ results = list(locked) + unlocked
+
+ if args.limit is not None:
+ results = results[: args.limit]
+
+ if not results:
+ print("no core beliefs", file=out) # type: ignore[arg-type]
+ return
+
+ if args.json:
+ rows = []
+ for b in results:
+ signals: list[str] = []
+ if b.lock_level != "none": # type: ignore[attr-defined]
+ signals.append("lock")
+ if b.corroboration_count >= args.min_corroboration: # type: ignore[attr-defined]
+ signals.append("corroboration")
+ alpha: float = b.alpha # type: ignore[attr-defined]
+ beta: float = b.beta # type: ignore[attr-defined]
+ ab = alpha + beta
+ if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ signals.append("posterior")
+ rows.append({
+ "id": b.id, # type: ignore[attr-defined]
+ "content": b.content, # type: ignore[attr-defined]
+ "lock_level": b.lock_level, # type: ignore[attr-defined]
+ "alpha": alpha,
+ "beta": beta,
+ "posterior_mean": round(alpha / ab, 3) if ab else 0.0,
+ "corroboration_count": b.corroboration_count, # type: ignore[attr-defined]
+ "signals": sorted(set(signals)),
+ })
+ print(json.dumps(rows, indent=2), file=out) # type: ignore[arg-type]
+ return
+
+ for b in results:
+ alpha = b.alpha # type: ignore[attr-defined]
+ beta = b.beta # type: ignore[attr-defined]
+ corr = b.corroboration_count # type: ignore[attr-defined]
+ ab = alpha + beta
+ parts: list[str] = []
+ if b.lock_level != "none": # type: ignore[attr-defined]
+ parts.append("LOCK")
+ if corr >= args.min_corroboration:
+ parts.append(f"CORR={corr}")
+ if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ parts.append(f"α={alpha:.1f}")
+ parts.append(f"β={beta:.1f}")
+ parts.append(f"μ={alpha / ab:.3f}")
+ tag = f" [{','.join(parts)}]" if parts else ""
+ print(f"{b.id}{tag}: {b.content}", file=out) # type: ignore[arg-type, attr-defined]
+
+
+def _cmd_core(args: argparse.Namespace, out: object) -> int:
+ """Surface load-bearing beliefs: locked ∪ corroborated ∪ high-posterior.
+
+ Spec: docs/feature-aelf-core.md. No new store method — composition over
+ list_locked_beliefs(), list_belief_ids(), and get_belief().
+ """
+ store = _open_store()
+ try:
+ locked: list[object] = [] if args.no_locked else store.list_locked_beliefs()
+ candidates: list[object] = []
+ if not args.locked_only:
+ for bid in store.list_belief_ids():
+ b = store.get_belief(bid)
+ if b is None or b.lock_level != "none":
+ continue
+ if _qualifies_core(b, args):
+ candidates.append(b)
+ finally:
+ store.close()
+ _emit_core(locked, candidates, args, out)
+ return 0
+
+
def _cmd_promote(args: argparse.Namespace, out: object) -> int:
"""Promote agent_inferred -> user_validated. Alias of `aelf validate`."""
return _cmd_validate(args, out)
@@ -3493,6 +3602,45 @@ def build_parser(*, show_advanced: bool = False) -> argparse.ArgumentParser:
)
p_locked.set_defaults(func=_cmd_locked)
+ # Read-only lens: load-bearing beliefs (locked ∪ corroborated ∪ high-posterior).
+ p_core = sub.add_parser(
+ "core",
+ help="surface load-bearing beliefs: locked ∪ corroborated ∪ high-posterior",
+ )
+ p_core.add_argument(
+ "--json", action="store_true", dest="json",
+ help="emit JSON list instead of text",
+ )
+ p_core.add_argument(
+ "--limit", type=int, default=None, metavar="N",
+ help="cap result count after filtering/sort",
+ )
+ p_core.add_argument(
+ "--min-corroboration", type=int, default=_CORE_MIN_CORROBORATION,
+ metavar="N",
+ help="corroboration_count threshold (default 2; 0 disables)",
+ )
+ p_core.add_argument(
+ "--min-posterior", type=float, default=_CORE_MIN_POSTERIOR,
+ metavar="FLOAT",
+ help="posterior-mean threshold (default 2/3; 0.0 disables)",
+ )
+ p_core.add_argument(
+ "--min-alpha-beta", type=int, default=_CORE_MIN_ALPHA_BETA,
+ metavar="N",
+ help="α+β co-gate for posterior signal (default 4)",
+ )
+ _core_excl = p_core.add_mutually_exclusive_group()
+ _core_excl.add_argument(
+ "--locked-only", action="store_true",
+ help="return only the locked subset",
+ )
+ _core_excl.add_argument(
+ "--no-locked", action="store_true",
+ help="suppress locked beliefs (surface corroboration/posterior only)",
+ )
+ p_core.set_defaults(func=_cmd_core)
+
# Hidden: belief lifecycle inverse of `lock` / `validate`. Power-user.
p_demote = sub.add_parser(
"demote",
From 610645ff4849bf570aa8abb65f241bcef51232da Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 15:21:12 -0700
Subject: [PATCH 02/11] test(cli): unit tests for aelf core (#439)
---
tests/test_cli_core.py | 283 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 283 insertions(+)
create mode 100644 tests/test_cli_core.py
diff --git a/tests/test_cli_core.py b/tests/test_cli_core.py
new file mode 100644
index 000000000..e7ac929e8
--- /dev/null
+++ b/tests/test_cli_core.py
@@ -0,0 +1,283 @@
+"""Tests for `aelf core` CLI subcommand (#439).
+
+Five-belief fixture matrix per spec (docs/feature-aelf-core.md):
+ b-locked lock=user alpha=1 beta=1 corr=0 → yes (LOCK)
+ b-corr lock=none alpha=1 beta=1 corr=3 → yes (CORR)
+ b-posterior lock=none alpha=4 beta=1 corr=0 → yes (μ=0.8, α+β=5)
+ b-thin-post lock=none alpha=2 beta=1 corr=0 → no (μ=0.667 but α+β=3)
+ b-prior lock=none alpha=1 beta=1 corr=0 → no
+
+Tests cover all 8 spec scenarios.
+"""
+from __future__ import annotations
+
+import io
+import json
+from pathlib import Path
+
+import pytest
+
+from aelfrice.cli import main
+from aelfrice.models import (
+ BELIEF_FACTUAL,
+ CORROBORATION_SOURCE_CLI_REMEMBER,
+ LOCK_NONE,
+ LOCK_USER,
+ ORIGIN_AGENT_INFERRED,
+ Belief,
+)
+from aelfrice.store import MemoryStore
+
+
+@pytest.fixture(autouse=True)
+def isolated_db(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
+ p = tmp_path / "aelf.db"
+ monkeypatch.setenv("AELFRICE_DB", str(p))
+ return p
+
+
+def _run(*argv: str) -> tuple[int, str]:
+ buf = io.StringIO()
+ code = main(argv=list(argv), out=buf)
+ return code, buf.getvalue()
+
+
+def _make_belief(
+ bid: str,
+ content: str,
+ lock_level: str = LOCK_NONE,
+ alpha: float = 1.0,
+ beta: float = 1.0,
+) -> Belief:
+ return Belief(
+ id=bid,
+ content=content,
+ content_hash="hash_" + bid[:6],
+ alpha=alpha,
+ beta=beta,
+ type=BELIEF_FACTUAL,
+ lock_level=lock_level,
+ locked_at="2026-05-06T00:00:00Z" if lock_level != LOCK_NONE else None,
+ demotion_pressure=0,
+ created_at="2026-05-06T00:00:00Z",
+ last_retrieved_at=None,
+ origin=ORIGIN_AGENT_INFERRED,
+ )
+
+
+def _seed_store(db: Path) -> dict[str, Belief]:
+ beliefs = {
+ "b-locked": _make_belief("b0locked0000000000", "locked ground truth", lock_level=LOCK_USER),
+ "b-corr": _make_belief("b0corr00000000000a", "independently corroborated"),
+ "b-posterior": _make_belief("b0posterior000000a", "strong posterior", alpha=4.0, beta=1.0),
+ "b-thin": _make_belief("b0thinpost000000aa", "thin posterior", alpha=2.0, beta=1.0),
+ "b-prior": _make_belief("b0prior000000000aa", "flat prior"),
+ }
+ s = MemoryStore(str(db))
+ try:
+ for b in beliefs.values():
+ s.insert_belief(b)
+ # b-corr: record 3 corroboration rows via the public API
+ for _ in range(3):
+ s.record_corroboration(
+ beliefs["b-corr"].id,
+ source_type=CORROBORATION_SOURCE_CLI_REMEMBER,
+ )
+ finally:
+ s.close()
+ return beliefs
+
+
+# --- scenario 1: default text output -----------------------------------------
+
+
+def test_core_default_includes_locked(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ code, out = _run("core")
+ assert code == 0
+ assert b["b-locked"].id in out
+
+
+def test_core_default_includes_corroborated(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ code, out = _run("core")
+ assert code == 0
+ assert b["b-corr"].id in out
+
+
+def test_core_default_includes_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ code, out = _run("core")
+ assert code == 0
+ assert b["b-posterior"].id in out
+
+
+def test_core_default_excludes_thin_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core")
+ assert b["b-thin"].id not in out
+
+
+def test_core_default_excludes_flat_prior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core")
+ assert b["b-prior"].id not in out
+
+
+def test_core_tag_block_lock(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core")
+ assert f"{b['b-locked'].id} [LOCK]" in out
+
+
+def test_core_tag_block_corr(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core")
+ assert "CORR=3" in out
+
+
+def test_core_tag_block_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core")
+ assert "μ=0.800" in out
+
+
+# --- scenario 2: --json round-trip -------------------------------------------
+
+
+def test_core_json_parses(isolated_db: Path) -> None:
+ _seed_store(isolated_db)
+ _, out = _run("core", "--json")
+ rows = json.loads(out)
+ assert isinstance(rows, list)
+
+
+def test_core_json_signals_lock(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--json")
+ rows = json.loads(out)
+ locked_row = next(r for r in rows if r["id"] == b["b-locked"].id)
+ assert "lock" in locked_row["signals"]
+
+
+def test_core_json_signals_corroboration(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--json")
+ rows = json.loads(out)
+ corr_row = next(r for r in rows if r["id"] == b["b-corr"].id)
+ assert "corroboration" in corr_row["signals"]
+
+
+def test_core_json_signals_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--json")
+ rows = json.loads(out)
+ post_row = next(r for r in rows if r["id"] == b["b-posterior"].id)
+ assert "posterior" in post_row["signals"]
+
+
+def test_core_json_signals_nonempty(isolated_db: Path) -> None:
+ _seed_store(isolated_db)
+ _, out = _run("core", "--json")
+ rows = json.loads(out)
+ for row in rows:
+ assert len(row["signals"]) >= 1
+
+
+# --- scenario 3: --locked-only -----------------------------------------------
+
+
+def test_core_locked_only_exits_zero(isolated_db: Path) -> None:
+ _seed_store(isolated_db)
+ code, _ = _run("core", "--locked-only")
+ assert code == 0
+
+
+def test_core_locked_only_returns_locked(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--locked-only")
+ assert b["b-locked"].id in out
+
+
+def test_core_locked_only_excludes_corr(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--locked-only")
+ assert b["b-corr"].id not in out
+
+
+def test_core_locked_only_excludes_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--locked-only")
+ assert b["b-posterior"].id not in out
+
+
+# --- scenario 4: --no-locked -------------------------------------------------
+
+
+def test_core_no_locked_suppresses_locked(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--no-locked")
+ assert b["b-locked"].id not in out
+
+
+def test_core_no_locked_includes_corr(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--no-locked")
+ assert b["b-corr"].id in out
+
+
+def test_core_no_locked_includes_posterior(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--no-locked")
+ assert b["b-posterior"].id in out
+
+
+# --- scenario 5: mutual exclusion exit 2 -------------------------------------
+
+
+def test_core_locked_only_and_no_locked_exit_two(
+ isolated_db: Path, capsys: pytest.CaptureFixture[str]
+) -> None:
+ with pytest.raises(SystemExit) as exc:
+ _run("core", "--locked-only", "--no-locked")
+ assert exc.value.code == 2
+
+
+# --- scenario 6: --limit 1 returns locked first ------------------------------
+
+
+def test_core_limit_one_returns_locked(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--limit", "1")
+ assert b["b-locked"].id in out
+ assert b["b-corr"].id not in out
+ assert b["b-posterior"].id not in out
+
+
+# --- scenario 7: empty store prints sentinel ----------------------------------
+
+
+def test_core_empty_store_exits_zero(isolated_db: Path) -> None:
+ code, _ = _run("core")
+ assert code == 0
+
+
+def test_core_empty_store_message(isolated_db: Path) -> None:
+ _, out = _run("core")
+ assert out.strip() == "no core beliefs"
+
+
+# --- scenario 8: threshold flags ---------------------------------------------
+
+
+def test_core_min_corroboration_raised_drops_corr(isolated_db: Path) -> None:
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--min-corroboration", "4")
+ assert b["b-corr"].id not in out
+
+
+def test_core_disabled_posterior_and_corr_includes_all_nonprior(isolated_db: Path) -> None:
+ """--min-posterior 0.0 --min-alpha-beta 0 includes b-thin (μ=0.667, α+β=3)."""
+ b = _seed_store(isolated_db)
+ _, out = _run("core", "--min-posterior", "0.0", "--min-alpha-beta", "0")
+ assert b["b-thin"].id in out
From 6824e7f9c410742be51f280f40a0c7175fdb1c2d Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 15:21:24 -0700
Subject: [PATCH 03/11] feat(slash_commands): add /aelf:core (#439)
---
src/aelfrice/slash_commands/core.md | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 src/aelfrice/slash_commands/core.md
diff --git a/src/aelfrice/slash_commands/core.md b/src/aelfrice/slash_commands/core.md
new file mode 100644
index 000000000..e2081dec8
--- /dev/null
+++ b/src/aelfrice/slash_commands/core.md
@@ -0,0 +1,18 @@
+---
+name: aelf:core
+description: Surface load-bearing beliefs — locked ∪ corroborated (≥2 sources) ∪ high-posterior (μ ≥ 2/3, α+β ≥ 4). Read-only.
+argument-hint: Optional flags, e.g. --json or --locked-only
+allowed-tools:
+ - Bash
+---
+
+List the beliefs that anchor the store: any belief that is user-locked,
+independently corroborated from at least two sources, or has a strong
+multi-event positive posterior. This is the operator's first-look lens
+when checking whether the store foundation is healthy.
+
+
+
+Run: `uv run aelf core $ARGUMENTS`
+Display the output verbatim. Do not add commentary.
+
From 31181c8b904c158d8717e904fe28c2d829599811 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 15:21:39 -0700
Subject: [PATCH 04/11] test(slash_commands): add core to EXPECTED_COMMANDS
(#439)
---
tests/test_slash_commands.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/test_slash_commands.py b/tests/test_slash_commands.py
index 2c429293c..f6d2a1951 100644
--- a/tests/test_slash_commands.py
+++ b/tests/test_slash_commands.py
@@ -49,6 +49,8 @@
# test_slash_commands_match_visible_cli_subcommands both enforce the
# slash file exists and matches the CLI surface.
"delete",
+ # v2.0 (#439) — load-bearing belief lens (locked ∪ corroborated ∪ high-posterior).
+ "core",
)
From 39bd8f950756237bf12dfd1977d8e074e1175e03 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 15:21:51 -0700
Subject: [PATCH 05/11] docs(COMMANDS): add aelf core to command reference
(#439)
---
docs/COMMANDS.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md
index c0449806b..1179d42b0 100644
--- a/docs/COMMANDS.md
+++ b/docs/COMMANDS.md
@@ -18,6 +18,7 @@ DB resolves from `$AELFRICE_DB`, then `/aelfrice/memory.db` when
| `search [--budget N]` | L0 locked + L2.5 entity-index (v1.3+) + L1 FTS5 BM25, token-budgeted (default 2,400 at v1.3+, 2,000 prior). L2.5 default-on; disable via `[retrieval] entity_index_enabled = false` in `.aelfrice.toml` or `AELFRICE_ENTITY_INDEX=0` in the env. Distinguishes "store empty" from "no match". |
| `lock ` | Insert at `(α, β) = (9.0, 0.5)` with `lock_level=user`. Idempotent — re-lock upgrades existing. |
| `locked [--pressured]` | List locks. With `--pressured`, only those with `demotion_pressure > 0`. |
+| `core [--json] [--limit N] [--min-corroboration N] [--min-posterior FLOAT] [--min-alpha-beta N] [--locked-only] [--no-locked]` | (v2.0+, #439) Surface load-bearing beliefs: locked ∪ {corroboration ≥ 2} ∪ {posterior ≥ 2/3 with α+β ≥ 4}. Read-only. |
| `unlock ` | Drop a user-lock without changing origin. Idempotent. Writes a `lock:unlock` audit row. |
| `delete [--yes] [--force]` | Hard-delete a belief: removes the belief row, FTS entry, edges (src and dst), and entity index rows. Writes one audit row to `feedback_history` (valence=-1.0, source=`user_deleted`) before the cascade so the forensic record survives. Confirmation prompt by default — prints belief content and requires the user to type the first 8 characters of the id; `--yes` skips the prompt. Refuses locked (`lock_level=user`) beliefs without `--force`; with `--force` the audit source becomes `user_deleted_force`. Exit 0 on success; exit 1 on not-found, locked-without-force, or prompt mismatch. |
| `demote ` | Drop a user lock (one tier per call: lock first, then user_validated). Delegates to `unlock` for the lock-drop path so an audit row is always written. |
From b186c9417e0f9d77613b7872b00747ce54b706b5 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 18:52:43 -0700
Subject: [PATCH 06/11] =?UTF-8?q?fix(cli):=20guard=20=5Fposterior=20agains?=
=?UTF-8?q?t=20=CE=B1+=CE=B2=3D=3D0=20(#439)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Sort path in _emit_core dereferences alpha/(alpha+beta) on every
belief; a malformed belief with alpha=beta=0 would raise
ZeroDivisionError and crash 'aelf core'. The JSON path already
guarded this case (line 1342: 'round(alpha / ab, 3) if ab else 0.0');
the sort path didn't.
Mirror the same fallback (μ=0.0 when α+β==0) in the inner _posterior
helper. Add a regression test (test_core_zero_alpha_beta_does_not_crash)
that constructs a Belief with alpha=beta=0 and asserts 'aelf core'
returns 0 without raising.
Found by Sourcery review on PR #463.
---
src/aelfrice/cli.py | 3 ++-
tests/test_cli_core.py | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/src/aelfrice/cli.py b/src/aelfrice/cli.py
index 48b3ab87d..a1389ae2f 100644
--- a/src/aelfrice/cli.py
+++ b/src/aelfrice/cli.py
@@ -1308,7 +1308,8 @@ def _emit_core(
def _posterior(b: object) -> float:
a: float = b.alpha # type: ignore[attr-defined]
bb: float = b.beta # type: ignore[attr-defined]
- return a / (a + bb)
+ ab = a + bb
+ return a / ab if ab > 0 else 0.0
unlocked.sort(key=lambda b: (-_posterior(b), b.id)) # type: ignore[attr-defined]
results = list(locked) + unlocked
diff --git a/tests/test_cli_core.py b/tests/test_cli_core.py
index e7ac929e8..68e8e1392 100644
--- a/tests/test_cli_core.py
+++ b/tests/test_cli_core.py
@@ -281,3 +281,28 @@ def test_core_disabled_posterior_and_corr_includes_all_nonprior(isolated_db: Pat
b = _seed_store(isolated_db)
_, out = _run("core", "--min-posterior", "0.0", "--min-alpha-beta", "0")
assert b["b-thin"].id in out
+
+
+# --- scenario 9: defensive — α+β==0 must not crash sort ----------------------
+
+
+def test_core_zero_alpha_beta_does_not_crash(isolated_db: Path) -> None:
+ """Belief with alpha=beta=0 must not raise ZeroDivisionError in sort path."""
+ s = MemoryStore(str(isolated_db))
+ try:
+ s.insert_belief(
+ _make_belief("b0zeroab0000000000", "zero ab edge case", alpha=0.0, beta=0.0),
+ )
+ s.insert_belief(
+ _make_belief(
+ "b0postlive00000000",
+ "live posterior",
+ alpha=4.0,
+ beta=1.0,
+ ),
+ )
+ finally:
+ s.close()
+ code, out = _run("core")
+ assert code == 0
+ assert "b0postlive00000000" in out
From da00bf5a4d3a96accb145b018706edc4fd2947b7 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 18:53:04 -0700
Subject: [PATCH 07/11] docs(cli): clarify aelf core threshold-flag help text
(#439)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Sourcery flagged a semantics mismatch: help text said '0 disables'
but the implementation reads as 'threshold = 0 admits any
non-negative value'. Existing test
test_core_disabled_posterior_and_corr_includes_all_nonprior asserts
b-thin (posterior-only candidate) is included with --min-posterior 0.0
--min-alpha-beta 0, which only holds under the lowering reading — so
the implementation is intentional and the test pins it; only the help
text was misleading.
Reword help to 'lower to widen lens — 0 admits …' so the documented
behavior matches code + existing test. No semantics change.
Spec memo (docs/feature-aelf-core.md, PR #456) flag table also says
'0 disables'; that is a separate doc-edit follow-up — not flipped here
to keep this PR focused on the Sourcery findings.
---
src/aelfrice/cli.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/aelfrice/cli.py b/src/aelfrice/cli.py
index a1389ae2f..080e18672 100644
--- a/src/aelfrice/cli.py
+++ b/src/aelfrice/cli.py
@@ -3619,12 +3619,14 @@ def build_parser(*, show_advanced: bool = False) -> argparse.ArgumentParser:
p_core.add_argument(
"--min-corroboration", type=int, default=_CORE_MIN_CORROBORATION,
metavar="N",
- help="corroboration_count threshold (default 2; 0 disables)",
+ help="corroboration_count threshold (default 2; lower to widen "
+ "lens — 0 admits any non-negative count)",
)
p_core.add_argument(
"--min-posterior", type=float, default=_CORE_MIN_POSTERIOR,
metavar="FLOAT",
- help="posterior-mean threshold (default 2/3; 0.0 disables)",
+ help="posterior-mean threshold (default 2/3; lower to widen "
+ "lens — 0.0 admits any belief that passes --min-alpha-beta)",
)
p_core.add_argument(
"--min-alpha-beta", type=int, default=_CORE_MIN_ALPHA_BETA,
From 134ce97385f55c58c3b820e2ec86c504c4f10d81 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Wed, 6 May 2026 18:53:21 -0700
Subject: [PATCH 08/11] test(cli_core): assert non-core beliefs absent from
--json output (#439)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Sourcery noted that test_core_default_includes_* asserts b-thin and
b-prior are excluded from default text output, but
test_core_json_parses only checked structure — the JSON path could
silently regress and emit non-core rows without the test catching it.
Mirror the text-mode exclusion assertion: at default thresholds, the
JSON row set must not contain b-thin or b-prior ids.
---
tests/test_cli_core.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/tests/test_cli_core.py b/tests/test_cli_core.py
index 68e8e1392..71df3c94b 100644
--- a/tests/test_cli_core.py
+++ b/tests/test_cli_core.py
@@ -146,10 +146,16 @@ def test_core_tag_block_posterior(isolated_db: Path) -> None:
def test_core_json_parses(isolated_db: Path) -> None:
- _seed_store(isolated_db)
+ b = _seed_store(isolated_db)
_, out = _run("core", "--json")
rows = json.loads(out)
assert isinstance(rows, list)
+ # JSON output must apply the same core-filter as text mode:
+ # b-thin (μ=0.667, α+β=3) and b-prior (μ=0.5, α+β=2) are excluded
+ # at default thresholds.
+ row_ids = {row["id"] for row in rows}
+ assert b["b-thin"].id not in row_ids
+ assert b["b-prior"].id not in row_ids
def test_core_json_signals_lock(isolated_db: Path) -> None:
From d03d159cf95b0112876c28c98a3e7d882168c9b2 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Thu, 7 May 2026 20:59:39 -0700
Subject: [PATCH 09/11] refactor(cli): use LOCK_NONE constant in aelf core
(#439)
Replace three hardcoded "none" string literals in _emit_core /
_cmd_core with the LOCK_NONE constant from aelfrice.models, matching
the existing LOCK_USER usage pattern elsewhere in cli.py. Sourcery
nit; no behavior change.
---
src/aelfrice/cli.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/aelfrice/cli.py b/src/aelfrice/cli.py
index 080e18672..7aed9c017 100644
--- a/src/aelfrice/cli.py
+++ b/src/aelfrice/cli.py
@@ -65,6 +65,7 @@
EDGE_SUPERSEDES,
EDGE_SUPPORTS,
INGEST_SOURCE_CLI_REMEMBER,
+ LOCK_NONE,
LOCK_USER,
ORIGIN_USER_STATED,
ORIGIN_USER_VALIDATED,
@@ -1325,7 +1326,7 @@ def _posterior(b: object) -> float:
rows = []
for b in results:
signals: list[str] = []
- if b.lock_level != "none": # type: ignore[attr-defined]
+ if b.lock_level != LOCK_NONE: # type: ignore[attr-defined]
signals.append("lock")
if b.corroboration_count >= args.min_corroboration: # type: ignore[attr-defined]
signals.append("corroboration")
@@ -1353,7 +1354,7 @@ def _posterior(b: object) -> float:
corr = b.corroboration_count # type: ignore[attr-defined]
ab = alpha + beta
parts: list[str] = []
- if b.lock_level != "none": # type: ignore[attr-defined]
+ if b.lock_level != LOCK_NONE: # type: ignore[attr-defined]
parts.append("LOCK")
if corr >= args.min_corroboration:
parts.append(f"CORR={corr}")
@@ -1378,7 +1379,7 @@ def _cmd_core(args: argparse.Namespace, out: object) -> int:
if not args.locked_only:
for bid in store.list_belief_ids():
b = store.get_belief(bid)
- if b is None or b.lock_level != "none":
+ if b is None or b.lock_level != LOCK_NONE:
continue
if _qualifies_core(b, args):
candidates.append(b)
From a60db1d10703c6593d84e4ca41eb8d9d92987363 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Thu, 7 May 2026 21:00:09 -0700
Subject: [PATCH 10/11] fix(cli): guard alpha/ab division when ab==0 in aelf
core (#439)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Three sites in _qualifies_core / _emit_core (JSON + text paths)
performed alpha/ab guarded only by `ab >= args.min_alpha_beta`. With
`--min-alpha-beta 0` (a documented valid value: 'admits any belief
that passes --min-alpha-beta'), a belief with α+β==0 satisfies the
gate and the division raises ZeroDivisionError. The `_posterior` inner
function already had the `ab > 0` guard from #439; its three siblings
did not.
Add the same guard to all three sites. New regression test
`test_core_zero_alpha_beta_with_min_ab_zero_does_not_crash` exercises
the unguarded path explicitly — the existing
`test_core_zero_alpha_beta_does_not_crash` only covered the sort
path because default `min_alpha_beta=4` short-circuits before
the division.
Refs CodeRabbit + Sourcery review on #463.
---
src/aelfrice/cli.py | 6 +++---
tests/test_cli_core.py | 20 ++++++++++++++++++++
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/aelfrice/cli.py b/src/aelfrice/cli.py
index 7aed9c017..8901d093d 100644
--- a/src/aelfrice/cli.py
+++ b/src/aelfrice/cli.py
@@ -1292,7 +1292,7 @@ def _qualifies_core(b: object, args: argparse.Namespace) -> bool:
if corr >= args.min_corroboration:
return True
ab = alpha + beta
- if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ if ab > 0 and ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
return True
return False
@@ -1333,7 +1333,7 @@ def _posterior(b: object) -> float:
alpha: float = b.alpha # type: ignore[attr-defined]
beta: float = b.beta # type: ignore[attr-defined]
ab = alpha + beta
- if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ if ab > 0 and ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
signals.append("posterior")
rows.append({
"id": b.id, # type: ignore[attr-defined]
@@ -1358,7 +1358,7 @@ def _posterior(b: object) -> float:
parts.append("LOCK")
if corr >= args.min_corroboration:
parts.append(f"CORR={corr}")
- if ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
+ if ab > 0 and ab >= args.min_alpha_beta and (alpha / ab) >= args.min_posterior:
parts.append(f"α={alpha:.1f}")
parts.append(f"β={beta:.1f}")
parts.append(f"μ={alpha / ab:.3f}")
diff --git a/tests/test_cli_core.py b/tests/test_cli_core.py
index 71df3c94b..d282af3a3 100644
--- a/tests/test_cli_core.py
+++ b/tests/test_cli_core.py
@@ -312,3 +312,23 @@ def test_core_zero_alpha_beta_does_not_crash(isolated_db: Path) -> None:
code, out = _run("core")
assert code == 0
assert "b0postlive00000000" in out
+
+
+def test_core_zero_alpha_beta_with_min_ab_zero_does_not_crash(
+ isolated_db: Path,
+) -> None:
+ """`--min-alpha-beta 0` must not enable the alpha/ab division on an α+β==0 belief.
+
+ The default test above passes only because `min_alpha_beta=4` short-circuits
+ the qualify check before the division. This variant exercises the actual
+ unguarded sites at the JSON and text emission paths.
+ """
+ s = MemoryStore(str(isolated_db))
+ try:
+ s.insert_belief(
+ _make_belief("b0zeroab0000000000", "zero ab edge case", alpha=0.0, beta=0.0),
+ )
+ finally:
+ s.close()
+ code, _ = _run("core", "--min-alpha-beta", "0")
+ assert code == 0
From a89bd81d3f852a3656dd969df718e5bce13f2c58 Mon Sep 17 00:00:00 2001
From: rrs <276464689+robotrocketscience@users.noreply.github.com>
Date: Thu, 7 May 2026 21:00:22 -0700
Subject: [PATCH 11/11] test(cli_core): drop CodeQL-flagged unused b
assignments (#439)
`test_core_tag_block_corr` and `test_core_tag_block_posterior`
assigned `b = _seed_store(isolated_db)` but never referenced `b`;
the assertions match raw substrings in stdout. Replace with bare
`_seed_store(isolated_db)` calls to clear the CodeQL py/unused-local-variable
warnings.
---
tests/test_cli_core.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/test_cli_core.py b/tests/test_cli_core.py
index d282af3a3..2360ca48d 100644
--- a/tests/test_cli_core.py
+++ b/tests/test_cli_core.py
@@ -131,13 +131,13 @@ def test_core_tag_block_lock(isolated_db: Path) -> None:
def test_core_tag_block_corr(isolated_db: Path) -> None:
- b = _seed_store(isolated_db)
+ _seed_store(isolated_db)
_, out = _run("core")
assert "CORR=3" in out
def test_core_tag_block_posterior(isolated_db: Path) -> None:
- b = _seed_store(isolated_db)
+ _seed_store(isolated_db)
_, out = _run("core")
assert "μ=0.800" in out