diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..b1c47cd --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,64 @@ +# Deploy the CogniFold showcase site (docs-site/) to GitHub Pages. +# +# ONE-TIME SETUP: enable Pages in the repo under +# Settings → Pages → Build and deployment → Source: "GitHub Actions". +# Without that, the deploy-pages step will fail with a "Pages not enabled" error. +# +# The site is data-driven from docs-site/data/memory_coverage.json. That file is +# a committed copy so the site renders standalone, but the SINGLE SOURCE OF TRUTH +# is src/cognifold/brain/memory_coverage.json — this workflow copies it into +# docs-site/data/ at build time so the published site always matches the canonical +# taxonomy. + +name: Deploy Pages + +on: + push: + branches: [main] + workflow_dispatch: + +# Standard GitHub Pages permissions. +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment; let in-progress runs finish. +concurrency: + group: pages + cancel-in-progress: false + +jobs: + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Sync canonical memory coverage data into the site + # src/cognifold/brain/memory_coverage.json is the single source of truth. + # Copy it over the committed standalone copy so the published site stays + # in sync. If the canonical file is absent (e.g. not yet merged), fall + # back to the committed copy already in docs-site/data/. + run: | + if [ -f src/cognifold/brain/memory_coverage.json ]; then + cp src/cognifold/brain/memory_coverage.json docs-site/data/memory_coverage.json + echo "Synced canonical memory_coverage.json into docs-site/data/." + else + echo "Canonical src/cognifold/brain/memory_coverage.json not found; using committed copy." + fi + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs-site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/docs-site/css/styles.css b/docs-site/css/styles.css new file mode 100644 index 0000000..a85d867 --- /dev/null +++ b/docs-site/css/styles.css @@ -0,0 +1,372 @@ +/* ========================================================================== + CogniFold showcase — dark neural-glow theme + Single stylesheet, no build step. Variables drive the whole palette. + ========================================================================== */ + +:root { + --bg: #05060c; + --bg-soft: #0a0d1a; + --panel: #0e1220; + --panel-2: #131829; + --border: #1d2540; + --text: #e8ecff; + --text-dim: #9aa3c7; + --text-faint: #6b73a0; + + /* Neural accent palette */ + --glow-cyan: #38e8ff; + --glow-violet: #9b6bff; + --glow-magenta: #ff5cc8; + --glow-amber: #ffb347; + + /* Status colors */ + --covered: #38e8ff; + --partial: #ffb347; + --planned: #4a5380; + + --radius: 16px; + --radius-sm: 10px; + --maxw: 1180px; + + --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + --mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, monospace; +} + +* { box-sizing: border-box; } + +html { scroll-behavior: smooth; scroll-padding-top: 80px; } + +body { + margin: 0; + font-family: var(--font); + color: var(--text); + background: var(--bg); + line-height: 1.65; + -webkit-font-smoothing: antialiased; + overflow-x: hidden; +} + +/* Ambient glow backdrop */ +body::before { + content: ""; + position: fixed; + inset: 0; + z-index: -2; + background: + radial-gradient(900px 600px at 78% -8%, rgba(155, 107, 255, 0.18), transparent 60%), + radial-gradient(800px 600px at 10% 6%, rgba(56, 232, 255, 0.14), transparent 55%), + radial-gradient(700px 700px at 50% 110%, rgba(255, 92, 200, 0.10), transparent 60%); + pointer-events: none; +} + +a { color: var(--glow-cyan); text-decoration: none; } +a:hover { text-decoration: underline; } + +h1, h2, h3 { line-height: 1.2; letter-spacing: -0.02em; margin: 0 0 0.5em; } + +section { padding: 96px 24px; } +.wrap { max-width: var(--maxw); margin: 0 auto; } + +.eyebrow { + text-transform: uppercase; + letter-spacing: 0.18em; + font-size: 12px; + font-weight: 700; + color: var(--glow-cyan); + margin-bottom: 14px; +} + +.section-title { font-size: clamp(28px, 4vw, 44px); font-weight: 800; } +.section-sub { color: var(--text-dim); max-width: 720px; font-size: 17px; } + +/* ===== Nav ================================================================ */ +.nav { + position: sticky; + top: 0; + z-index: 50; + backdrop-filter: blur(14px); + background: rgba(5, 6, 12, 0.72); + border-bottom: 1px solid var(--border); +} +.nav-inner { + max-width: var(--maxw); + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between; + padding: 14px 24px; +} +.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 18px; letter-spacing: -0.02em; } +.brand .dot { + width: 12px; height: 12px; border-radius: 50%; + background: radial-gradient(circle at 30% 30%, var(--glow-cyan), var(--glow-violet)); + box-shadow: 0 0 14px var(--glow-cyan); +} +.nav-links { display: flex; gap: 26px; align-items: center; } +.nav-links a { color: var(--text-dim); font-size: 15px; font-weight: 500; } +.nav-links a:hover { color: var(--text); text-decoration: none; } +.nav-links .gh { color: var(--text); } +@media (max-width: 760px) { .nav-links a:not(.gh) { display: none; } } + +/* ===== Buttons ============================================================ */ +.btn { + display: inline-flex; align-items: center; gap: 9px; + padding: 13px 22px; border-radius: 999px; + font-weight: 600; font-size: 15px; + border: 1px solid var(--border); + transition: transform 0.15s ease, box-shadow 0.25s ease, border-color 0.2s; +} +.btn:hover { transform: translateY(-2px); text-decoration: none; } +.btn-primary { + color: #05060c; + background: linear-gradient(135deg, var(--glow-cyan), var(--glow-violet)); + border-color: transparent; + box-shadow: 0 0 24px rgba(56, 232, 255, 0.35); +} +.btn-primary:hover { box-shadow: 0 0 36px rgba(155, 107, 255, 0.5); } +.btn-ghost { color: var(--text); background: rgba(255, 255, 255, 0.03); } +.btn-ghost:hover { border-color: var(--glow-cyan); color: var(--glow-cyan); } + +/* ===== Hero =============================================================== */ +.hero { + display: grid; + grid-template-columns: 1.15fr 0.85fr; + gap: 48px; + align-items: center; + padding-top: 80px; + padding-bottom: 80px; +} +.hero h1 { + font-size: clamp(36px, 5.4vw, 64px); + font-weight: 850; + background: linear-gradient(120deg, #ffffff 25%, var(--glow-cyan) 70%, var(--glow-violet)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} +.hero .tagline { font-size: 19px; color: var(--text-dim); max-width: 560px; } +.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 30px; } +.hero-meta { display: flex; gap: 26px; margin-top: 36px; flex-wrap: wrap; } +.hero-meta .stat { display: flex; flex-direction: column; } +.hero-meta .stat b { font-size: 24px; font-weight: 800; color: var(--text); } +.hero-meta .stat span { font-size: 13px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.08em; } + +@media (max-width: 900px) { + .hero { grid-template-columns: 1fr; text-align: center; } + .hero .tagline { margin-inline: auto; } + .hero-cta, .hero-meta { justify-content: center; } + .ring-wrap { margin-inline: auto; } +} + +/* Coverage ring */ +.ring-wrap { display: flex; flex-direction: column; align-items: center; gap: 18px; } +.ring { + position: relative; width: 300px; height: 300px; + filter: drop-shadow(0 0 30px rgba(56, 232, 255, 0.25)); +} +.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); } +.ring .track { fill: none; stroke: var(--border); stroke-width: 16; } +.ring .progress { + fill: none; stroke: url(#ringGrad); stroke-width: 16; stroke-linecap: round; + transition: stroke-dashoffset 1.8s cubic-bezier(0.16, 1, 0.3, 1); +} +.ring .center { + position: absolute; inset: 0; + display: flex; flex-direction: column; align-items: center; justify-content: center; + text-align: center; +} +.ring .pct { font-size: 58px; font-weight: 850; letter-spacing: -0.03em; } +.ring .pct .sym { font-size: 30px; color: var(--text-dim); } +.ring .label { font-size: 13px; color: var(--text-dim); max-width: 170px; line-height: 1.4; } +.ring-caption { font-size: 14px; color: var(--text-faint); } + +/* ===== Brain section ===================================================== */ +.brain-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 48px; } +@media (max-width: 980px) { .brain-grid { grid-template-columns: 1fr; } } + +.brain-stage { + position: relative; + background: radial-gradient(circle at 50% 40%, rgba(56, 232, 255, 0.06), transparent 70%), var(--panel); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 18px; + min-height: 440px; + display: flex; align-items: center; justify-content: center; +} +.brain-stage svg { width: 100%; height: auto; max-height: 460px; } + +/* anatomical region styling */ +.region { cursor: pointer; transition: opacity 0.25s, filter 0.25s; } +.region .lobe { transition: fill 0.4s, filter 0.4s, stroke 0.3s; stroke-width: 1.2; } +.region-label { + font-family: var(--mono); font-size: 11px; fill: var(--text-dim); + pointer-events: none; transition: fill 0.25s; +} +.region.dim { opacity: 0.32; } +.region.active .lobe { filter: drop-shadow(0 0 10px currentColor); } +.region.highlight .lobe { stroke: #fff; stroke-width: 2.2; filter: drop-shadow(0 0 16px currentColor); } +.region.highlight .region-label { fill: #fff; } + +.brain-legend { display: flex; gap: 18px; justify-content: center; margin-top: 10px; flex-wrap: wrap; } +.brain-legend .item { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-dim); } +.brain-legend .swatch { width: 12px; height: 12px; border-radius: 3px; } + +/* Systems side panel */ +.systems-panel { display: flex; flex-direction: column; gap: 12px; max-height: 540px; overflow-y: auto; padding-right: 6px; } +.systems-panel::-webkit-scrollbar { width: 8px; } +.systems-panel::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; } + +.sys-card { + background: var(--panel); + border: 1px solid var(--border); + border-left: 3px solid var(--planned); + border-radius: var(--radius-sm); + padding: 14px 16px; + cursor: pointer; + transition: transform 0.15s, border-color 0.2s, background 0.2s; +} +.sys-card:hover, .sys-card.active, .sys-card.active-region { + transform: translateX(4px); + background: var(--panel-2); +} +.sys-card.active-region { box-shadow: 0 0 0 1px var(--glow-cyan), 0 0 18px rgba(56, 232, 255, 0.25); } +.sys-card.s-covered { border-left-color: var(--covered); } +.sys-card.s-partial { border-left-color: var(--partial); } +.sys-card.s-planned { border-left-color: var(--planned); } +.sys-card.s-covered:hover, .sys-card.s-covered.active { border-color: var(--covered); } +.sys-card.s-partial:hover, .sys-card.s-partial.active { border-color: var(--partial); } + +.sys-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; } +.sys-name { font-weight: 700; font-size: 15.5px; } +.sys-region { font-size: 12px; color: var(--text-faint); font-family: var(--mono); } +.chip { + font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px; + text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap; +} +.chip.covered { color: #04222a; background: var(--covered); } +.chip.partial { color: #2a1c04; background: var(--partial); } +.chip.planned { color: var(--text-dim); background: rgba(74, 83, 128, 0.3); border: 1px solid var(--planned); } + +.sys-detail { margin-top: 10px; font-size: 14px; color: var(--text-dim); display: none; } +.sys-card.active .sys-detail { display: block; } +.sys-detail .row { margin-top: 8px; } +.sys-detail .row b { color: var(--text); font-weight: 600; } +.sys-detail .evidence { font-family: var(--mono); font-size: 12px; color: var(--glow-cyan); } + +/* Tooltip */ +.tooltip { + position: fixed; z-index: 100; pointer-events: none; + background: var(--panel-2); border: 1px solid var(--border); + border-radius: 10px; padding: 10px 13px; max-width: 260px; + font-size: 13px; color: var(--text); box-shadow: 0 12px 40px rgba(0,0,0,0.6); + opacity: 0; transform: translateY(6px); transition: opacity 0.15s, transform 0.15s; +} +.tooltip.show { opacity: 1; transform: translateY(0); } +.tooltip .t-title { font-weight: 700; margin-bottom: 3px; } +.tooltip .t-status { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; } + +/* ===== Architecture ====================================================== */ +.cls-diagram { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 44px; position: relative; } +@media (max-width: 860px) { .cls-diagram { grid-template-columns: 1fr; } } +.cls-layer { + background: var(--panel); border: 1px solid var(--border); + border-radius: var(--radius); padding: 26px 22px; position: relative; + transition: transform 0.2s, box-shadow 0.3s; +} +.cls-layer:hover { transform: translateY(-4px); } +.cls-layer.l1 { box-shadow: inset 0 0 0 1px rgba(56, 232, 255, 0.25); } +.cls-layer.l2 { box-shadow: inset 0 0 0 1px rgba(155, 107, 255, 0.25); } +.cls-layer.l3 { box-shadow: inset 0 0 0 1px rgba(255, 92, 200, 0.25); } +.cls-layer .badge { + font-family: var(--mono); font-size: 12px; font-weight: 700; letter-spacing: 0.05em; + padding: 4px 10px; border-radius: 6px; display: inline-block; margin-bottom: 14px; +} +.cls-layer.l1 .badge { color: var(--glow-cyan); background: rgba(56, 232, 255, 0.1); } +.cls-layer.l2 .badge { color: var(--glow-violet); background: rgba(155, 107, 255, 0.1); } +.cls-layer.l3 .badge { color: var(--glow-magenta); background: rgba(255, 92, 200, 0.1); } +.cls-layer h3 { font-size: 21px; } +.cls-layer p { color: var(--text-dim); font-size: 14.5px; margin: 0; } +.cls-layer .region-tag { font-size: 12px; color: var(--text-faint); font-family: var(--mono); margin-top: 12px; } +.cls-arrow { + position: absolute; top: 50%; font-size: 22px; color: var(--text-faint); + transform: translateY(-50%); z-index: 2; +} +.arch-note { + margin-top: 40px; padding: 24px 28px; border-radius: var(--radius); + background: linear-gradient(135deg, rgba(155,107,255,0.08), rgba(56,232,255,0.05)); + border: 1px solid var(--border); +} +.arch-note h3 { font-size: 18px; color: var(--glow-violet); } +.arch-note p { color: var(--text-dim); margin: 0; font-size: 15px; } +.time-strip { + margin-top: 18px; text-align: center; font-family: var(--mono); font-size: 13px; + color: var(--text-faint); border-top: 1px dashed var(--border); padding-top: 16px; +} + +/* ===== Benchmarks ======================================================== */ +.bench-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 44px; } +@media (max-width: 980px) { .bench-grid { grid-template-columns: repeat(2, 1fr); } } +@media (max-width: 520px) { .bench-grid { grid-template-columns: 1fr; } } +.bench-card { + background: var(--panel); border: 1px solid var(--border); + border-radius: var(--radius); padding: 22px 20px; transition: transform 0.18s, border-color 0.2s; +} +.bench-card:hover { transform: translateY(-4px); border-color: var(--glow-cyan); } +.bench-card .score { + font-size: 32px; font-weight: 850; letter-spacing: -0.02em; + background: linear-gradient(120deg, var(--glow-cyan), var(--glow-violet)); + -webkit-background-clip: text; background-clip: text; color: transparent; +} +.bench-card .metric { font-size: 12.5px; color: var(--text-faint); font-family: var(--mono); margin-top: 2px; } +.bench-card .name { font-size: 15px; font-weight: 700; margin-top: 12px; } +.bench-card .desc { font-size: 13px; color: var(--text-dim); margin-top: 4px; } +.bench-foot { margin-top: 22px; font-size: 13px; color: var(--text-faint); } + +/* ===== Quickstart ======================================================== */ +.qs-grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 32px; margin-top: 44px; align-items: start; } +@media (max-width: 880px) { .qs-grid { grid-template-columns: 1fr; } } +.code-block { + background: #04050a; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; +} +.code-block .code-head { + display: flex; align-items: center; gap: 7px; padding: 11px 16px; + border-bottom: 1px solid var(--border); background: var(--panel); +} +.code-block .code-head .d { width: 11px; height: 11px; border-radius: 50%; } +.code-block .code-head .d.r { background: #ff5f57; } +.code-block .code-head .d.y { background: #febc2e; } +.code-block .code-head .d.g { background: #28c840; } +.code-block .code-head .title { margin-left: 8px; font-family: var(--mono); font-size: 12px; color: var(--text-faint); } +.code-block pre { margin: 0; padding: 20px; overflow-x: auto; font-family: var(--mono); font-size: 13.5px; line-height: 1.7; } +.code-block .tok-comment { color: var(--text-faint); } +.code-block .tok-cmd { color: var(--glow-cyan); } +.code-block .tok-str { color: var(--glow-amber); } + +.integrations { display: flex; flex-direction: column; gap: 14px; } +.int-card { + background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); + padding: 18px 20px; transition: border-color 0.2s, transform 0.15s; +} +.int-card:hover { border-color: var(--glow-violet); transform: translateY(-2px); } +.int-card h3 { font-size: 16px; margin-bottom: 6px; } +.int-card p { color: var(--text-dim); font-size: 14px; margin: 0; } +.int-card .arrow { color: var(--glow-cyan); } + +/* ===== Footer ============================================================ */ +.footer { + border-top: 1px solid var(--border); padding: 40px 24px; text-align: center; + color: var(--text-faint); font-size: 14px; +} +.footer .links { display: flex; gap: 22px; justify-content: center; margin-bottom: 14px; flex-wrap: wrap; } +.footer .links a { color: var(--text-dim); } + +/* Reveal-on-scroll */ +.reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.7s ease, transform 0.7s ease; } +.reveal.in { opacity: 1; transform: none; } + +@media (prefers-reduced-motion: reduce) { + * { scroll-behavior: auto !important; } + .reveal { opacity: 1; transform: none; transition: none; } + .ring .progress { transition: none; } +} diff --git a/docs-site/data/memory_coverage.json b/docs-site/data/memory_coverage.json new file mode 100644 index 0000000..3a6c50f --- /dev/null +++ b/docs-site/data/memory_coverage.json @@ -0,0 +1,144 @@ +{ + "version": "1.0", + "methodology": "Each human memory system is scored covered (1.0), partial (0.5), or planned (0.0). The overall coverage percentage is the weight-normalized sum of status scores across all systems, where weight reflects each system's relative importance to an always-on agent memory. This file is the single source of truth, mirrored from src/cognifold/brain/memory_coverage.json.", + "status_scores": { + "covered": 1.0, + "partial": 0.5, + "planned": 0.0 + }, + "overall_coverage_pct": 60, + "systems": [ + { + "id": "working", + "name": "Working Memory", + "taxonomy_group": "Short-term / Online", + "brain_region": "Prefrontal cortex", + "status": "covered", + "weight": 1.0, + "cognifold_mechanism": "Hierarchical context window (immediate / working / background) surfaces the most relevant nodes per event via composite scoring.", + "evidence": "scoring/hierarchical.py; BABILong 96.0% EM", + "description": "Transient, capacity-limited store that holds and manipulates information for the task at hand. CogniFold realizes it as a budgeted, three-level context window assembled fresh for every event." + }, + { + "id": "episodic", + "name": "Episodic Memory", + "taxonomy_group": "Declarative", + "brain_region": "Hippocampus", + "status": "covered", + "weight": 1.0, + "cognifold_mechanism": "EVENT nodes capture what-happened-when verbatim; entity-anchored boosting and raw-turn preservation keep episodes retrievable.", + "evidence": "models/event.py; LoCoMo 82.8% J-Score", + "description": "Memory for specific autobiographical events bound to a time and place. The Hippocampal EVENT layer is CogniFold's verbatim episodic substrate." + }, + { + "id": "semantic", + "name": "Semantic Memory", + "taxonomy_group": "Declarative", + "brain_region": "Neocortex", + "status": "covered", + "weight": 1.0, + "cognifold_mechanism": "CONCEPT nodes emerge from repeated EVENTs; the agent folds episodes into generalized, grounded knowledge with explainable reasoning.", + "evidence": "agent/agent.py; LongMemEval ~93%", + "description": "General world knowledge and facts abstracted away from any single experience. The Neocortical CONCEPT layer crystallizes semantics from the event stream." + }, + { + "id": "prospective", + "name": "Prospective Memory (Intent)", + "taxonomy_group": "Declarative", + "brain_region": "Prefrontal cortex", + "status": "covered", + "weight": 1.2, + "cognifold_mechanism": "INTENT nodes crystallize proactively from accumulated concepts and time anchors — remembering to act in the future is a property of the topology, not the agent policy.", + "evidence": "models/node.py (IntentStatus); intent/; ToMi 91.6% EM", + "description": "Remembering to carry out intended actions at the right future moment. This proactive intent crystallization is CogniFold's unique differentiator versus passive memory stores." + }, + { + "id": "temporal", + "name": "Temporal Memory", + "taxonomy_group": "Organizational", + "brain_region": "Hippocampus / Entorhinal", + "status": "covered", + "weight": 0.9, + "cognifold_mechanism": "TIME nodes anchor deadlines and schedules; recency decay and urgency boosting make approaching deadlines salient in retrieval.", + "evidence": "temporal/extractor.py; StreamingQA 78.4% EM", + "description": "Encoding of when events occurred and their order, enabling deadline awareness and time-sensitive reasoning. TIME nodes plus recency/urgency scoring provide CogniFold's temporal axis." + }, + { + "id": "consolidation", + "name": "Memory Consolidation", + "taxonomy_group": "Maintenance", + "brain_region": "Hippocampus → Neocortex", + "status": "partial", + "weight": 0.9, + "cognifold_mechanism": "Inter-session consolidation merges similar concepts and reinforces grounded structure; offline systems-level replay is on the roadmap.", + "evidence": "merge_similar_concepts; --event-stream consolidation logs", + "description": "The gradual transfer of memories from fast hippocampal storage to durable neocortical representations. CogniFold consolidates at session boundaries; richer sleep-like offline replay is planned." + }, + { + "id": "forgetting", + "name": "Adaptive Forgetting", + "taxonomy_group": "Maintenance", + "brain_region": "Distributed", + "status": "partial", + "weight": 0.7, + "cognifold_mechanism": "Recency decay lowers stale node salience and orphan pruning removes unsupported concepts; principled importance-weighted decay is in progress.", + "evidence": "scoring/ranker.py (decay_rate); prune_orphan_concepts", + "description": "Active down-weighting and removal of low-value memories to keep the store relevant. CogniFold decays and prunes today; calibrated, value-aware forgetting is the next step." + }, + { + "id": "procedural", + "name": "Procedural Memory", + "taxonomy_group": "Non-declarative", + "brain_region": "Basal ganglia / Cerebellum", + "status": "planned", + "weight": 0.6, + "cognifold_mechanism": "Planned: skills and learned action sequences captured as reusable procedure nodes distinct from declarative concepts.", + "evidence": "Roadmap", + "description": "Implicit memory for skills and habits — how to do things. Not yet modeled; a procedure layer is on the roadmap." + }, + { + "id": "priming", + "name": "Priming", + "taxonomy_group": "Non-declarative", + "brain_region": "Neocortex (sensory)", + "status": "planned", + "weight": 0.4, + "cognifold_mechanism": "Planned: residual activation that biases retrieval toward recently or repeatedly encountered patterns.", + "evidence": "Roadmap", + "description": "Implicit facilitation where exposure to a stimulus speeds later processing of related stimuli. A retrieval-bias mechanism is planned." + }, + { + "id": "conditioning", + "name": "Associative Conditioning", + "taxonomy_group": "Non-declarative", + "brain_region": "Amygdala / Cerebellum", + "status": "planned", + "weight": 0.4, + "cognifold_mechanism": "Planned: reinforcement-driven edge strengthening between co-occurring stimuli and outcomes.", + "evidence": "Roadmap", + "description": "Learned associations between stimuli and responses through repeated pairing. Reinforcement-weighted edges are a planned extension." + }, + { + "id": "affective", + "name": "Affective Memory", + "taxonomy_group": "Modulatory", + "brain_region": "Amygdala", + "status": "planned", + "weight": 0.5, + "cognifold_mechanism": "Planned: emotional salience tags that modulate consolidation strength and retrieval priority.", + "evidence": "Roadmap", + "description": "Emotional coloring of memories that biases what is stored and recalled. Salience-based modulation is on the roadmap." + }, + { + "id": "sensory", + "name": "Sensory Memory", + "taxonomy_group": "Short-term / Online", + "brain_region": "Sensory cortices", + "status": "planned", + "weight": 0.4, + "cognifold_mechanism": "Planned: ultra-short multimodal buffers feeding raw perceptual traces into the event stream.", + "evidence": "Roadmap", + "description": "Brief, high-fidelity retention of raw perceptual input before it decays or enters working memory. Multimodal sensory buffers are planned." + } + ] +} diff --git a/docs-site/index.html b/docs-site/index.html new file mode 100644 index 0000000..bcea75e --- /dev/null +++ b/docs-site/index.html @@ -0,0 +1,214 @@ + + + + + + CogniFold — Brain-Inspired Always-On Agent Memory + + + + + + + + + + + + + + + + + + +
+
+
Always-On Proactive Memory · via Cognitive Folding
+

CogniFold

+

A brain-inspired always-on agent memory that folds continuously arriving events into self-emerging cognitive structure — built for the next generation of proactive assistants.

+ +
+
~60%Brain memory modeled
+
5Systems covered
+
12Systems mapped
+
+
+ +
+
+
Human Brain Memory Modeled: ~60%
+
+
+ + +
+
+
+
The Headline
+

How much of the brain's memory have we modeled?

+

CogniFold maps the human memory taxonomy onto concrete mechanisms. Hover a system to light up the brain region it lives in. Covered systems glow, partial systems pulse, planned systems are dim with a roadmap note.

+
+ +
+
+
+
+
+
+
Modeled
+
Partial
+
Planned
+
+
+ +
+
+
+
+
+
+ + +
+
+
+
Architecture
+

A tri-layer cognitive folding loop

+

CogniFold extends Complementary Learning Systems (CLS) with a prefrontal Intent layer. Events fold into concepts; concepts crystallize into intents — surfaced through a hierarchical context window across a TIME axis.

+
+ +
+
+ EVENT +

Hippocampal layer

+

Verbatim episodes captured as EVENT nodes — what happened, when. The fast, high-fidelity store.

+
// hippocampus · episodic + temporal
+
+
+
+ CONCEPT +

Neocortical layer

+

Patterns emerge across episodes into grounded CONCEPT nodes — generalized, explainable knowledge.

+
// neocortex · semantic
+
+
+
+ INTENT +

Prefrontal layer

+

INTENT nodes crystallize proactively from accumulated concepts and time anchors — goals, not just facts.

+
// prefrontal · prospective + working
+
+
+ +
⟵ TIME axis · recency decay · urgency boosting · deadline-aware retrieval ⟶
+ +
+

The differentiator: proactive intent crystallization

+

Proactivity is a property of the memory substrate, not the agent's policy. Goals emerge from the topology that accumulates the conditions for them — when concepts and time anchors align, an INTENT node forms on its own, before it is asked for.

+
+
+
+ + +
+
+
+
Evaluation
+

Benchmarked across memory & reasoning

+

Real measured results across long-context recall, multi-hop QA, theory-of-mind, and streaming knowledge.

+
+ +
+
82.8%
J-Score
LoCoMo
Long-conversation memory (Mem0 protocol)
+
~93%
accuracy
LongMemEval
Long-term memory evaluation
+
96.0%
EM
BABILong
Reasoning over long contexts
+
91.6%
EM
ToMi
Theory-of-mind belief tracking
+
0.587
F1
MuSiQue-Ans
Multi-hop question answering
+
0.720
F1
NarrativeQA
Long-form narrative QA
+
93.2%
accuracy
MuTual
Multi-turn dialogue reasoning
+
78.4%
EM
StreamingQA
Temporal knowledge over streams
+
+ +

Metrics are measured on CogniFold runs; see docs/BENCHMARK.md in the repository for protocols, dates, and reproduction commands.

+
+
+ + +
+
+
+
Get Started
+

Quickstart

+

Install, then run the stateful memory service. CogniFold integrates with agent runtimes over HTTP and via MCP.

+
+ +
+
+
+ + bash +
+
# Install (editable)
+uv pip install -e .
+
+# Provide an LLM key
+export OPENAI_API_KEY="sk-..."
+
+# Launch the always-on memory service
+cognifold serve
+
+# Or process an event timeline directly
+cognifold run timeline.json --agent --steps 15
+cognifold query "exercise habits" --graph graph.json
+
+ + +
+
+
+ + + + + +
+ + + + diff --git a/docs-site/js/app.js b/docs-site/js/app.js new file mode 100644 index 0000000..c5ad56c --- /dev/null +++ b/docs-site/js/app.js @@ -0,0 +1,192 @@ +// app.js — data-driven entry point. Loads memory_coverage.json and renders the +// coverage ring, the brain visualization, and the systems side panel. + +import { renderBrain } from "./brain.js"; + +const STATUS_LABEL = { covered: "Modeled", partial: "Partial", planned: "Planned" }; + +async function loadData() { + const res = await fetch("./data/memory_coverage.json", { cache: "no-cache" }); + if (!res.ok) throw new Error(`Failed to load coverage data: ${res.status}`); + return res.json(); +} + +// ---- Coverage ring ------------------------------------------------------- +function renderRing(pct) { + const ring = document.getElementById("coverage-ring"); + const R = 130; + const C = 2 * Math.PI * R; + ring.innerHTML = ` + +
+
0%
+
Human brain memory modeled
+
`; + + const progress = ring.querySelector(".progress"); + const num = ring.querySelector(".num"); + const target = C - (pct / 100) * C; + + // Animate when the ring scrolls into view (or immediately if reduced motion). + const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + const animate = () => { + requestAnimationFrame(() => { progress.style.strokeDashoffset = String(target); }); + if (reduce) { num.textContent = String(pct); return; } + const dur = 1800, start = performance.now(); + const tick = (t) => { + const k = Math.min(1, (t - start) / dur); + const eased = 1 - Math.pow(1 - k, 3); + num.textContent = String(Math.round(eased * pct)); + if (k < 1) requestAnimationFrame(tick); + }; + requestAnimationFrame(tick); + }; + + const io = new IntersectionObserver((entries, obs) => { + for (const e of entries) if (e.isIntersecting) { animate(); obs.disconnect(); } + }, { threshold: 0.4 }); + io.observe(ring); +} + +// ---- Systems side panel -------------------------------------------------- +function renderSystems(systems, brain, tooltip) { + const panel = document.getElementById("systems-panel"); + panel.innerHTML = ""; + + for (const sys of systems) { + const card = document.createElement("article"); + card.className = `sys-card s-${sys.status}`; + card.dataset.system = sys.id; + card.setAttribute("tabindex", "0"); + card.innerHTML = ` +
+
+
${escapeHtml(sys.name)}
+
${escapeHtml(sys.brain_region)} · ${escapeHtml(sys.taxonomy_group)}
+
+ ${STATUS_LABEL[sys.status]} +
+
+

${escapeHtml(sys.description)}

+
Mechanism: ${escapeHtml(sys.cognifold_mechanism)}
+
${escapeHtml(sys.evidence)}
+
`; + + const enter = (ev) => { + brain.highlightBySystem(sys.id); + showTooltip(tooltip, sys, ev); + }; + const leave = () => { brain.highlightBySystem(null); hideTooltip(tooltip); }; + + card.addEventListener("mouseenter", enter); + card.addEventListener("mousemove", (ev) => positionTooltip(tooltip, ev)); + card.addEventListener("mouseleave", leave); + card.addEventListener("focus", () => brain.highlightBySystem(sys.id)); + card.addEventListener("blur", () => brain.highlightBySystem(null)); + + // click to expand details + card.addEventListener("click", () => card.classList.toggle("active")); + card.addEventListener("keydown", (e) => { + if (e.key === "Enter" || e.key === " ") { e.preventDefault(); card.classList.toggle("active"); } + }); + + panel.appendChild(card); + } +} + +function highlightSystemCard(sid, on) { + const card = document.querySelector(`.sys-card[data-system="${sid}"]`); + if (card) card.classList.toggle("active-region", on); +} + +// ---- Tooltip helpers ----------------------------------------------------- +function showTooltip(tip, sys, ev) { + const color = { covered: "#38e8ff", partial: "#ffb347", planned: "#4a5380" }[sys.status]; + tip.innerHTML = ` +
${escapeHtml(sys.name)}
+
${STATUS_LABEL[sys.status]} · ${escapeHtml(sys.brain_region)}
+
${escapeHtml(sys.cognifold_mechanism)}
`; + tip.classList.add("show"); + positionTooltip(tip, ev); +} +function positionTooltip(tip, ev) { + const pad = 16; + let x = ev.clientX + pad, y = ev.clientY + pad; + const r = tip.getBoundingClientRect(); + if (x + r.width > window.innerWidth - 10) x = ev.clientX - r.width - pad; + if (y + r.height > window.innerHeight - 10) y = ev.clientY - r.height - pad; + tip.style.left = `${x}px`; + tip.style.top = `${y}px`; +} +function hideTooltip(tip) { tip.classList.remove("show"); } + +function escapeHtml(s) { + return String(s).replace(/[&<>"']/g, (c) => + ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); +} + +// ---- Scroll reveal ------------------------------------------------------- +function setupReveal() { + const io = new IntersectionObserver((entries) => { + for (const e of entries) if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } + }, { threshold: 0.12 }); + document.querySelectorAll(".reveal").forEach((el) => io.observe(el)); +} + +// ---- Boot ---------------------------------------------------------------- +async function main() { + setupReveal(); + const tooltip = document.getElementById("tooltip"); + + let data; + try { + data = await loadData(); + } catch (err) { + console.error(err); + document.getElementById("systems-panel").innerHTML = + `

Could not load coverage data. Serve this folder over HTTP (e.g. python -m http.server) rather than opening the file directly.

`; + return; + } + + // Headline numbers + const pct = data.overall_coverage_pct ?? 0; + document.querySelectorAll("[data-coverage-pct]").forEach((n) => { n.textContent = `~${pct}%`; }); + renderRing(pct); + + // Counts in hero meta + const counts = data.systems.reduce((a, s) => { a[s.status] = (a[s.status] || 0) + 1; return a; }, {}); + setText("stat-covered", counts.covered || 0); + setText("stat-partial", counts.partial || 0); + setText("stat-total", data.systems.length); + + // Brain + systems + const brainMount = document.getElementById("brain-mount"); + const brain = renderBrain(brainMount, data.systems, { + onRegionEnter: (region, status, ev) => { + // highlight all system cards hosted by this region + region.systems.forEach((sid) => highlightSystemCard(sid, true)); + const host = data.systems.find((s) => region.systems.includes(s.id)); + if (host) showTooltip(tooltip, host, ev); + }, + onRegionLeave: (region) => { + region.systems.forEach((sid) => highlightSystemCard(sid, false)); + hideTooltip(tooltip); + }, + }); + renderSystems(data.systems, brain, tooltip); +} + +function setText(id, v) { const el = document.getElementById(id); if (el) el.textContent = v; } + +main(); diff --git a/docs-site/js/brain.js b/docs-site/js/brain.js new file mode 100644 index 0000000..39bd8ee --- /dev/null +++ b/docs-site/js/brain.js @@ -0,0 +1,200 @@ +// brain.js — renders a stylized anatomical brain (SVG) with labeled regions. +// Each region maps to one or more memory-system ids. Regions light up by the +// aggregated status of the systems they host, and expose hover highlighting. + +// Region geometry: a lateral (side) view of the brain. Paths are hand-tuned +// blobs approximating the major lobes / structures. Coordinates live in a +// 0..600 x 0..420 viewBox. +export const REGIONS = [ + { + id: "prefrontal", + label: "Prefrontal cortex", + systems: ["working", "prospective"], + // front of brain (left side of viewBox) + path: "M70 150 C60 110 95 70 150 64 C180 60 205 74 214 100 C200 130 196 165 192 196 C170 206 130 214 104 206 C80 198 76 176 70 150 Z", + labelXY: [118, 138], + }, + { + id: "neocortex", + label: "Neocortex", + systems: ["semantic"], + // top / parietal-occipital dome + path: "M214 100 C232 60 300 44 372 56 C448 68 498 110 500 158 C470 168 420 170 372 168 C310 166 250 158 200 150 C202 132 208 114 214 100 Z", + labelXY: [350, 100], + }, + { + id: "hippocampus", + label: "Hippocampus", + systems: ["episodic", "temporal", "consolidation"], + // central medial-temporal seahorse region + path: "M250 200 C270 188 320 188 348 200 C372 210 378 234 360 248 C330 262 282 262 256 248 C238 238 234 210 250 200 Z", + labelXY: [305, 226], + }, + { + id: "temporal-lobe", + label: "Temporal lobe", + systems: ["sensory", "priming"], + // lower-front lobe + path: "M150 230 C140 268 168 300 220 306 C268 312 300 296 306 270 C282 264 256 256 238 246 C210 232 178 226 150 230 Z", + labelXY: [212, 286], + }, + { + id: "amygdala", + label: "Amygdala", + systems: ["affective", "conditioning"], + // small almond near hippocampus + path: "M236 252 C232 240 252 234 266 240 C278 246 276 262 262 266 C248 270 240 264 236 252 Z", + labelXY: [214, 264], + }, + { + id: "neocortex-back", + label: "Cortical assoc.", + systems: ["forgetting"], + // occipital back lobe + path: "M448 168 C492 168 522 192 520 226 C518 256 488 274 452 270 C424 266 408 244 410 218 C412 192 426 172 448 168 Z", + labelXY: [468, 222], + }, + { + id: "cerebellum", + label: "Cerebellum", + systems: ["procedural"], + // bottom-back ridged structure + path: "M380 268 C420 262 470 276 480 308 C486 334 456 356 410 356 C368 356 340 338 338 312 C336 290 352 272 380 268 Z", + labelXY: [418, 322], + }, + { + id: "basal-ganglia", + label: "Basal ganglia", + systems: ["procedural"], + // deep central nucleus + path: "M300 232 C322 226 350 234 356 252 C360 268 342 282 318 282 C296 282 282 268 284 252 C286 240 292 234 300 232 Z", + labelXY: [322, 258], + }, +]; + +const STATUS_COLOR = { covered: "#38e8ff", partial: "#ffb347", planned: "#4a5380" }; + +// Aggregate a region's status from the systems it hosts. +function regionStatus(region, systemsById) { + const statuses = region.systems + .map((sid) => systemsById[sid]?.status) + .filter(Boolean); + if (statuses.some((s) => s === "covered")) return "covered"; + if (statuses.some((s) => s === "partial")) return "partial"; + return "planned"; +} + +const SVGNS = "http://www.w3.org/2000/svg"; +function el(name, attrs = {}) { + const e = document.createElementNS(SVGNS, name); + for (const [k, v] of Object.entries(attrs)) e.setAttribute(k, v); + return e; +} + +/** + * Render the brain into `mount`. + * @returns {{ highlightBySystem: (sid:string|null)=>void, regionForSystem: (sid:string)=>string|undefined }} + */ +export function renderBrain(mount, systems, { onRegionEnter, onRegionLeave } = {}) { + const systemsById = Object.fromEntries(systems.map((s) => [s.id, s])); + + const svg = el("svg", { + viewBox: "0 0 600 420", + role: "img", + "aria-label": "Anatomical brain showing which memory systems CogniFold models", + }); + + // glow filter + const defs = el("defs"); + const filter = el("filter", { id: "brainGlow", x: "-40%", y: "-40%", width: "180%", height: "180%" }); + const blur = el("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "5", result: "b" }); + const merge = el("feMerge"); + merge.appendChild(el("feMergeNode", { in: "b" })); + merge.appendChild(el("feMergeNode", { in: "SourceGraphic" })); + filter.appendChild(blur); + filter.appendChild(merge); + defs.appendChild(filter); + svg.appendChild(defs); + + // faint full-brain silhouette behind regions for cohesion + const silhouette = el("path", { + d: "M70 150 C55 95 110 52 180 50 C250 48 320 42 400 50 C480 58 528 104 522 160 C530 210 512 262 480 300 C470 345 420 366 360 360 C300 372 250 360 210 320 C160 318 130 300 120 270 C90 262 70 234 66 196 C62 178 64 164 70 150 Z", + fill: "rgba(155,107,255,0.04)", + stroke: "rgba(155,107,255,0.18)", + "stroke-width": "1.5", + }); + svg.appendChild(silhouette); + + // central connective threads (subtle neural net feel) + const threads = [ + [118, 138, 305, 226], [305, 226, 350, 100], [305, 226, 322, 258], + [322, 258, 418, 322], [214, 264, 305, 226], [468, 222, 350, 100], + [118, 138, 212, 286], + ]; + for (const [x1, y1, x2, y2] of threads) { + svg.appendChild(el("line", { + x1, y1, x2, y2, stroke: "rgba(56,232,255,0.10)", "stroke-width": "1", + })); + } + + const regionEls = {}; + const systemToRegion = {}; + + for (const region of REGIONS) { + const status = regionStatus(region, systemsById); + const color = STATUS_COLOR[status]; + + const g = el("g", { class: `region ${status === "planned" ? "dim" : "active"}` }); + g.style.color = color; // drives currentColor in CSS glow + g.dataset.region = region.id; + + const lobe = el("path", { + d: region.path, + fill: status === "planned" ? "rgba(74,83,128,0.12)" : `${color}22`, + stroke: color, + }); + lobe.classList.add("lobe"); + + // pulsing animation for partial regions + if (status === "partial") { + const anim = el("animate", { + attributeName: "fill-opacity", values: "0.35;0.85;0.35", + dur: "2.6s", repeatCount: "indefinite", + }); + lobe.appendChild(anim); + } + + const [lx, ly] = region.labelXY; + const label = el("text", { x: lx, y: ly, "text-anchor": "middle" }); + label.classList.add("region-label"); + label.textContent = region.label; + + g.appendChild(lobe); + g.appendChild(label); + + g.addEventListener("mouseenter", (ev) => onRegionEnter?.(region, status, ev)); + g.addEventListener("mouseleave", () => onRegionLeave?.(region)); + + svg.appendChild(g); + regionEls[region.id] = g; + for (const sid of region.systems) systemToRegion[sid] = region.id; + } + + mount.appendChild(svg); + + return { + highlightBySystem(sid) { + for (const g of Object.values(regionEls)) g.classList.remove("highlight"); + if (!sid) return; + const rid = systemToRegion[sid]; + if (rid && regionEls[rid]) regionEls[rid].classList.add("highlight"); + }, + highlightRegion(rid) { + for (const g of Object.values(regionEls)) g.classList.remove("highlight"); + if (rid && regionEls[rid]) regionEls[rid].classList.add("highlight"); + }, + regionForSystem(sid) { + return systemToRegion[sid]; + }, + }; +}