Changelog¶
Notable changes to Campus RAG Assistant — independent extension of the UC Berkeley ETS Chabot platform (campus-rag-assistant).
Keep a Changelog format.
Attribution and license: README.
Author & maintainer: sandeep-jay — sole implementation author
of the upstream Berkeley ETS Chabot codebase (copyright UC Regents) and author of
this independent extension. Distributed under the UC Regents
LICENSE; see NOTICE. Not an official UC Berkeley product.
Convention: sections use session dates (when work happened). GitHub PR numbers are noted where the public merge story matters.
Edit [Unreleased] while you work. When a session is done, rename it to
## [YYYY-MM-DD] — short title and open a new [Unreleased].
[Unreleased]¶
Fixed¶
- CI — disable scheduled live helpdesk trajectory eval. Removed the
agent-eval-liveGitHub Actions job and the dailyscheduletrigger; live supervisor comparison remains available locally viatox -e agent-eval-livewhen AWS/LangSmith are configured. - CI — agent-eval tox env fails on pytest 9.x. GitHub Actions resolves
pytest>=8.0.0to pytest 9.1.x;pytest-ruff==0.2.1still declares the removedpatharg onpytest_collect_file, so pytest aborts during plugin registration (PluginValidationError) before any trajectory scenario runs. Bumpedpytest-ruffto0.5for pytest 8.1+/9.x hook compatibility;tox -e backend,agent-evalpasses locally.
Added¶
- Helpdesk agent — score-based KB confidence gate and evidence trimming. The agent now reads the top-1 similarity
scorefrom the KB retry's documents and only proposes a KB-grounded solution when it clearsHELPDESK_AGENT_KB_CONFIDENCE_FLOOR(default0.55). Below the floor — or zero hits — the agent escalates to the existing web-consent flow instead of confidently surfacing irrelevant articles. Fixes the Panopto case where a 15-doc Kaltura retrieval was being marketed as the answer without ever asking the user about live web search. The retry log now includestop_score/floorso the threshold can be tuned. The agent also caps surfaced evidence atHELPDESK_AGENT_EVIDENCE_TOP_N(default3) sources/document contents so the chat bubble shows the top supporting hits rather than the full retrieved list. The activity timeline now renders the agent's KB pass as "Knowledge base (agent retry)" and the web pass as "Public web search" so they're visually distinct from the chat-level KB retrieval. - Helpdesk agent — surfaced GitHub error detail in ticket-create failures.
create_github_issuenow extracts GitHub'smessageanderrors[*].messagepayload into the surfacedHTTPExceptiondetail, and the Vue ticket modal readsresponse.data.detailso the toast tells the user why GitHub refused the issue (auth scope, validation, rate limit) instead of a generic "Failed to file agent ticket. Please try again."
Fixed¶
- Helpdesk chat — scroll dead-space after agent resume.
MessageList.vuewas set tomin-h-fullregardless of whether messages were present; combined withscrollTop = scrollHeight, that left short follow-up bubbles stranded at the top of an otherwise empty viewport. The full-height pad now only applies to the empty welcome state, so the new agent turn and "Thinking…" indicator sit in the natural reading position. -
Helpdesk agent — activity trace discoverability. The current actionable agent turn now expands its "What the agent did" trace by default and keeps the header visible, so users can immediately see KB retry, low-confidence gating, web-search consent, and web-search steps without hunting for a collapsed control.
-
Helpdesk agent — structured sources and live-web consent —
AgentTurnnow carriessources,document_contents,source_kind, anddisclaimeron propose-solution turns, populated from KB retry or web-search documents using the same shape as chat metadata. Persistedagent_summaryrows retain that evidence for reloads. When KB retry finds no fix and the configured web provider is live (WEB_SEARCH_PROVIDER=tavilywithTAVILY_API_KEY), the agent pauses with a radio consent question (Search the web/Skip and draft a ticket) before calling Tavily; mock web search remains automatic for CI/demo. VueMessageBubble.vuerenders the existing sources panel and web disclaimer for live and persisted agent bubbles. - Campus router and agent capability registry (Phase 5) — added
backend/app/services/agents/registry.py(AgentSpec{name, subgraph_factory, tools, enabled_flag, description}withregister_agent/get_agent/enabled_domains/unregister_agent; helpdesk registers at import time) andbackend/app/services/agents/router.py(RouterDecision{domain, confidence, reason},classify_domain(...),helpdesk_should_escalate(...)). The router is off by default (CAMPUS_ROUTER_ENABLED=false); the mock provider drives a deterministic sentinel router for PR CI, the live LLM path useswith_structured_output(RouterDecision)and falls back tokb_answeron any error. Chat metadata now carriesrouter_decisionon both the JSON (/api/chat/chat,/api/chat/sessions/{id}/messages) and SSE (/api/chat/stream) paths. VueMessageBubble.vuepromotes the escalation chip whenkb_resolved == falseor the router classifies the turn ashelpdeskwith confidence at or aboveROUTER_HELPDESK_FLOOR(default0.6). Tests cover the seam (test_echo_agent_registers_without_router_changes), router contract, and chat-API end-to-end behaviour. Docs: new ADR-007 (Proposed),docs/roadmap/AGENT_REGISTRY.mdcontract, updatedAGENTIC_HELPDESK_REBUILD.mdPhase 5 status, mkdocs nav. - Helpdesk agent — compiled LangGraph
StateGraph— addedbackend/app/services/helpdesk_graph/graph.pywith nodessupervisor,tools,clarifier,classifier,writer,solution,await_user,await_confirm, and terminals (link_existing,file_ticket,resolved,aborted).start_session/resume_session/confirm_session/abort_sessionnow invokeHELPDESK_GRAPH.ainvoke(...); supervisor routing is deterministic (select_supervisor_action) so user-visible behaviour,AgentTurnshape, anddebug_tracebyte-shape are unchanged. LangSmith now renders one nested graph tree per session instead of a flat span. Phase 1b swaps the custom JSON checkpoint for anAsyncPostgresSaverand the pause nodes forlanggraph.types.interrupt(). - Helpdesk agent — LangGraph checkpointers — added configurable checkpoint backends (
postgres,sqlite,memory) with Postgres as the default, Alembic-owned LangGraph checkpoint tables, andinterrupt()/Command(resume=...)pause-resume flow for user clarification and HITL ticket confirmation. The legacy JSON SQLite checkpoint path remains behindHELPDESK_AGENT_USE_LANGGRAPH_CHECKPOINT=falsefor one release. Thesqlitebackend is an opt-in dev fallback:langgraph-checkpoint-sqliteis intentionally not pinned inrequirements.txt(2.0.x carriesGHSA-9rwj-6rc7-p77cand 3.x requires a LangGraph 1.x bump); install it manually when you actually want SQLite locally. - Helpdesk agent — live supervisor adapter — added bindable LangChain tool wrappers for KB retry, web search, duplicate search, and HITL ticket filing plus a structured-output supervisor/classifier adapter behind
HELPDESK_AGENT_LLM_SUPERVISOR=false. Invalid or disallowed supervisor decisions fall back to a safe draft path or the deterministic supervisor. - Helpdesk agent — specialist routing — added help-first supervisor gating, classifier confidence tracking (
HELPDESK_AGENT_CLARIFY_CONFIDENCE_FLOOR), targeted clarification, andIdempotency-Keyhandling on/api/helpdesk/agent/confirm. - Helpdesk agent — live graph stream trace —
/api/helpdesk/agent/start/streamand/api/helpdesk/agent/resume/streamnow emit real LangGraph node/toolstepevents with status, summary, and latency instead of canned progress strings. Vue renders those events in a live "What the agent did" timeline and still falls back to persisteddebug_traceon refresh. - Helpdesk agent — Phase 3 metrics — added Prometheus series for tool latency, supervisor decisions, estimated tokens, and turns taken:
chatbot_helpdesk_agent_tool_latency_seconds,chatbot_helpdesk_agent_decision_total,chatbot_helpdesk_agent_tokens_total, andchatbot_helpdesk_agent_turns_taken. - Helpdesk agent — trajectory eval gate — added
backend/tests/eval/helpdesk_agent_scenarios.json,test_helpdesk_agent_scenarios.py,tox -e agent-evalfor PR-gated mock trajectory metrics, andtox -e agent-eval-livefor nightly/manual live LLM supervisor comparison. - Helpdesk agent guardrails — added
HELPDESK_AGENT_MAX_TURNS,HELPDESK_AGENT_MAX_QUESTIONS,HELPDESK_AGENT_MAX_TOOL_RETRIES,HELPDESK_AGENT_MAX_TOKENS_PER_SESSION, andHELPDESK_AGENT_DEADLINE_SECONDSdefaults for Phase 0 budget enforcement. - Local Postgres via Docker Compose — added a repo-root
docker-compose.ymlwith apostgres:14dbservice, first-run database bootstrap SQL, and backend runner startup/health-check wiring so local development no longer depends on Homebrew Postgres by default. - Database listener guard — the backend runner now detects non-Docker listeners on port 5432 and asks developers to stop them or opt into
SKIP_DOCKER_DB=1, preventing accidental connections to an old local Postgres.
Changed¶
- Quick start database setup — README and operations docs now lead with
docker compose --env-file /dev/null up -d db, documentSKIP_DOCKER_DB=1for existing Postgres services, and preserve a one-release Homebrew fallback path. - Development database URL — local development defaults now use
127.0.0.1instead oflocalhostso macOS does not accidentally routelocalhostto an existing Homebrew Postgres listener while Docker publishes IPv4.
Fixed¶
- Backend pytest no longer hangs forever on a fresh Docker Postgres (macOS).
backend/tests/conftest.pyshelled out topsql -lqt/createdb -h localhostto bootstrap thechatbot_testdatabase. On macOS,localhostresolves to::1first and Docker Desktop publishes the Postgres listener on IPv4 only; the IPv6 TCP handshake completes through vpnkit/gVisor but the Postgres backend never receives the startup packet, so libpq blocks indefinitely on the server greeting and pytest's main thread parks inos.waitpidbefore any test runs — looking liketests/api/test_auth.py::test_registeris "stuck in a loop" when in fact the first session fixture never returned. The conftest now (1) forces127.0.0.1(rewritinglocalhostif set), (2) passesPGPASSWORDand-wso libpq fails fast instead of waiting on a closed stdin password prompt, (3) caps the connect handshake withPGCONNECT_TIMEOUT=5and the subprocess with a 30 s wall-clocktimeout, and (4) re-raises a clearRuntimeError("On macOS this usually means localhost resolved to IPv6…") so the next person hits a loud error instead of an open-ended stall..env.testis updated to defaultPOSTGRES_HOST=127.0.0.1to matchDATABASE_URLin dev. - Helpdesk agent multi-turn UI — next question now appears below the user reply.
frontend-vue/src/components/chat/AgentTurnActions.vuepreviously upserted the existing assistant bubble in place when a follow-up turn arrived after a pill/radio click, which left the next question above the just-added user message — once the chat was scrolled to the bottom it read as "nothing happened" after the user picked an option. The button-driven path now matches the free-text reply path (addAssistantMessage), so each new agent turn appends a fresh bubble directly under the user's answer.MessageBubble.vuegates<AgentTurnActions>and the "agent is running" timeline pulse byisLastMessage, so older bubbles freeze into read-only history and don't expose stale clickable pills/radios. TherecordAgentTurnIntoChatupsert is retained for the genuinely-terminal callers that swap a pending bubble for a final result without an intervening user reply (abort-on-mode-change, manual ticket file, helpdesk-escalation chip). New tests:MessageBubble.test.tscovers theisLastMessagegate (renders on last, hidden otherwise) andAgentTurnActions.test.tsasserts the bubble order[prior agent → user reply → new agent]after a pill click. - Helpdesk docs truth-in-advertising — README and helpdesk docs now separate the shipped deterministic runner from the target LLM supervisor / compiled
StateGraph/AsyncPostgresSavermigration tracked in ADR-006.
Security¶
- Helpdesk tool input redaction — redacts outbound KB retry, Tavily/web-search, and GitHub duplicate-search queries before provider calls so cloud keys or tokens pasted by a user do not leave the app in tool parameters.
[v3.0.0] — 2026-05-31¶
Added (docs refresh pass — PRs #50, #51)¶
- Docs — releases hub — consolidated
docs/release-notes/index.md(v1.0 / v2.0 / v3.0.0); dropped duplicatedocs/README.md(#50). - Docs — ADR-006 — ADR-006 records the LLM supervisor migration plan; helpdesk/index.md gains a shipped-vs-target row table (#51).
Changed (docs refresh pass — PRs #52–#57)¶
- Docs — reviewer introductions (#57) — aligned README, docs landing, Reviewer Guide, Case Study, and Architecture around one canonical product introduction; reordered first-visit sections around product features and architecture; added Azure retrieval parity in Architecture/Design; extended
scripts/check_docs.pyto enforce intro + capability rows. - Docs — first-visit polish (#56) — moved operational runbooks into
docs/operations-manual/, added an operations-manual landing page, and tightened the root README, docs landing, Reviewer Guide, and Case Study so first-time reviewers see crisp portfolio value before release history or deep reference material; collapsible primary nav on the docs site. - Docs cleanup arc (#50–#54) — six-PR documentation consolidation: releases hub; helpdesk shipped-vs-target labels + ADR-006; ARCHITECTURE + DESIGN refresh with LANGGRAPH/WEB_RESEARCH folded into DESIGN; operations surface consolidated (PERFORMANCE, PRODUCTION_TLS, E2E, TENANT_CONFIG absorbed);
eval_baseline_2026-05-19renamed to eval_baseline_v2.md; SECURITY dependency floor + PRODUCT_ROADMAP Phase 6d shipped status refreshed. - Docs — OPERATIONS.md (#53) — absorbs local OAuth, production HTTPS/HTTP/2, Playwright E2E, campus Phase 0 performance guardrails.
- Docs — DESIGN.md (#52) — absorbs tenant config and LangGraph KB path + opt-in web research sections; documents Azure AI Search retrieval in parity with AWS Bedrock KB.
- Docs — EVALUATION.md (#54) — helpdesk eval distinguishes shipped metrics from planned trajectory scenario rig (Agentic Rebuild Phase 4).
- Docs — PRODUCT_ROADMAP.md (#55) — Phase 6d marked shipped (
v3.0.0); Agentic Helpdesk Rebuild is the live forward track.
Fixed (docs refresh pass)¶
- Docs drift — helpdesk spec and ADR-005 no longer overstate LLM supervisor, compiled StateGraph, enforced budgets, and trajectory eval as shipped.
Added¶
- Helpdesk agent frontend wiring: Vue now starts the helpdesk agent from unresolved KB answers or AGENT-mode chat input, renders each agent journey as one assistant bubble with an activity timeline, resumes sessions from in-chat actions, streams start/resume progress over SSE with fallback to non-streaming calls, and hands
draft_readyturns to the existing ticket review modal. -
Helpdesk agent UX controls: added the ASK/AGENT mode switch, agent outcome badge, accessible radio/pill action rendering, cancel-on-mode-exit behavior, and sanitized telemetry for mode changes, start/resume, stream fallback, draft review, confirmation, and abort flows.
-
Helpdesk agent backend Phase A-D: added the LangGraph-backed
/api/helpdesk/agent/{start,resume,confirm,abort}flow plus/start/streamand/resume/streamSSE endpoints, SQLite checkpoint persistence, stale-question guards, classifier-driven ticket facts, retrieval/web solver tools, duplicate GitHub issue search, and HITL-gated ticket filing. - Durable agent chat persistence:
services/helpdesk/persist.py::upsert_agent_summarymaintains one assistantchat_messagesrow per agent journey, updates it across question/info/draft/terminal turns, and stores a trimmed trace for later UI rendering. -
Helpdesk agent observability: added backend funnel/error metrics and LangSmith tracing wrappers for agent entry points, tools, and LLM helpers, all gated so tracing failures do not affect user responses.
-
Design tokens v2 / chat cohesion: rebuilt the light + dark palettes around a single accent family + neutral surfaces. New tokens (
--surface-raised,--sidebar*,--accent-subtle,--success-subtle,--warning-subtle,--user-message*) and elevation utilities (shadow-soft,shadow-pop,shadow-modal,chat-reading-column,surface-dotgrid). - Sidebar UX:
SessionList.vuenow groups sessions by recency (Today/Yesterday/This Week/Older) with collapsible groups (state persisted inlocalStorage) andShow morepagination so long histories stay scannable. - Always-visible copy-to-clipboard on every assistant message (next to like/dislike), with a transient
Copiedconfirmation. - Vue test hygiene: raised the test-only Node EventTarget listener ceiling for MSW so the full Vitest suite no longer emits the
MaxListenersExceededWarning. - Backend: deterministic
chat_messagesordering — addedorder_by='ChatMessage.id'to theChatSession.messagesrelationship and an explicitsorted(..., key=lambda m: m.id)inGET /api/chat/sessions/{id}so reloaded transcripts never reshuffle around updated rows. - Helpdesk escalation (post-RAG): when
metadata.kb_resolved=false, Vue shows two independent LLM-backed actions with distinct output shapes. Summarize issue posts a narrativeConversationSummaryinline as an assistant message; Create ticket extracts a structuredTicketDraft, opens an accessible review modal, and files the reviewed draft to GitHub. POST /api/helpdesk/summarize(recap),POST /api/helpdesk/draft-ticket(structuredTicketDraft), andPOST /api/helpdesk/create-issue(file GitHub issue) — all feature-flagged viaHELPDESK_ENABLEDand inheriting chat auth + rate limits.kb_resolvedheuristic on KB chat responses (fuzzy out-of-scope detection + optional rerank score floor); propagated through SSEdoneand message metadata.- Prometheus metrics:
chatbot_helpdesk_recap_*,chatbot_helpdesk_draft_ticket_*,chatbot_helpdesk_create_issue_total,chatbot_helpdesk_kb_resolved_total. - Mock-mode demo sentinel query:
Oracle Financials 403 error on budget reports.
Documentation¶
-
v3 documentation refresh — versioned asset layout under
docs/assets/{architecture,product,auth}/{v1,v2,v3}/; v3 architecture diagrams (overview, detailed, topology) and helpdesk agent screenshots; updated README, ARCHITECTURE.md, mkdocs nav; high-level release notes for v0.1, v2.0, and v3.0.0 underdocs/release-notes/; AGENTIC_HELPDESK_REBUILD.md roadmap added to nav. -
Helpdesk agent surfacing — added top-level Helpdesk Agent section to MkDocs nav with a new overview page (
docs/helpdesk/index.md), pulled the existing product spec (CONVERSATION_FLOW.md) and engineering spec (HELPDESK_AGENT.md) out of the orphaned roadmap subtree into nav, replaced the ASCII topology in the engineering spec with a Mermaid diagram, expanded the helpdesk evaluation section, and cross-linked the new hub from README, docs landing, REVIEWER_GUIDE, PORTFOLIO_CASE_STUDY, DESIGN, and docs/README. Also surfaced previously-orphanedTENANT_CONFIG.mdandPERFORMANCE.mdin nav and broke the four ADR files out as individual nav entries (previously onlyadr/README.mdwas reachable). - ADR-005 — Bounded helpdesk agent — recorded the decision to ship a single-supervisor LangGraph with hard tool budgets and a HITL gate on
file_ticketrather than open multi-agent autonomy; added to the ADR index and case-study decision table. docs/PERFORMANCE.mdreframed as a forward-looking backlog tracker (campus production-scale track) so readers do not confuse Phase 1-3 with implementation status.- Repository hygiene — removed
docs/.DS_Storefrom the working tree (already covered by.gitignore). -
Updated
docs/ARCHITECTURE.mdto mark the AGENT-mode Vue wiring as shipped on top of the backend helpdesk agent endpoints. -
Documented the backend helpdesk-agent endpoint surface, state/checkpoint model, tool flow, and HITL confirmation path in
docs/ARCHITECTURE.md. -
Helpdesk agent design freeze (2026-05-25): new RFCs at docs/roadmap/CONVERSATION_FLOW.md (product spec: ASK vs AGENT modes, intent router, cross-mode behaviors) and docs/roadmap/HELPDESK_AGENT.md (engineering spec: helpdesk LangGraph, multi-turn checkpointer, supervisor + clarifier/classifier/writer specialists, tools, HITL gate, budgets, and full P0+P1 hardening). PRODUCT_ROADMAP.md Phase 6d now points at both RFCs.
- Reposition README and MkDocs landing page to lead with ownership and architecture; move upstream attribution into a dedicated "Origin and Scope" section.
- Add
docs/REVIEWER_GUIDE.mdwith 90-second read, senior-signal evidence map, and per-persona review paths; surfaced in MkDocs nav near the top. - Replace "Demo readiness" with "Review artifacts" framing in README and docs site.
- Rewrite
docs/PORTFOLIO_CASE_STUDY.md"My role" section so platform ownership leads and upstream context follows. - Drop weak phrases ("not a weekend chatbot", "portfolio-grade") near the top of public-facing docs.
Security¶
- PR #44 —
no tool attributionworkflow (.github/workflows/no-tool-attribution.yml) scans PR title, body, and commit messages via.githooks/tool_attribution_guard.py --check; required onProtect main. - PR #45 — PR template trimmed to Summary and Test plan only (no Notes section).
- Patched frontend test-tooling transitive
js-cookieadvisory (GHSA-qjx8-664m-686j) by refreshing the lockfile tojs-cookie3.0.7;npm cinow reports zero frontend vulnerabilities. - Redaction pass before summarization/issue filing (emails, JWT-like tokens, AWS keys, GitHub tokens, bearer tokens, and keyed secrets).
- GitHub issue creation targets a separate private demo repo (
GITHUB_REPO); documented in.env.exampleanddocs/operations-manual/security.md. - Frontend dev-tool CVEs remediated — upgraded
frontend-vuetest/build tooling sonpm audit --audit-level=moderateis clean:vite6.4.2,esbuild0.25.0,vitest/@vitest/coverage-v84.1.7, plus lockfile transitive fixes forws8.20.1andbrace-expansion5.0.6. Verified withnpm run typecheck,npm test -- --run(130 tests),npm run build, andnpm audit --audit-level=moderate.langgraph/langgraph-checkpointalerts remain deferred because patched checkpoint/LangGraph combinations requirelangchain-core1.x and conflict with the current LangChain 0.3 stack. - Vulnerable Python pins bumped to patched releases (closes 7 Dependabot alerts on
main): authlib==1.3.2→1.6.12— patches 1 CRITICAL JWS injection (GHSA-9ggr-2464-2j32) and 5 HIGH advisories (OIDC bypass, padding oracle, DoS, account takeover).langchain==0.3.20→0.3.30— patches HIGH LangSmith deserialize advisory.langchain-community==0.3→0.3.27— patches HIGH advisory.streamlit==1.30.0→1.54.0— patches 2 MEDIUM Windows-only path-traversal / SSRF advisories. Verified by running the fullbackendtest suite (118 passed, 0 new regressions vs baseline) and restarting the local backend/frontend; OAuth import paths and Streamlit demo all clean. The riskierlanggraph/langgraph-checkpointmajor-version migration and thevite/esbuild(frontend dev tooling) bumps are tracked separately as follow-up work in the Dependabot alert queue.
Fixed¶
-
Frontend theme tokens compile correctly (delete-conversation dialog overlap) —
frontend-vue/src/assets/main.csswas using Tailwind v4 (@tailwindcss/vite+@import 'tailwindcss';) without a@themeblock, so design-token utilities (bg-background,bg-card,bg-muted,border-border,text-foreground,text-muted-foreground, etc.) were silent no-ops. Surfaces appeared opaque only becausebodysetbackground-color: hsl(var(--background)); inside the scrolling session list, the sidebar's sticky delete-confirmation panel had no actual background and rendered transparently over the session items. Added an@theme inlinemapping for the existing--background,--foreground,--card,--popover,--primary,--secondary,--muted,--accent,--destructive,--border,--input, and--ringCSS variables so the utilities compile. Fixes the delete-conversation dialog overlap and theUserMenudropdown which used the same pattern. -
Dependency review PR guard — added
dependency review (new high/critical CVEs)to CI usingactions/dependency-review-action@v4. It runs on pull requests and fails when a dependency diff introduces a new high/critical advisory. Dependabot alerts remain enabled, while Dependabot security auto-update PRs remain disabled for manual triage. - Secret-leak defense in depth (gitleaks layers) — five independent guards now sit between a credential and a public push:
.gitignore.env*catch-all plus pattern blocks for keys/credentials/tfvars/secrets dirs;backend/tests/core/test_env_template.py(everySettingsfield documented; no real-lookingSecretStrvalues in.env.example);- local
.githooks/pre-pushrunsgitleaks detect --log-opts="<remote>..HEAD"and fails the push on any finding (scripts/install-hooks.shwires it locally and, with--global, into~/.config/git/hooks); - new
tox -e secretsenv andgitleaks (history + diff)job in.github/workflows/ci.ymlrungitleaks detect --all --reflog --no-mergeson every PR and push; - GitHub repo settings now have Secret Scanning, Push Protection, and Dependabot alerts enabled — even
git push --no-verifyis blocked at GitHub's edge for known-provider patterns. (Dependabot security updates / auto-PR bumps are intentionally left off — they kept breaking the build; vulnerabilities are triaged manually from the alert queue.) - Tool attribution guard —
.githooks/commit-msgdelegates to.githooks/tool_attribution_guard.py(local strip +--checkfor CI). Strips AI-tool authorship lines (Co-authored-by:,Signed-off-by:, vendor URL footers) from commit messages.scripts/install-hooks.sh --globalinstalls commit-msg + pre-push protections into~/.config/git/hooks/. - Secret hardening (Pydantic
SecretStr) —SECRET_KEY,AWS_SECRET_ACCESS_KEY,AZURE_OPENAI_API_KEY,AZURE_SEARCH_KEY,OAUTH_GOOGLE_CLIENT_SECRET,OAUTH_GITHUB_CLIENT_SECRET,LANGCHAIN_API_KEY, andTAVILY_API_KEYinbackend/app/config/default.pyare now typedSecretStr, so they redact inrepr, logs, exceptions, andmodel_dump_json. Cleartext is read only at the boundary (JWT codec, OAuth client, Azure SDK, Tavily, LangSmith).simple_tracer.pyno longer logs the LangSmith key in env-var dumps. - Pydantic settings tightening —
DefaultSettings.model_configswitched fromextra='allow'toextra='ignore'with explicitSettingsConfigDict(case-sensitive, UTF-8, optionalsecrets_dirfor Docker/K8s secret mounts). Previously-undeclaredAZURE_SEARCH_VECTOR_FIELDnow declared (text_vectordefault) and documented in.env.example. - CI guard for env template —
backend/tests/core/test_env_template.pyasserts everyDefaultSettingsfield is documented in.env.example(per-field forSecretStrfields) and that noSecretStrfield carries a non-placeholder uncommented value. - Secrets management doc —
docs/operations-manual/security.mdnow describes the load precedence, the list ofSecretStrfields, a production checklist (secret stores, instance roles, rotation), and the leak-response runbook.
Changed¶
-
Generic terminology pass — replaced institution-specific brand names so the repo reads as a generic campus platform:
bCourses→Canvas LMSacross app code, prompt templates, frontend strings, and eval fixtures (~330 occurrences across 15 files); FastAPI app title, description, and welcome message rebranded toCampus AI Assistant API. -
Sample tenant renamed —
samples/berkeley/tenant_rag_config.json→samples/acme-university/tenant_rag_config.json;assistant_namebecomes "Acme University Teaching & Learning Assistant" so the sample reads as a generic placeholder rather than a real institution. -
Documentation accuracy pass — aligned CI/branch-protection docs with
Protect mainrequired checks, local tox parity (secretswithout mandatorydocs),PIP_SYNC=0backend startup, helpdesk agent API surface, and roadmap status after helpdesk merge (PRs #37–#43). Also surfaced the helpdesk agent in README, docs landing page, REVIEWER_GUIDE, PORTFOLIO_CASE_STUDY, DESIGN, OPERATIONS (runtime flags + metrics), SECURITY (privacy/redaction/kill-switch), CI (env vars), and EVALUATION (agent scenario eval). -
Environment identifier consolidated — dropped the legacy
ENVIRONMENTfield fromDefaultSettings/DevelopmentSettings/TestSettings;APP_ENVis now the only source of truth. Updatedbackend/app/main.py,backend/app/api/oauth_routes.py,backend/verify_configs.py,frontend-streamlit/app/{config,main}.py,scripts/verify_oauth.py,tox.ini(removed three redundantENVIRONMENT = testlines),.env.example, anddocs/ARCHITECTURE.md. - GitHub Pages documentation site — added MkDocs Material scaffold, docs CI build/deploy workflow,
tox -e docs, a Pages landing page, and README/documentation positioning polish around the independent extension framing. .env.examplerewritten into 16 numbered sections with explicit[REQUIRED]/[REQUIRED IF <cond>]/[OPTIONAL — default: <v>]labels on every entry; duplicates removed and previously-undocumented fields added..env.testreorganized to mirror the same section numbering as.env.example;APP_ENV=testset explicitly.
[2026-05-19] — Portfolio polish (PR #24)¶
Changed¶
- Docs (portfolio polish) — README restructured for progressive disclosure (pitch, role alignment, highlights, upstream delta, quality baseline); added PORTFOLIO_CASE_STUDY.md, docs/adr/ (4 ADRs), PRODUCTION_HARDENING.md; reframed EVALUATION.md baseline paragraph; updated docs/README.md index.
- README — Overview without
<details>collapsibles (full architecture, design, screenshots, LangSmith traces visible); CI status badge. - Eval — expanded eval_baseline_2026-05-19.md (retained AWS scores, Azure sweep table, findings); eval respects LangGraph when
RAGAS_EVAL=1; Phase 5 script precision-balanced profile;RAGAS_DO_NOT_TRACKin tox eval. - Logging —
RequestIdFilteron handlers; redact JWT payloads and chat queries at INFO; cap vendor loggers; optionalLOG_JSON; access log viaapp.access; single idempotentinitialize_logger(). - Docs — documentation cohesion: DESIGN.md (product boundaries, decisions); README problem/quality sections; rename PRODUCT_ROADMAP.md; de-portfolio language; generic campus/Canvas LMS framing; document Bedrock KB + OpenSearch Serverless alongside Azure Search; expanded docs/README.md index; ARCHITECTURE.md LangGraph/OAuth/research_mode; WEB_RESEARCH.md KB path diagram; CI.md portfolio quick tox note; E2E.md OAuth note; RELEASE.md tag message; deduped CHANGELOG
[Unreleased].
[2026-05-19] — Portfolio features (PRs #13–#17)¶
Added¶
- Phase 5 retrieval — multi-query expansion/fusion, optional Bedrock/client metadata filters, rerank node (condense → multi_query → retrieve → rerank → generate).
- Phase 5 rerank — LangGraph
reranknode; FlashRank + keyword fallback;RERANK_*settings; candidate fetch viaRERANK_CANDIDATE_K. - Phase 3 lite — README Quality & observability; LangSmith
chat-session-*run names; curated goldenground_truth;scripts/promote_golden_draft.py. - RAGAS golden bootstrap —
scripts/bootstrap_golden_dataset.py,backend/tests/eval/seed_questions.json; golden set refreshed from live AWS KB (10 rows). - OAuth (dev) — API-port OAuth + one-time handoff to Vue (
/oauth/handoff) fixes GitHubstate_mismatchacross Vite proxy ports.
Changed¶
- Docs — README refresh (highlights, LangGraph/web/eval features, stack table); screenshot gallery under
docs/assets/{product,observability,auth}/; doc index (docs/README.md), ARCHITECTURE.md, WEB_RESEARCH.md; consolidated LangSmith capture in EVALUATION.md;.gitignorefor.cursor/and golden draft. - Phase 5 retrieval tuning — RRF document fusion, keyword prefilter before rerank; tuned eval profile in
scripts/run_eval_phase5.sh(faithfulness/recall up vs initial Phase 5; precision still below gate). - Phase 3 lite — portfolio RAGAS baseline policy; LangSmith trace screenshots in README; Phase 3 roadmap marked done (lite).
Fixed¶
[2026-05-19] — GitHub Actions CI/CD¶
Added¶
- CI/CD — GitHub Actions:
ci.yml(tox onmain+ PRs),cd.yml(Vue build + optional EB deploy onqa/release); docs/operations-manual/ci-cd.md. Removed.travis.yml.
Fixed¶
- CI — pin
@rollup/rollup-*platform packages infrontend-vueoptionalDependencies (fixes Linuxnpm cioptional-deps bug). - CI — use
HUSKY=0 npm ci(not--ignore-scripts) so Rollup native bindings install on Linux runners. - CI —
frontend-vuetox env skipsnvm usewhenCI=true(GHA) or nvm is absent; CI workflow runs tox sequentially.
Changed¶
- CI —
tox -e lint,backend,frontend-vuegreen; ruff format/fix, LangGraph import fixes, ChatViewresearch-modebinding. - Docs — roadmap cleanup: PRODUCT_ROADMAP.md is the single index; removed
TODAY_SPRINT.mdandroadmap/README.md; campus scale track moved to archive/PHASED_IMPROVEMENT_ROADMAP.md. - Tests —
conftestforcesRAG_ENGINE=chainso API stream tests stay isolated from developer.env.
[2026-05-18] — Security dependency bumps¶
Changed¶
- Runtime dependencies — FastAPI 0.115.x (Starlette CVE fixes),
python-multipart>=0.0.27,python-jose>=3.4,PyJWT>=2.12,requests/urllib3/httpxupgrades,gunicorn>=22,python-dotenv>=1.2.2. - LangGraph pins — exact
langgraph==0.2.76+langgraph-checkpoint==2.0.26(resolveshttpxconflict with LangChain 0.3).
Added¶
- docs/operations-manual/security.md — audit commands, production hardening checklist, dependency policy.
[2026-05-18] — LangGraph live validation (AWS KB parity)¶
Added¶
- LangGraph live path —
run_rag_graphimport fix; live AWS KB smoke validated withRAG_ENGINE=langgraph(sources + coherent answers). - LangGraph SSE — status event while graph runs in
asyncio.to_thread; paced token chunks for progressive UI (simulated streaming until graph-native stream). - Web research (frontend) —
research_modeon API; Pinia +ChatInputtoggle whenVITE_WEB_RESEARCH_ENABLED=true(serverWEB_RESEARCH_ENABLEDrequired). - Docs — sprint checklist updates; LangGraph latency notes in LANGGRAPH.md.
Changed¶
- Dependencies — pin
langgraph0.2.x +langgraph-checkpoint2.x for LangChain 0.3 compatibility (see upcoming security branch for broader bumps). scripts/run-backend-venv.sh— start via./venv/bin/python -m uvicornso reload uses project venv.
Fixed¶
- Answer leakage — stronger
_strip_condensed_question_leakage(backend +normalizeAssistantContent). - Empty-state prompts —
{{ prompt }}mustache inMessageList.vue. - SSE burst render —
requestAnimationFramebetween tokens inchat.ts. - Graph unit tests — mock patch fixture and KB-path LLM stub.
[2026-05-18] — GitHub OAuth, LangGraph scaffold, and chat UI polish¶
Added¶
- GitHub OAuth —
POST /api/auth/oauth/{provider}/startand callback routes;OAuthButtons.vue; Alembic0003user OAuth fields;scripts/verify_oauth.py. backend/app/core/auth_cookies.py— shared HTTP-only JWT cookie helpers for login and OAuth.- RAG streaming —
stream_query_async()via LangChainastream_events; SSEstatusevents; condensed-question leakage stripping inrag.py. - LangGraph scaffold —
backend/app/services/graph/(runner, nodes, state); opt-inweb_searchtool;RAG_ENGINE=langgraphconfig (default remainschain). - Docs — PRODUCTION_TLS.md (HTTPS + OAuth redirects); SPRINT_2026-05-18_LANGGRAPH.md; WEB_RESEARCH.md.
- Vue chat UI — typography scale (
text-chat-*,.chat-prose); wider layout; mobile sidebar overlay; accessible user message accent; assistant sources stacked below replies; sticky composer.
Changed¶
- Local dev defaults — Vite on
http://127.0.0.1:5173(strictPort);FRONTEND_URL/OAUTH_REDIRECT_BASE_URLaligned to avoidMismatchingStateError(see PRODUCTION_TLS.md). - Frontend — Pinia chat store appends stream tokens immediately; dedicated
/api/chat/streamVite proxy (no buffering). - Auth API — login/register use shared cookie helpers; OAuth links or creates users by provider subject.
- Roadmap docs — LangGraph and portfolio roadmap updated for sprint status.
requirements.txt— LangGraph-related dependencies for graph scaffold.
[2026-05-18] — Generic tenant-hydrated RAG prompts¶
Added¶
backend/app/services/tenant_rag_config.py— load branding from env +tenant.rag_config(JSONB).- Alembic
0002—tenant.rag_configcolumn. docs/TENANT_CONFIG.md— config shape and resolution order.samples/acme-university/tenant_rag_config.json— generic campus sample tenant profile (not default; renamed from the originalsamples/berkeley/path during the documentation accuracy pass).
Changed¶
- Prompt templates — generic
prompt_prefix.txt/few_shot_examples.jsonwith{{placeholders}}. - Chat + RAG — hydrate prompts per request from the signed-in user's tenant.
PROJECT_NAME/.env.example—ASSISTANT_NAME,SUPPORTED_TOPICS,OUT_OF_SCOPE_MESSAGE.- README — bring-your-own KB + tenant config.
[2026-05-18] — Performance Phase 0 quick wins¶
Added¶
docs/PERFORMANCE.md— Phase 0 shipped tuning; documentation checklists for Phase 1–3.- Config:
CHAT_HISTORY_MAX_MESSAGES,STREAM_ARTIFICIAL_DELAY_MS,SQLALCHEMY_POOL_SIZE,SQLALCHEMY_MAX_OVERFLOW(see.env.example). - Prometheus:
chatbot_chat_first_token_latency_seconds(SSE time-to-first-token). - Test:
test_get_session_messages_respects_max_messages.
Changed¶
- Streaming: removed fixed
time.sleepon SSE tokens; optional demo delay viaSTREAM_ARTIFICIAL_DELAY_MSin RAG only. - Chat API:
_load_chat_history()caps messages passed to LangChain. - DB: SQLAlchemy engine uses configured pool +
pool_pre_ping. run_services.sh: multi-worker uvicorn viaAPI_WORKERS/UVICORN_WORKERS(default 2).docs/operations-manual/operations.md: SLOs split for auth/session vs live RAG; first-token alert hint.docs/roadmap/PHASED_IMPROVEMENT_ROADMAP.md: Phase 0 perf shipped note; FlashRank marked Phase 2 / not inrag.pyyet.
[2026-05-18] — Docs cleanup and Campus RAG Assistant rebrand¶
Changed¶
- README: product-first Campus RAG Assistant opening; license/attribution under License.
- GitHub repo renamed to campus-rag-assistant; About description updated.
- changelog/CHANGELOG.md — single session-based log under
changelog/(other files in folder gitignored). - Trimmed ARCHITECTURE.md; clarified known gaps (buffered chat vs SSE).
Removed¶
docs/PORTFOLIO.md,docs/EXECUTION_PLAN.md,docs/DOC_AUDIT.md,scripts/new-changelog.sh.
Added¶
- Full session history in changelog/CHANGELOG.md (2025 Berkeley baseline + 2026 fork sessions).
[2026-05-17] — tox and Vue in CI¶
Merged as PR #9.
Added¶
- tox
frontend-vueenv:npm ci, typecheck, ESLint, Vitest (Node 20 via.nvmrc). - requirements.txt:
langchain-openai, Azure SDKs;bcrypt>=4.0.1,<4.1.0for passlib in tox. - Lazy Azure provider imports in
backend/app/services/providers/__init__.py.
Changed¶
- tox
backend:RATE_LIMIT_ENABLED=false, excludeslow(RAGAS) by default. - README Testing:
tox -e lint,backend,frontend-streamlit,frontend-vue. - Ruff/pytest marker cleanups.
[2026-05-17] — Portfolio publish to GitHub¶
PRs #1–#8 → campus-rag-assistant main.
Packages work from May 2026 dev sessions into reviewable commits.
PR #1 — Dev tooling¶
.githooks/pre-commit,scripts/install-hooks.sh,run-backend-venv.sh,run-frontend-vue.sh,kill-dev-servers.sh, load-test helpers..gitignoreportfolio hygiene.
PR #2 — Alembic¶
alembic.ini,backend/alembic/,0001_initial_schema.py.
PR #3 — Platform middleware¶
request_context.py,metrics.py,rate_limit.py,dev_routes.py; wired inmain.py,auth.py,chat.py.
PR #4 — Providers, RAG, eval¶
backend/app/services/providers/(AWS / Azure / mock);rag.pyregistry wiring.backend/tests/eval/RAGAS golden harness.
PR #5 — Vue 3 SPA¶
frontend-vue/scaffold, API/auth, chat UI, sessions, sources, Vitest + Playwright scaffolding.
PR #6 — Streamlit client¶
frontend-streamlit/(auth, chat services, UI components, pytest).
PR #7 — Load tests¶
load-tests/k6 smoke + auth-chat-session; user seed script.
PR #8 — Docs and README¶
docs/architecture, operations, E2E, evaluation, roadmaps, LangGraph design.- Portfolio README, mock
.env.example.
Post-publish cleanup (PR #7–#8 follow-ups)¶
- Removed duplicate
frontend/tree;run_services.sh/ tox →frontend-streamlit/. main.py:create_allonly in dev/test;requirements.txt:alembic,redis.- Removed root
root-open-k6.js, empty rootpackage-lock.json.
[2026-05-01] — RAG platform, Vue, providers (dev session)¶
Implementation work; landed on main via 2026-05-17 PRs above. Some session notes describe features not merged.
Added — on main¶
- Vue 3 SPA, Streamlit tree, provider registry, Redis rate limiter, Prometheus metrics, dev routes, RAGAS eval, core scripts.
Added — session plan only (not on main)¶
POST /api/chat/stream(SSE); FlashRankRERANK_*; extra tox envs (eval,load-smoke, …).
Changed / fixed / security¶
rag.py,chat.py, schemas,.env.example, requirements, ruff / pytest; password rules;MessageBubble.vue; generic chat 500s; EB health proxy.
Follow-ups¶
- RAGAS golden Q&A; production
REDIS_URL; LangGraph / SSE / rerank — docs/roadmap/LANGGRAPH.md.
[2026-05-01] — Logging and request correlation (dev session)¶
Summary¶
One request id per HTTP request (X-Request-ID); optional JSON logs; quieter auth logs.
Added¶
request_context.py,LOG_JSON, tests,kill-dev-servers.sh, Vueinterceptors.tsforX-Request-ID.
Changed / removed / security¶
logger.py,main.py,security.py, config; removed unusedLOGGING_PROPAGATION_LEVEL; no JWT dumps at INFO.
Berkeley ETS Chabot (baseline)¶
Chabot — campus RAG chatbot for UC Berkeley ETS over AWS Bedrock.
Upstream: ets-berkeley-edu/chabot.
© The Regents of the University of California — LICENSE.
sandeep-jay led implementation (CBO-tracked PRs below). Regents headers remain on derived files in this fork.
[2025-08-01] — Streamlit UX and frontend tests¶
Added¶
- Streamlit refactor: chat interface, message display, feedback UI and stylesheets ([CBO-86]).
- Frontend test suite covering auth, chat, and message modules ([CBO-89]).
[2025-06-13] — Backend and API test suites¶
Added¶
- Pytest for RAG workflow, AWS/Bedrock/LangSmith, auth, DB/models/services ([CBO-69], [CBO-71], [CBO-72], [CBO-84]).
- Chat API interaction tests: CRUD, feedback, sources, mocks ([CBO-70]).
pyproject.tomltool config; tox/travis alignment ([CBO-72]).
[2025-06-05] — Streamlit cleanup¶
Changed¶
- Removed basic Streamlit prototype in favor of modular refactor ([CBO-99]).
[2025-05-30] — Chat API and Streamlit auth¶
Added¶
- Chat endpoints: sessions, messages, feedback,
test_langsmith([CBO-45]–[CBO-47]). - Streamlit login, auth module, client services ([CBO-65], [CBO-66], [CBO-80], [CBO-81]).
[2025-05-29] — JWT auth and advanced RAG¶
Added¶
- JWT authentication module and auth endpoints ([CBO-74], [CBO-75]).
- Advanced RAG with Bedrock integration ([CBO-85]).
[2025-05-28] — Elastic Beanstalk deploy sketch¶
Added¶
.ebextensionsand Nginx config for FastAPI + Streamlit ([CBO-63]).
[2025-05-12] — Bedrock RAG and first UI¶
Added¶
- AWS, LangChain, Bedrock; simple RAG and
/chatintegration; prompt templates ([CBO-31], [CBO-34], [CBO-36], [CBO-41]). - Basic Streamlit chat UI + LangSmith tracing ([CBO-36], [CBO-42]).
- ruff and tox ([CBO-67]).
[2025-05-05] — FastAPI foundation¶
Added¶
- FastAPI boilerplate (
/,/health) ([CBO-30]). - Pydantic-settings config manager ([CBO-32]).
- Modular logger ([CBO-35]).
- SQLAlchemy + chatbot table design ([CBO-49]).
[2025-05-13] — CI and README¶
Added¶
- Travis CI linters ([CBO-82]).
- README instructions ([CBO-82]).
Changed¶
.gitignorefor.toxand.ruff*([NOJIRA]).