From 10d749b77f88101fd8371d54d85b1d3e9704c6db Mon Sep 17 00:00:00 2001 From: Patrick Date: Mon, 11 May 2026 07:46:33 -0400 Subject: [PATCH] feat(ops): remove Memory + Releases tabs (info still on Home) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Patrick's call: trim attune ops nav to the tabs people actually use. The Memory and Releases tabs both have low daily utility, and Releases is strictly redundant with Home's "Family snapshot" panel. What's removed: - /memory route + memory.html template - /releases route + releases.html template - data.list_memory_topics() helper + MemoryEntry dataclass (both unused after the route removal) - Nav entries for Memory and Releases in server.py - "memory, releases" mention in home.html hero subtitle What's kept: - /api/info still surfaces version data via family_versions() - Home "Family snapshot" panel still lists installed family packages — that's where the Releases info lives - The Releases KPI tile on Home now anchors to the in-page #family-snapshot section instead of /releases - attune memory CLI commands are unaffected (this is just dashboard UI) Tests updated: - test_smoke.py parametrized page list trimmed to workflows/telemetry/health - New test_removed_pages_404 asserts /memory and /releases return 404 (regression catch if someone re-adds them carelessly) Pairs naturally with the (gated, approved) spec to add a Specs tab in #230 — net effect of both: 6 tabs → 5 tabs but all 5 are high-utility for the spec-driven workflow. --- src/attune/ops/data.py | 25 --------------------- src/attune/ops/routes/dashboard.py | 13 ----------- src/attune/ops/server.py | 2 -- src/attune/ops/templates/home.html | 6 ++--- src/attune/ops/templates/memory.html | 22 ------------------ src/attune/ops/templates/releases.html | 31 -------------------------- tests/unit/ops/test_smoke.py | 12 +++++++++- 7 files changed, 14 insertions(+), 97 deletions(-) delete mode 100644 src/attune/ops/templates/memory.html delete mode 100644 src/attune/ops/templates/releases.html diff --git a/src/attune/ops/data.py b/src/attune/ops/data.py index 29a2cb0b4..8d0d23008 100644 --- a/src/attune/ops/data.py +++ b/src/attune/ops/data.py @@ -34,13 +34,6 @@ class WorkflowEntry: tier_map: dict[str, str] -@dataclass(frozen=True) -class MemoryEntry: - topic: str - snippet: str - path: str - - @dataclass(frozen=True) class FamilyVersion: package: str @@ -213,24 +206,6 @@ def list_workflows() -> list[WorkflowEntry]: return sorted(out, key=lambda w: w.name) -def list_memory_topics(config: Config, *, limit: int = 50) -> list[MemoryEntry]: - """List recent personal-memory entries, if any.""" - out: list[MemoryEntry] = [] - base = config.memory_dir - if not base.exists(): - return out - - for md in sorted(base.rglob("*.md"))[:limit]: - try: - text = md.read_text(encoding="utf-8") - except OSError: - continue - snippet = text.strip().splitlines()[0] if text.strip() else "" - topic = md.stem.replace("_", " ") - out.append(MemoryEntry(topic=topic, snippet=snippet[:240], path=str(md))) - return out - - def family_versions() -> list[FamilyVersion]: """Resolve installed versions for every related attune package.""" packages = ("attune-ai", "attune-author", "attune-rag", "attune-help", "attune-gui") diff --git a/src/attune/ops/routes/dashboard.py b/src/attune/ops/routes/dashboard.py index c690a8bc0..6ae0b604c 100644 --- a/src/attune/ops/routes/dashboard.py +++ b/src/attune/ops/routes/dashboard.py @@ -71,19 +71,6 @@ async def telemetry_page(request: Request) -> HTMLResponse: return _render(request, "telemetry.html", page="telemetry", telemetry=summary) -@router.get("/memory", response_class=HTMLResponse) -async def memory_page(request: Request) -> HTMLResponse: - cfg = request.app.state.config - entries = data.list_memory_topics(cfg) - return _render(request, "memory.html", page="memory", entries=entries) - - -@router.get("/releases", response_class=HTMLResponse) -async def releases_page(request: Request) -> HTMLResponse: - versions = data.family_versions() - return _render(request, "releases.html", page="releases", versions=versions) - - @router.get("/health", response_class=HTMLResponse) async def health_page(request: Request) -> HTMLResponse: cfg = request.app.state.config diff --git a/src/attune/ops/server.py b/src/attune/ops/server.py index 005b13c50..3c2f12753 100644 --- a/src/attune/ops/server.py +++ b/src/attune/ops/server.py @@ -41,8 +41,6 @@ def create_app(config: Config, *, runner: RunnerService | None = None) -> FastAP ("/", "Home"), ("/workflows", "Workflows"), ("/telemetry", "Telemetry"), - ("/memory", "Memory"), - ("/releases", "Releases"), ("/health", "Health"), ] diff --git a/src/attune/ops/templates/home.html b/src/attune/ops/templates/home.html index ee6b6fff1..9c76bb5ef 100644 --- a/src/attune/ops/templates/home.html +++ b/src/attune/ops/templates/home.html @@ -3,7 +3,7 @@ {% block content %}

attune ops

-

Operations dashboard for the workflow OS — workflows, telemetry, memory, releases.

+

Operations dashboard for the workflow OS — workflows, telemetry, health.

@@ -33,7 +33,7 @@

attune ops

{% if workflow_count == 0 %}attune package not importable{% else %}runnable from CLI / MCP / dashboard{% endif %}
- +
attune-ai
{% if attune_ai and attune_ai.version %}v{{ attune_ai.version }}{% else %}—{% endif %}
{{ versions|length }} family packages tracked
@@ -78,7 +78,7 @@

Daily activity (7 days)

{% endif %}
-
+

Family snapshot

    {% for v in versions %} diff --git a/src/attune/ops/templates/memory.html b/src/attune/ops/templates/memory.html deleted file mode 100644 index afff8a1e1..000000000 --- a/src/attune/ops/templates/memory.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "base.html" %} -{% block title %}Memory{% endblock %} -{% block content %} -
    -

    Memory

    -

    {{ entries|length }} entries from {{ attune_home }}/memory/.

    -
    - -{% if entries %} -
      - {% for entry in entries %} -
    • -
      {{ entry.topic }}
      -
      {{ entry.snippet }}
      -
      {{ entry.path }}
      -
    • - {% endfor %} -
    -{% else %} -

    No memory entries yet. Run attune memory capture or interact with the MCP memory tools to start building one.

    -{% endif %} -{% endblock %} diff --git a/src/attune/ops/templates/releases.html b/src/attune/ops/templates/releases.html deleted file mode 100644 index 64095a409..000000000 --- a/src/attune/ops/templates/releases.html +++ /dev/null @@ -1,31 +0,0 @@ -{% extends "base.html" %} -{% block title %}Releases{% endblock %} -{% block content %} -
    -

    Releases

    -

    Installed versions across the attune family.

    -
    - - - - - {% for v in versions %} - - - - - - {% endfor %} - -
    PackageVersionStatus
    {{ v.package }}{% if v.version %}v{{ v.version }}{% else %}—{% endif %} - {% if v.source == 'installed' %} - installed - {% else %} - not installed - {% endif %} -
    - -
    -

    Tip: install the rest of the family with pip install attune-author attune-rag attune-help attune-gui. Each gives the dashboard more to surface.

    -
    -{% endblock %} diff --git a/tests/unit/ops/test_smoke.py b/tests/unit/ops/test_smoke.py index 0691a9a9b..a9cf60802 100644 --- a/tests/unit/ops/test_smoke.py +++ b/tests/unit/ops/test_smoke.py @@ -35,7 +35,7 @@ def test_home_renders(client): @pytest.mark.parametrize( "path", - ["/workflows", "/telemetry", "/memory", "/releases", "/health"], + ["/workflows", "/telemetry", "/health"], ) def test_pages_render(client, path): response = client.get(path) @@ -43,6 +43,16 @@ def test_pages_render(client, path): assert "