Skip to content

v0.7.0rc1 — salience tier Phase 1 + capture attention Phase A

Pre-release
Pre-release

Choose a tag to compare

@cipher813 cipher813 released this 22 May 15:15
cadd59b

[0.7.0rc1] - 2026-05-22

Fixes

  • build_standing_set.py exemplar bias — added declarative-posture
    patterns.
    The pre-fix CONSTRAINT_EXEMPLARS list leaned heavily
    imperative ("never," "always," "must," "default to"). Surfaced
    2026-05-22: against the real prod vault the auto-selected top-10
    was 100% engineering rules — career / lifestyle / posture
    constraints spanning multi-year load-bearing facts (runway,
    recruiter posture, start-date framing, job-search mode) did not
    surface despite being equally durable, because the user encodes
    them declaratively ("Brian's stance," "current preference,"
    "passive/selective mode") rather than imperatively. Added 10
    declarative-posture exemplars representing the same constraint
    class in declarative shape. Exemplar list 22 → 30; imperative /
    declarative split now roughly balanced. ROADMAP audit-finding
    follow-up per feedback_audit_findings_become_roadmap_followups.
    Operator should re-run scripts/salience_phase0.sh snapshot && scripts/salience_phase0.sh score to verify the bias fix surfaces
    career-context memories alongside the engineering rules in the
    top-10.

Features

  • Salience tier Phase 1 — first-class standing-context recall
    (default-off, soak-gated).
    Memories explicitly promoted via
    memory_promote are injected into every <mnemon-context>
    envelope on every prompt, regardless of query similarity. The cap
    is the contract: default 15, hard ceiling 20. Plan:
    private/mnemon-salience-tier-plan-260521.md.
    • Reframed validation gate (2026-05-22). Phase 1 IS the
      validation. Earlier plan called for a synthetic A/B against the
      Phase 0 env-var-flagged form before committing to schema +
      tooling. Reframed because the injection mechanism is identical
      between the two forms — an A/B of the gated env-var path
      carries no marginal information once Phase 1 ships gated behind
      STANDING_TIER_ENABLED=false. Operator promotes ~5 career-
      context memories, flips the flag, observes ≥1 week soak for
      runway-style under-weighting recurrence vs absence. Per
      feedback_phase_gated_soak_consumer_must_be_ready: ship the
      substrate gated, flip activation at a separate milestone.
    • Schema migration: documents.tier TEXT NOT NULL DEFAULT 'situational' via _migrate_tier(). Index idx_documents_tier
      on live rows for the cap-count probe + search exclusion filter.
      Additive + harmless if STANDING_TIER_ENABLED stays off.
    • Store.promote_to_standing(id) + demote_to_situational(id)
      • list_standing() + standing_tier_status(). Promote
        raises StandingTierCapReached at the runtime cap,
        StandingTierProvenanceRejected when source_client is in
        STANDING_TIER_BLOCKED_SOURCE_CLIENTS (Layer 4 composition —
        hook-sourced memories cannot be promoted; operator-explicit
        gesture only), and StandingTierError on missing /
        invalidated docs. Idempotent re-promote returns True; demote
        of a situational doc returns False (no-op).
    • Store.search_bm25 + Store.search_vector gain
      include_standing: bool = False keyword param. Standing-tier
      docs excluded from ranked retrieval by default — they're
      injected unconditionally already; ranking them too would
      double-count and crowd the situational signal. Threaded through
      search.search() so the higher-level entry respects the
      invariant.
    • MCP tools: memory_promote(id), memory_demote(id),
      memory_list_standing() — both stdio (server.py) and
      Streamable HTTP (server_remote.py reuses the same mcp
      object). 14 → 17 registered tools.
    • CLI: mnemon standing list / promote <id> / demote <id>.
      mnemon status gains a Standing tier: N/CAP line.
    • build_context integration: when STANDING_TIER_ENABLED
      (config constant OR MNEMON_STANDING_TIER_ENABLED env override,
      accepting 1/true/yes/on), build_context calls
      memory_list_standing via the remote client in a single
      round-trip and renders the result as the "Standing context"
      sub-section ahead of "Situational recall." Phase 0 env-var path
      (MNEMON_STANDING_TIER_FILE → standing.json → standing-rendered.md
      cache) is preserved as fallback so operators retain a
      per-session override mechanism.
    • Composability invariants (all preserved):
      • Layer 0 (is_well_shaped) — capture rejection runs before
        anything reaches the standing-tier promotion path
      • Layer 1 envelope — standing block sits inside the same
        <mnemon-context> data-marking + nonce as situational
      • Layer 4 (HOOK_SOURCE_CONFIDENCE_CEILING + provenance) —
        hook-sourced memories cannot be promoted; explicit
        StandingTierProvenanceRejected rejection
      • rc16 source_key upsert — unchanged; tier orthogonal
      • Capture attention Phase A — recurrence_count accretes
        against canonical situational memories; standing-tier
        promotion is operator-gated on top of that signal
    • Soak gates for flipping default-on: (a) ≥1 week with the
      flag on; (b) observed reduction in runway-style under-weighting
      recurrence on real career-strategy conversations; (c) zero
      spurious-injection complaints from operator review of every
      promoted memory.
    • 22 new tests in tests/test_standing_tier.py covering: promote
      success / cap-rejection (cap=2 in test, 3rd raises) /
      hook-sourced rejection / invalidated rejection / missing rejection
      / cap respects invalidated (freed slot reclaimable) / demote
      round-trip / demote idempotent on situational / demote frees cap
      slot / list_standing ordering + content / search excludes by
      default / search includes when requested / build_context
      flag-off no-fetch / flag-on memory_list_standing call /
      env-var truthy value parsing. Suite 814 → 836 passing
      (test_server_remote.py tool-count assertions bumped 14 → 17).

Schema

  • documents.tier TEXT NOT NULL DEFAULT 'situational'
    additive migration in _migrate_tier() after the existing
    _migrate_recurrence_count. Index idx_documents_tier scoped to
    live rows for cap-count + search-filter queries.

  • Capture attention Phase A — recurrence-weighted memory convergence
    (default-off, soak-gated).
    When a new save's content is semantically
    close to ≥2 prior memories spanning distinct sessions, capture
    attention preserves the new memory + inserts 'restates' relations
    to each cluster member + boosts the canonical neighbor's confidence

    • increments the canonical's new recurrence_count column. The
      cluster of restatements stays discoverable; the load-bearing signal
      accretes on the canonical; MMR diversity at recall naturally
      suppresses near-duplicates without us dropping them at capture.
      Plan: private/mnemon-capture-attention-plan-260522.md. Driver: the
      2026-05-22 finding that load-bearing facts stated across many
      sessions land as fragmented memories rather than a single canonical
      assertion (the operator was implicitly substituting for a missing
      mechanism).
    • SOTA invariant: preserve+relate+boost, never skip-the-save.
      Earlier draft considered "boost canonical + skip the new save"
      as the auto-apply path — rejected because each restatement
      carries different framing and discarding it throws away the very
      signal the recurrence detector is honoring. The institutional
      pattern is preserve the data, link via relations, accrete the
      importance signal — operator-reviewed merge is Phase C of the
      plan, not Phase A's job.
    • Embedding-only (no LLM dependency). Same SOTA-for-public-
      release-constraint logic that drove build_standing_set.py's
      embedding-based scorer (the roadmapped LLM-judge opt-in P2 item
      composes as an advanced mode but isn't required).
    • Feature flag CAPTURE_ATTENTION_ENABLED default-off through
      soak. Two acceptance criteria to flip default-on (per plan
      §"Soak acceptance criteria"): (1) boost_rate ≤ 0.25 over a 7-day
      window measured via mnemon attention-status; (2) ≥80% precision
      on a 20-canonical manual review.
    • correction_of parameter on Store.save() (forward-compat
      for salience-tier Phase 2 promotion signals). When set, capture
      attention is skipped — operator explicit gesture beats automated
      recurrence detection.
    • mnemon attention-status CLI — soak monitor: boost-rate
      ratio over 7 days, recurrence-count distribution, top-10
      canonicals, last-10 'restates' relations audit trail.
    • scripts/calibrate_capture_threshold.py — data-tuned
      threshold selection. Samples N pairs from the operator's vault
      snapshot, prompts for same/different tagging, computes
      precision-recall at {0.70, 0.75, 0.80, 0.85, 0.90}, recommends
      the precision-leaning sweet spot. Persists tagged pairs to
      tests/fixtures/capture_attention_pairs.json for regression
      locking.
    • Failure mode: named exception + WARN swallow. Embedder /
      vecstore unavailability raises CaptureAttentionUnavailableError
      from apply_capture_attention(); Store.save() catches +
      logger.warnings + continues (the new memory is saved; only the
      recurrence-boost side effect is skipped). Acceptable swallow per
      feedback_no_silent_fails category (b) — secondary observability
      hung off a primary save path that records the failure.
    • Composes with the existing layered defenses unchanged.
      Capture attention runs AFTER Layer 0 (is_well_shaped rejects
      scaffolding before the path is reached) + AFTER Layer 4 ceiling
      (HOOK_SOURCE_CONFIDENCE_CEILING clamp survives the boost).
      'restates' is a new relation type — doesn't collide with the
      existing 'supersedes' / 'contradicts' / 'related'.
    • 13 new tests in tests/test_capture_attention.py covering: the
      preserve-everything invariant, feature-flag-off no-behavior-
      change, distinct-sessions trigger, same-session no-trigger,
      threshold respected, hook ceiling, user uncapped, pinned-canonical
      selection, correction_of override, fail-loud on embedder
      unavailability, schema migration idempotency. Suite 801 → 814
      passing.

Schema

  • documents.recurrence_count INTEGER NOT NULL DEFAULT 0
    additive migration in _migrate_recurrence_count(). Pre-existing
    rows get count=0 and recurrence detection starts forward from the
    next save. Harmless if CAPTURE_ATTENTION_ENABLED stays off.