Skip to content

v0.15.0

Latest

Choose a tag to compare

@github-actions github-actions released this 20 Jul 10:11
29ff5db

Added

  • One unified "human decisions needed" list — athenaeum decisions +
    athenaeum merges + list_pending_decisions MCP tool (#401).
    Athenaeum
    accumulated two separate human-decision queues — pending questions
    (contradiction detector) and pending merges (resolver proposals) — but
    merges had no CLI and appeared in no briefing, so a real backlog (34
    proposals aged 1–4 weeks, found 2026-07-20) could sit unseen indefinitely.

    • New athenaeum decisions {list,next,count} --json returns both queues
      in one call, each item tagged type: "question" | "merge" with common
      fields (id, created_at, summary, confidence) plus a type-specific
      payload, sorted oldest-first. count prints
      N decisions pending (Q questions, M merges; oldest Xd).
    • New athenaeum merges {list,next,count} --json — the merges half, a mirror
      of athenaeum questions (the CLI-only briefing path had no way to read
      merges before).
    • New list_pending_decisions() MCP tool gives containerized agents the same
      unified list.
    • Every merge is rendered as an answerable question: each source page
      is named by its human title (frontmatter name:, not the uuid-slug) with a
      one-line gist, because cosine topic-similarity alone is not "should-merge"
      and misleads without the pages' own words. A human can decide approve/reject
      from one decisions list item without opening the raw wiki files.
  • Kill switch — athenaeum disable / enable / status (#379). One
    discoverable, reversible command stops all athenaeum background work instead
    of hand-editing the hook commands out of ~/.claude/settings.json and
    pkill-ing in-flight detectors. Backed by a state file
    ($ATHENAEUM_CACHE_DIR/disabled, default ~/.cache/athenaeum/disabled) plus
    an ATHENAEUM_DISABLED env override that every entry point honours — the
    session-end compile pass, the MCP write tools (remember,
    resolve_question, resolve_merge), and the shell hooks in
    examples/claude-code/ (which read the file directly with grep, so the
    per-turn recall path adds no Python startup).

    • athenaeum disable turns everything off (compile, contradiction detection,
      recall, notifications). athenaeum disable --compile is granular — it stops
      only the expensive compile/detect pass and leaves recall on.
    • athenaeum enable removes the state file and restores prior behaviour
      exactly. athenaeum status now reports the on/off state, scope, and reason.
    • The env override wins over the file; ATHENAEUM_DISABLED=1 (or all /
      compile) forces the state without touching the file — handy for a scoped
      one-off — and athenaeum enable warns when the env is still forcing it off.
  • Durable LLM-spend ledger + athenaeum spend + a spend ceiling (#378).
    Athenaeum runs on two cost models that must never be blended — the
    claude-cli subscription path (no invoice; consumes subscription quota,
    constrained in TOKENS) and the metered anthropic API path (real
    dollars: the resolver on the api backend, batch mode, and the per-turn
    query-topics recall extractor). The in-memory token summary was logged and
    discarded, so "how much has athenaeum spent, and is any of it real money?"
    was unanswerable from data. Now:

    • Ledger. Each pipeline run appends one JSONL record to
      ~/.cache/athenaeum/spend.jsonl carrying the provider (claude-cli
      vs anthropic — the field that makes "are we spending real money?" an
      empirical question), run type, model ids, the four token counters kept
      separate, and a provider-tagged USD estimate that is always $0 on
      the subscription path so subscription rows can never be summed into the
      dollar total. Append-only and crash-safe (single O_APPEND write per
      record; the reader tolerates a torn trailing line); records only counts and
      metadata, never content or credentials. On by default; disable with
      spend.ledger_enabled: false / ATHENAEUM_SPEND_LEDGER_ENABLED=0.
    • athenaeum spend --since 7d [--by-model] [--by-provider] [--json].
      Reports $ for the API path and tokens for the subscription path,
      never blended. --json is the shape /good-morning consumes.
    • Spend ceiling. Configurable per-run and per-day ceilings —
      spend.max_tokens_per_run / spend.max_tokens_per_day (subscription
      tokens) and spend.max_usd_per_run / spend.max_usd_per_day (API
      dollars). On breach the librarian pass stops early and loudly and defers
      the remaining intake (like the max_api_calls budget) rather than silently
      continuing. Off unless configured.
  • Configurable pre-run pull to sync the knowledge repo (#399). athenaeum run can now pull the knowledge repo before a run and push intake + outcomes
    after, so a run starts from and lands back to GitHub instead of drifting from
    the remote.

  • Progress heartbeat for the merge + post-compile phases (#398). Both
    phases now emit periodic progress lines, so a long-running (or wedged) run is
    legible instead of logging zero output for hours.

Fixed

  • Move-then-retire no longer leaves dangling MEMORY.md pointers (#388).
    The move-then-retire pass (retire.py) git rm'd a retired raw member but
    never rewrote the sibling per-scope MEMORY.md index that pointed at it, so
    every retirement left a dangling pointer — and unlike the compiled wiki page,
    MEMORY.md loads into every session's context, so a stale line keeps
    asserting a fact whose file is gone. The retire pass now drops each retired
    member's index pointer in the SAME commit as the deletion (conservative: only
    pointers to members that run retired; a pre-existing dangling pointer is left
    for the backfill), so index and deletion stay atomic. Cross-tree links
    (../wiki/…), URLs, anchors, headings and prose are preserved verbatim.
    • Backfill: athenaeum auto-memory prune-index (#388). A one-shot sweep
      for pointers already orphaned by pre-#388 runs — dry-run by default (prints
      the dangling-per-scope list, exit 2), --apply rewrites the affected
      indexes in one labeled, git-recoverable commit. A pointer is dangling when
      its bare <file>.md target no longer exists in the scope directory.
  • Stale pre-#330 docstrings in cli.py (#378 drive-by). _cmd_ingest_answers
    and _cmd_reresolve_questions described "builds a live Anthropic client from
    ANTHROPIC_API_KEY"; both now build through the provider seam
    (build_llm_client), matching the actual post-#330 behavior.
  • Resolver over-cluster merges are capped and floored (#400). Degenerate
    merge proposals (thousands of sources at low confidence, re-proposed and
    regenerated every run) are now suppressed by a cohesion floor plus a size cap.
  • athenaeum run now has a wall-clock deadline (#396). A hung
    post-checkpoint phase can no longer wedge a run indefinitely while holding the
    run-lock; the run aborts at the deadline instead.
  • Runlock auto-recovers an alive-but-wedged holder (#397). A stuck lock
    holder is now detected and recovered automatically instead of blocking every
    writer until a manual --force.
  • _pending_merges.md no longer regrows unbounded (#394). Fixes a
    regression of #299/#303 that let the file balloon (to ~13MB) and flood each
    run with tens of thousands of malformed-header warnings.
  • Keyword-backend scoring uses term frequency, not presence (#384).
    Corrects the keyword search backend's scoring, fixing a Python 3.13 CI flake.

Security

  • Workflow hardening for OpenSSF Scorecard (#405). Added a least-privilege
    top-level permissions: { contents: read } block to ci.yml (closes the
    Token-Permissions / High alert) and SHA-pinned the remaining tag-referenced
    third-party actions — dependabot/fetch-metadata, 1password/load-secrets-action,
    actions/checkout + actions/create-github-app-token (in promote-main.yml),
    and pypa/gh-action-pypi-publish — each with a trailing # vX.Y.Z comment,
    matching the existing convention. dependabot.yml's github-actions ecosystem
    block keeps the pins fresh automatically.