diff --git a/.gitea/workflows/build-push.yml b/.gitea/workflows/build-push.yml index 513cc2c..eefb320 100644 --- a/.gitea/workflows/build-push.yml +++ b/.gitea/workflows/build-push.yml @@ -53,6 +53,7 @@ jobs: - name: Build Docker image run: | docker build --no-cache \ + --build-arg COMMIT_SHA=${{ steps.sha.outputs.short_sha }} \ -t "${IMAGE}:${{ steps.sha.outputs.short_sha }}" \ -t "${IMAGE}:latest" . diff --git a/Dockerfile b/Dockerfile index aad1f29..8aa72cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ COPY . . # Pass commit SHA at build time ARG COMMIT_SHA=dev -ENV COMMIT_SHA=${COMMIT_SHA} +ENV NEXT_PUBLIC_COMMIT_SHA=${COMMIT_SHA} # Build Next.js app RUN pnpm run build diff --git a/app/api/ci-status/route.ts b/app/api/ci-status/route.ts index 25dcedc..524806f 100644 --- a/app/api/ci-status/route.ts +++ b/app/api/ci-status/route.ts @@ -2,7 +2,15 @@ import { NextRequest, NextResponse } from 'next/server' const FORGEJO_URL = 'https://forgejo.riotpiao.com' const DEFAULT_REPO = 'rock/riotpiao.com' -const ALLOWED_REPOS = ['rock/riotpiao.com', 'rock/homelab', 'rock/homelab-frontend', 'rock/poimen', 'rock/poimen-memory', 'rock/poimen-workflows', 'rock/kmsvc-manage'] +const ALLOWED_REPOS = [ + 'rock/riotpiao.com', + 'riotpiao-poimen/homelab', + 'riotpiao-poimen/homelab-frontend', + 'riotpiao-poimen/poimen', + 'riotpiao-poimen/poimen-memory', + 'riotpiao-poimen/poimen-workflows', + 'riotpiao-poimen/kmsvc-manage', +] export async function GET(request: NextRequest) { const repo = request.nextUrl.searchParams.get('repo') || DEFAULT_REPO diff --git a/app/page.tsx b/app/page.tsx index 12fcda2..d7625c8 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -13,10 +13,10 @@ export default function Home() { const [bioModalOpen, setBioModalOpen] = useState(false) const { t } = useLanguage() - // Order: 0=Homelab, 1=Poimen Memory, 2=Poimen Workflow, 3=RBC, 4=AWS + // Order: 0=Poimen Workflow, 1=Poimen Memory, 2=Homelab, 3=RBC, 4=AWS const projects = t.projects.items.map((item, index) => ({ ...item, - id: ['project-homelab', 'project-poimen-memory', 'project-poimen-workflow', 'project-rbc', 'project-aws'][index], + id: ['project-poimen-workflow', 'project-poimen-memory', 'project-homelab', 'project-rbc', 'project-aws'][index], status: index === 3 ? 'completed' as const : index <= 2 @@ -29,15 +29,17 @@ export default function Home() { : undefined, videoUrl: '#', articleUrl: index === 4 ? 'https://lnkd.in/p/gm2PZkWw' : '#', - deepDive: index === 0 ? { url: '/homelab', label: 'Architecture & Deep Dive' } : undefined, + deepDive: index === 2 ? { url: '/homelab', label: 'Explore the Architecture →' } + : index === 1 ? { url: '/poimen/memory', label: 'Explore the Memory System →' } + : undefined, ciRepos: index === 0 ? [ - { label: 'portfolio', repo: 'rock/riotpiao.com', forgejoBase: 'https://forgejo.riotpiao.com/rock/riotpiao.com' }, - { label: 'homelab-frontend', repo: 'riotpiao-poimen/homelab-frontend', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/homelab-frontend' }, - { label: 'kmsvc', repo: 'riotpiao-poimen/kmsvc-manage', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/kmsvc-manage' }, + { label: 'poimen-wf', repo: 'riotpiao-poimen/poimen-workflows', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/poimen-workflows' }, ] : index === 1 ? [ { label: 'poimen-mem', repo: 'riotpiao-poimen/poimen-memory', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/poimen-memory' }, ] : index === 2 ? [ - { label: 'poimen-wf', repo: 'riotpiao-poimen/poimen-workflows', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/poimen-workflows' }, + { label: 'portfolio', repo: 'rock/riotpiao.com', forgejoBase: 'https://forgejo.riotpiao.com/rock/riotpiao.com' }, + { label: 'homelab-frontend', repo: 'riotpiao-poimen/homelab-frontend', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/homelab-frontend' }, + { label: 'kmsvc', repo: 'riotpiao-poimen/kmsvc-manage', forgejoBase: 'https://forgejo.riotpiao.com/riotpiao-poimen/kmsvc-manage' }, ] : undefined, })) diff --git a/app/poimen/memory/page.tsx b/app/poimen/memory/page.tsx new file mode 100644 index 0000000..0cb2e00 --- /dev/null +++ b/app/poimen/memory/page.tsx @@ -0,0 +1,292 @@ +'use client' + +import Link from 'next/link' +import { ArrowLeft } from 'lucide-react' +import { motion } from 'framer-motion' + +const skillCategories = [ + { + title: 'Core Runtime', + skills: ['Rust', 'actix-web', 'tokio', 'serde'], + }, + { + title: 'Storage & Search', + skills: ['PostgreSQL (CloudNativePG)', 'pgvector (HNSW)', 'Cosine Similarity', 'BFS Graph Traversal'], + }, + { + title: 'LLM & Embeddings', + skills: ['Ollama (ornith:35b)', 'TEI (nomic-embed)', '768-dim Embeddings'], + }, + { + title: 'Identity & Security', + skills: ['Authentik OIDC', 'JWT Verification', 'SOPS Encrypted Secrets', 'RBAC'], + }, + { + title: 'Data Pipeline', + skills: ['Fixed-Window Chunking', 'Entity Extraction', 'Fact Extraction', 'Reflection Filtering'], + }, + { + title: 'Infrastructure', + skills: ['Kubernetes', 'ArgoCD', 'Kustomize', 'cert-manager'], + }, +] + +const sectionVariants = { + hidden: { opacity: 0, y: 40 }, + visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }, +} + +export default function PoimenMemoryPage() { + return ( +
+
+ + + Back to Projects + + + {/* Hero */} + +
+ Poimen (Ποιμήν) · Memory System +
+

+ Teaching the Shepherd to Remember +

+

+ A Graph-RAG memory system that gives AI agents long-term recall, semantic search, and self-compacting knowledge. +

+

+ Agents forget. Every conversation starts from zero unless you build memory into the system. + Poimen Memory is a Rust-based Graph-RAG service that ingests conversations, + extracts entities and relationships via LLM, stores them in a temporal knowledge graph backed + by pgvector, and serves them back through three-tier retrieval — signature + match at 50ms, graph-boosted hybrid search, and Obsidian fallback. The cache self-compacts: + stale embeddings are evicted, frequently-accessed chunks are promoted, and the graph auto-reconciles + on every write. +

+
+ + {/* Section 1: Architecture Overview */} + +
+
+ System Design +
+

+ Architecture Overview +

+
+ +
+

+ The memory system runs as a Rust microservice inside the Kubernetes poimen namespace. + An actix-web API server handles HTTP requests, authenticates via Authentik OIDC JWT, + and routes to either the search path (direct pgvector query) or the ingest path (async + pipeline through an internal queue → LLM extraction → graph persistence). All data lives in a + CloudNativePG cluster with HNSW indexes for vector similarity. +

+
+ + {/* Architecture Diagram */} +
+

+ 🏗️ System Architecture +

+
+