{% extends "base.html" %} {% block title %}Curated Memory{% endblock %} {% block head_extra %} {# Shared utility for persisting filter UI state per-page in localStorage. See app/web/static/js/filter-state.js for the public API and adoption pattern. Loaded with defer so window.FilterState exists by the time the page's own DOMContentLoaded listener runs. #} {% endblock %} {% block layout %} {% set page_hero_eyebrow = "Knowledge" %} {% set page_hero_title = "Curated Memory" %} {% set page_hero_subtitle = "Approved and mandated knowledge distilled from analyst sessions — the shared organizational memory your AI agents pull at runtime via /api/memory/*." %} {% include "_page_hero.html" %}
{% if pending_review_count and pending_review_count > 0 %}
{{ pending_review_count }} pending item{{ 's' if pending_review_count != 1 else '' }} awaiting review — review them at /admin/corporate-memory
{% endif %}
{{ stats.contributors }}
Contributors
{{ stats.knowledge_count }}
Knowledge Items
{{ user_stats.authored }}
My Contributions
{% if user_contributions %} My Contributions ({{ user_contributions|length }}) {% endif %}
{# Special pseudo-category "my_upvotes" — gets translated to ?upvoted_by_me=true in loadKnowledge() and the tree filter. Replaces the old dead "My Rules" filter that sent ?category=my_rules (no row ever matched). #} {% for cat in categories %} {% endfor %}
{# Per-user dismissed-filter toggle. Dismissed items are visible by default (grayed out + an Undismiss button) — the toggle provides an opt-in cleanup view. Persisted via FilterState so it survives a page reload on the same browser. #}
{% for item in knowledge['items'] %}
{{ item.title }}
{{ item.category.replace('_', ' ').title() }} {% if item.domain %}{{ item.domain|title }}{% endif %} {% if item.confidence %}{{ '%.0f'|format(item.confidence * 100) }}%{% endif %} {% if item.source_type == 'user_verification' %}Verified{% endif %} {% if item.status == 'mandatory' %}Mandatory{% endif %} {% if item.dismissed_by_me %}Dismissed{% endif %} Added {{ item.created_at.strftime('%Y-%m-%d') if item.created_at else 'recently' }}
{# Dismiss / Undismiss — hidden entirely for mandatory items (governance rule: cannot be opted out). Toggles between Dismiss (when not yet dismissed) and Undismiss. #} {% if item.status != 'mandatory' %} {% if item.dismissed_by_me %} {% else %} {% endif %} {% endif %}
{% if item.synced %} In your rules {% endif %}
{{ item.content }}
{% else %}

No knowledge items yet.

Knowledge is extracted from team CLAUDE.local.md files every 30 minutes.

{% endfor %}
{% if user_contributions %}

My Contributions

Items you contributed via session corrections or notes. Flag items as personal to exclude from enterprise memory.

{% for item in user_contributions %}
{{ item.title }}
{{ item.category.replace('_', ' ').title() if item.category else 'N/A' }} {% if item.domain %}{{ item.domain|title }}{% endif %} {% if item.confidence %}{{ '%.0f'|format(item.confidence * 100) }}%{% endif %} {{ item.status|title }} {% if item.is_personal %}Personal{% endif %}
{{ item.content }}
{% endfor %}
{% endif %}
{% endblock %} {% block scripts %} {% endblock %}