Skip to content

P1b — SLM: memory-lifecycle aggregator + MemoryLifecycleTab monitoring tab #12632

Description

@mrveiss

Plan (execute from here): docs/superpowers/plans/2026-07-26-system-lifecycle-observability.md — find this task's section.

Part of umbrella #12630. Depends on #12631. Design: docs/superpowers/specs/2026-07-26-system-lifecycle-observability-design.md.

Phase 1b — SLM aggregator + monitoring tab.

  • autobot-slm-backend: thin endpoint calling the node GET /api/memory/lifecycle via the SLM→node client; fleet-aware (single node now, structured to fan out); degrades to degraded: true + empty sections when node down.
  • autobot-slm-frontend/src/views/monitoring/MemoryLifecycleTab.vue under /monitoring (router child + nav entry). Reinforcement leaderboard + cold-facts table + "what decay would prune" table with a clear "dry-run — nothing is deleted" affordance. i18n across all SLM locales.

Tests: aggregator returns node payload; degraded path when node absent; tab renders sections.

Activity

  1. mrveiss commented on Aug 22, 2026

    @mrveiss
    OwnerAuthor

    Part 1 of 2 landed — #14653 merged as 1aa44f734. This issue stays open; the frontend half is not built.

    Done

    The SLM aggregator: GET /api/memory/lifecycle, admin-gated, calling the node endpoint from #12631 (merged as 00720b5d1).

    Verified in base: the aggregator module, the verify-on TLS default, the SSOT-derived limit ceiling, the gated mount, and 8 aggregator tests.

    The property that carried the design is that degraded composes — the node reports its own partial reads, so a proxy surfacing only transport failures would show a node whose decay section is broken as perfectly healthy. Each failure cause stays distinct rather than collapsing into "unreachable": 403 means the key is wrong, 404 means the node predates #12631, a timeout means alive but slow, and an operator acts differently on each.

    Still open — the frontend half

    • autobot-slm-frontend/src/composables/useMemoryLifecycleApi.ts
    • autobot-slm-frontend/src/views/monitoring/MemoryLifecycle.vue — reinforcement leaderboard, cold-facts table, and the "what decay would prune" table with a clear dry-run affordance
    • Router child under /monitoring and the nav entry
    • The monitoring.memory.* key block across every SLM locale

    Two corrections from review worth carrying forward

    TLS verification defaulted OFF. The module cited api/voice_proxy.py as its pattern and inverted it — voice_proxy reads AUTOBOT_SKIP_TLS_VERIFY and verifies unless told not to; this required opting in, on the channel carrying the internal API key. Now the same variable and polarity, so one switch covers every node proxy.

    The limit ceiling was a magic number. le=100 inlined in the Query tripped the #694 hardcoded-value check. Fixed with QueryDefaults.MAX_SEARCH_LIMIT rather than the KNOWLEDGE_DEFAULT_LIMIT the linter suggested — both are 100 today, but one is a maximum and the other a default, and a ceiling that tracks a default drifts the moment the default moves.

    Note on the stack

    This was built as a stacked PR on issue-12631. Worth recording for anyone doing the same here: while stacked it ran 1 CI check, because the workflows filter on base branch. It only got the full suite after #14651 merged and GitHub retargeted it. A stacked PR must never be merged while stacked — its green means nothing.

  2. github-actions commented on Aug 22, 2026

    @github-actions
    Contributor

    PR #14653 (merged to Dev_new_gui) references this issue with a close keyword.

    feat(memory): SLM aggregator for the node lifecycle view (#12632, part 1 of 2)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  3. mrveiss commented on Aug 23, 2026

    @mrveiss
    OwnerAuthor

    Handoff — everything needed to finish this from the issue alone

    The backend half is merged and live. What follows is the frontend half, with the details verified against the tree rather than copied from the plan.

    Already done (merged, no action)

    The payload the tab renders

    {
      "nodes": [
        {
          "node": "<node base url>",
          "degraded": false,
          "reinforcement": { "hot": [ ... ], "cold": [ ... ] },
          "decay": { "last_run": "...", "config": { ... }, "prune_preview": [ ... ] }
        }
      ],
      "degraded": false
    }
    • Each hot/cold entry: fact_id, quality_score, access_count, last_accessed, effective_score
    • Each prune_preview entry: fact_id, reasons: [str] — the reasons carry values, e.g. "quality 0.01 below floor 0.10"
    • decay.config: epoch_set, quality_floor, max_age_days, max_per_run, scan_limit
    • An unreachable node still carries every section key, plus error — one of node_unreachable, node_timeout, node_status_<code>, node_bad_payload, internal_api_key_not_configured. Render the cause; they are distinct on purpose (403 = wrong key, 404 = node predates P1a — Node: GET /api/memory/lifecycle (reinforcement + dry-run prune preview) #12631, timeout = alive but slow).
    • degraded composes: it is true if the node reports its own partial read, not only on transport failure.

    Query param: limit, default 20, max QueryDefaults.MAX_SEARCH_LIMIT (100).

    To build

    • autobot-slm-frontend/src/composables/useMemoryLifecycleApi.ts — fetchLifecycle(limit?)
    • autobot-slm-frontend/src/views/monitoring/MemoryLifecycle.vue — reinforcement leaderboard, cold-facts table, and a "what decay would prune" table
    • autobot-slm-frontend/src/router/index.ts — a /monitoring/memory child
    • Nav entry alongside the other monitoring tabs
    • autobot-slm-frontend/src/locales/en.json — a monitoring.memory.* key block

    Correction to the plan on locales. The plan says "SLM locale files (all locales)". Verified: this frontend registers only en — src/i18n/index.ts imports @/locales/en.json and nothing else, and src/locales/ contains that one file. The 11-locale rule applies to autobot-frontend, not here. One file to touch, not eleven.

    Mirror an existing tab in src/views/monitoring/ — AlertsMonitor.vue has a test alongside it (AlertsMonitor.test.ts) worth copying the shape of.

    The one thing the UI must not get wrong

    The prune table is a dry-run preview — nothing is deleted, and that has to be unmistakable in the UI. It is the list an operator reviews before enabling enforcement. A table of facts headed for deletion, without a clear affordance saying nothing has happened yet, invites exactly the misreading this feature exists to prevent.

    Also worth surfacing: decay.config.epoch_set: false means pruning is disabled entirely — the single most consequential thing an operator can be wrong about here, and invisible unless the tab says so.

    Acceptance

    • The tab renders all three sections from one aggregator call
    • A degraded node shows which cause, not a generic error
    • The prune table states plainly that it deletes nothing
    • epoch_set: false is visible as "pruning disabled"

    Related

    Umbrella #12630. Phase 2 (#12633 node breaker states, #12634 SLM lifecycle aggregate) is unstarted and independent of this. #14655 is a prune-predicate bug found while building P1a, deliberately unfixed — this umbrella's non-goals forbid changing prune behaviour in P1/P2.

  4. added this to the v0.10.0 milestone on Sep 12, 2026
  5. mrveiss commented on Sep 12, 2026

    @mrveiss
    OwnerAuthor

    Stale-issue sweep (never auto-closed — Dev_new_gui wasn't GitHub's default branch at merge time). Verified against current origin/main; leaving open.

    • Aggregator: MET — autobot-slm-backend/api/memory_lifecycle_proxy.py:69-70 GET /lifecycle, registered main.py:713.
    • Frontend MemoryLifecycleTab: NOT MET — no *MemoryLifecycle* file exists under autobot-slm-frontend/src, no router/nav entry.

    The delivering PR (#14653) says so itself: "Does not close #12632... frontend tab, composable, router child, nav entry, locale blocks are not in it." Backend-only so far; the frontend half is undelivered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions