feat: add Nexus — persistent conversational awareness space with live memory (#1208)
Some checks failed
Tests / lint (pull_request) Failing after 12s
Tests / test (pull_request) Has been skipped

Implements the Nexus: a dedicated conversational-only interface where Timmy
maintains a persistent session backed by his live memory store. Unlike the
main dashboard chat (which includes tool-approval flow), the Nexus is pure
dialogue with semantic memory context surfaced on every exchange.

Changes:
- src/dashboard/routes/nexus.py — GET/POST/DELETE routes; uses dedicated
  `nexus` session_id so history is isolated from the main dashboard chat
- src/dashboard/templates/nexus.html — two-column layout: chat left,
  memory sidebar + teaching panel right
- src/dashboard/templates/partials/nexus_message.html — chat partial with
  OOB memory-hits swap
- src/dashboard/templates/partials/nexus_facts.html — teaching confirmation
  + facts list partial
- src/dashboard/app.py — import and register nexus_router
- src/dashboard/templates/base.html — NEXUS link in INTEL dropdown
- static/css/mission-control.css — Nexus layout, memory sidebar, teaching
  panel styles (no inline CSS)
- tests/dashboard/test_nexus.py — 9 unit tests, all green
- docs/nexus-spec.md — full scope + acceptance criteria for #1208

Fixes #1208

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alexander Whitestone
2026-03-23 18:33:42 -04:00
parent 46edac3e76
commit 6da5bf6d6d
9 changed files with 568 additions and 0 deletions

View File

@@ -2664,3 +2664,53 @@
color: var(--bg-deep);
}
.vs-btn-save:hover { opacity: 0.85; }
/* ── Nexus ────────────────────────────────────────────────── */
.nexus-layout { max-width: 1400px; margin: 0 auto; }
.nexus-header { border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
.nexus-title { font-size: 1.4rem; font-weight: 700; color: var(--purple); letter-spacing: 0.1em; }
.nexus-subtitle { font-size: 0.8rem; color: var(--text-dim); margin-top: 0.2rem; }
.nexus-grid {
display: grid;
grid-template-columns: 1fr 320px;
gap: 1rem;
align-items: start;
}
@media (max-width: 900px) {
.nexus-grid { grid-template-columns: 1fr; }
}
.nexus-chat-panel { height: calc(100vh - 180px); display: flex; flex-direction: column; }
.nexus-chat-panel .card-body { overflow-y: auto; flex: 1; }
.nexus-empty-state {
color: var(--text-dim);
font-size: 0.85rem;
font-style: italic;
padding: 1rem 0;
text-align: center;
}
/* Memory sidebar */
.nexus-memory-hits { font-size: 0.78rem; }
.nexus-memory-label { color: var(--text-dim); font-size: 0.72rem; margin-bottom: 0.4rem; letter-spacing: 0.05em; }
.nexus-memory-hit { display: flex; gap: 0.4rem; margin-bottom: 0.35rem; align-items: flex-start; }
.nexus-memory-type { color: var(--purple); font-size: 0.68rem; white-space: nowrap; padding-top: 0.1rem; min-width: 60px; }
.nexus-memory-content { color: var(--text); line-height: 1.4; }
/* Teaching panel */
.nexus-facts-header { font-size: 0.7rem; color: var(--text-dim); letter-spacing: 0.08em; margin-bottom: 0.4rem; }
.nexus-facts-list { list-style: none; padding: 0; margin: 0; font-size: 0.8rem; }
.nexus-fact-item { color: var(--text); border-bottom: 1px solid var(--border); padding: 0.3rem 0; }
.nexus-fact-empty { color: var(--text-dim); font-style: italic; }
.nexus-taught-confirm {
font-size: 0.8rem;
color: var(--green);
background: rgba(0,255,136,0.06);
border: 1px solid var(--green);
border-radius: 4px;
padding: 0.3rem 0.6rem;
margin-bottom: 0.5rem;
}