Commit Graph

73 Commits

Author SHA1 Message Date
daveadmin 8587ec372f fix: expose DBN_USER_TIER so plus/pro SSO users can use doc picker
isPaidUser() was checking DBN_FREE_TIER_BALANCE === undefined, which
is only true for CaveauAI sessions. SSO users (even plus/pro) always
have DBN_FREE_TIER_BALANCE set, so the picker was showing the upgrade
modal for everyone in the SSO flow. Now reads DBN_USER_TIER explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:45:57 +02:00
daveadmin f383ad5b74 feat: document & audio corpus picker for all tools
- Add "Select from My Docs" button to all text tool forms; free-tier
  users see an upgrade modal, paid (CaveauAI) users get a searchable
  multi-select modal backed by /api/dashboard/documents.php
- Add "Select from My Audio" picker on Transcribe with single-select
  and a "Save to My Audio" button for persisting uploaded clips
- New PHP helpers in bootstrap.php: dbnToolsFetchDocChunks,
  dbnToolsClientIdFromSession, dbnToolsInjectDocContent
- timeline, ask, redact APIs prepend selected document content
  (fetched from client_chunks SQL) before the textarea text
- api/dashboard/audio-upload.php stores audio files on server and
  creates a client_documents row with source_type='audio'
- api/transcribe.php falls back to stored audio via audio_doc_id POST
  field when no file is uploaded
- api/dashboard/documents.php supports ?source_type= filter
- tools.js: doc_ids added to JSON payload; stored-audio transcribe path
- New assets/css/doc-picker.css, assets/js/doc-picker.js
- SQL migration: scripts/sql/audio_docs_column.sql

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 21:38:04 +02:00
daveadmin 90117fa9de feat(nav): unified navbar, account page, corpus summary widget, and i18n fixes
- New includes/nav.php: sticky site-wide nav with Tools dropdown, Dashboard
  link, compact language switcher, user identity → /account.php, Log out
- New account.php: credits & plan, profile, team, usage sections
- New api/corpus-summary.php: JSON endpoint for corpus doc count + last updated
- Replaces topbar in layout.php, layout_dashboard.php, and dashboard.php
- Fixes hardcoded Norwegian strings in dashboard.php credit cards via dbnToolsT()
- Adds 35 new i18n keys across all 4 languages (en/no/uk/pl) in i18n.php
- CSS: .dbn-nav navbar + .account-* account page styles in tools.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:11:39 +02:00
daveadmin 33dc5406b2 feat(auth): add login/logout, user identity, and soft auth gate
- api/logout.php: destroys session + clears cookie, redirects to /
- api/guest-session.php: sets guest flag, lets users explore without account
- layout.php: removes hard PHP redirect; authenticated users see email +
  "Logg ut" in topbar; guests see guest banner (sticky, dismissible) and
  auth gate modal (dismissible via localStorage) instead of redirect
- layout_footer.php: injects auth gate modal + JS for banner/modal dismiss
- layout_dashboard.php: adds username + "Logg ut" to dash-topbar
- index.php: adds "Utforsk uten konto" link under primary login CTA
- tools.css: .guest-banner, .auth-gate-*, .topbar-user, .dash-topbar__user

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 18:05:51 +02:00
daveadmin 06d01a3bce feat(dashboard): add corpus dashboard at /dashboard/
Full private corpus dashboard for tools.dobetternorge.no users — each SSO
account gets an auto-provisioned CaveauAI tenant (clients row, corpus) on
first visit. Includes upload (file/paste/URL), RAG chat with SSE streaming
and citation chips, document CRUD, FalkorDB graph relations tab, and
improved save-from-tool flow with tag/preview support.

- dashboard/{index,documents,document,upload,chat,settings}.php
- api/dashboard/{corpus-init,documents,upload,ingest-status,chat-stream,
  save-from-tool,graph}.php
- includes/{CorpusProvision,layout_dashboard,layout_dashboard_footer}.php
- assets/css/dashboard.css  assets/js/corpus-save.js (routing upgrade)
- includes/{bootstrap,layout}.php extended for dashboard provisioning

Migration 141 (clients.dbn_sso_uid + import_method enum) applied on chloe.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 17:15:40 +02:00
daveadmin 83fc71414f Add premium My Case MVP 2026-05-23 10:17:34 +02:00
daveadmin e0aeefc73e Add member welcome modal and promote public login CTAs
- dashboard.php: welcome overlay modal on first visit, shows all 10 tool
  tips in a 2-col grid; localStorage key dbn-welcome-v1-seen persists
  dismiss; "Don't show again" checkbox (default checked); backdrop+Escape
  close without persisting
- index.php: Sign in / Join free buttons added to sticky nav; access gate
  section moved from page bottom to immediately after hero so login CTAs
  are the first thing a visitor sees without scrolling; gate card titles
  enlarged and top-border accent added for visual weight
- tools.css: .wlc-* welcome modal styles; .lt-nav__btn-signin/join nav
  CTA button styles; .lt-gate--prominent and .lt-gate__card-title--large

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 20:17:02 +02:00
daveadmin b014638f39 feat(corpus): add save-to-corpus + private corpus search scope
- POST /api/save-to-corpus.php — saves tool output text to user's default CaveauAI corpus via ClientRagPipeline
- api/case/upload.php — dual-writes uploaded PDFs to CaveauAI client_documents (best-effort)
- assets/js/corpus-save.js — shared <dialog> handler for .js-save-corpus buttons on all tool pages
- includes/layout_footer.php — injects corpus-save.js + shared save dialog markup
- korrespond/deep-research/barnevernet/discrepancy JS — save-to-corpus buttons on output sections
- api/search.php + LegalTools::search() — corpus_scope param ('shared'|'private'|'both'), merges personal CaveauAI corpus with shared legal library when 'both'
- includes/tool_form.php + assets/js/tools.js — corpus scope radio toggle shown on search tab
- api/user-docs.php — add POST upload method for non-SSO authenticated users

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 17:50:32 +02:00
daveadmin fe9a1812f1 Promote why-ours strip to top; add pricing CTA section at bottom
- Add prominent navy why-ours banner strip between hero and tools grid:
  eyebrow, large title, sub-text, 3 checkmark bullet points, gold CTA button
- Add pricing CTA strip after trust section: eyebrow, title, sub-text,
  4 tier pill tags (€0/€9/€29/€79), navy CTA button to pricing.php
- Remove the small pill links from the bottom of the trust section
- All new sections fully translated in no/en/uk/pl (11 new i18n keys)
- Add .lt-why-strip and .lt-pricing-strip CSS in tools.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 07:55:09 +02:00
daveadmin 7edc42c483 Add EN/UK/PL translations across index, footer, and why-ours pages
- index.php: translate hardcoded hero kicker, stat, explore CTA, tools
  section title/sub, and learn-more arrow; add Pricing nav link
- footer.php: fully translate tagline, privacy note, nav links, and
  disclaimer into all 4 languages via dbnToolsT()
- includes/i18n.php: 15 new keys per language (hero_kicker, footer_*,
  tools_section_*, pricing_nav_link, why_ours_trust_link, learn_more)
- translations/why-ours.php: complete uk + pl translations (70 keys each)
- assets/css/tools.css: add .lt-nav__secondary-link style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 07:48:40 +02:00
daveadmin abdad0f7e3 Fix infographic images not scaling to browser width
Removed hard-coded pixel width/height attributes from <img> tags and
tightened kdoc-diagram-img CSS (max-width:100%, overflow:hidden) so
images scale fluidly at all viewport sizes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 07:37:22 +02:00
daveadmin 2aa86a0950 Replace CSS comparison/graph diagrams with custom infographic images
Swaps the CSS-only kdoc-compare and kdoc-graph blocks for two custom
transparent-background PNGs (+ lossless WebP) designed by the user.
memoryVlibrary shows the two-path General AI vs DBN flow; norwegianLaw
shows the connected-law knowledge graph. Both served via <picture> with
WebP primary and PNG fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 07:23:53 +02:00
daveadmin fc84bb31fe Add why-ours.php — plain-language explainer page
Explains why Do Better Norge tools give different answers than ChatGPT:
RAG, BM25+vector search, reranker, knowledge graph, fine-tuned model.
Includes EN/NO translations, 5 optimised WebP/JPEG images, new kdoc-compare
and kdoc-graph CSS components. Link added from index.php trust section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 06:48:02 +02:00
daveadmin ba9cddf9a1 Add monetization spine + Build Your Own Case (Min Sak)
- Stripe: StripeClient.php, checkout/portal/webhook endpoints, idempotent event handling
- FreeTier: tier-aware credits (free/light/pro/pro_plus), bonus_balance, hourly caps per tier
- pricing.php + billing.php: 4-tier cards, 3 topups, Customer Portal, balance breakdown
- Min Sak: CaseStore.php, AzureDocIntelligence.php, AzureSearchAdmin.php — per-user hybrid RAG
- api/case/: upload, list, delete, ingest-callback (HMAC-auth'd from n8n)
- award-survey-credits: inter-site HMAC endpoint for dobetternorge.no survey bonus
- dashboard.php: tier badge, balance breakdown card, Min Sak CTA, survey CTA
- KorrespondAgent + all 3 other agents: use_my_case toggle wired to dbnToolsCaseContext()
- bootstrap.php: dbnToolsCaseContext(), dbnToolsIntersiteSecret(), dbnToolsCurrentTier()

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 20:52:54 +02:00
daveadmin 0e167bf464 Integrate dbn-legal-agent-v2: upgrade all v1 refs + add Korrespond legal-check
- Replace dbn-legal-agent with dbn-legal-agent-v2 in bootstrap.php
  (dbnToolsRunLegalCheck), DeepResearchAgent.php (interpretSeed,
  expandQueries, synthesis fallback, deploy label), BvjAnalyzerAgent.php
  (check_model label) — 8 locations total
- Add dbn-legal-agent-v2 legal threshold check to KorrespondAgent:
  called after selfCheck() in both generate() and refine(); result
  surfaced as legal_check[] in the API response
- Render legal_check card in korrespond.js using existing bvj-red-flag
  styles; shows only when non-empty
- Add .korr-legal-check CSS block in tools.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 23:59:07 +02:00
daveadmin 81ba20c44a Add Timeline documentation pages (about, guide, tech)
3 new public pages matching the korrespond doc pattern: timeline-about.php
(marketing), timeline-guide.php (user guide), timeline-tech.php (tech
showcase). Hero images + 4 screenshots in assets/images/timeline/. Doc
links added to timeline.php and preview.php?tool=timeline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:00:40 +02:00
daveadmin 1638db3eb9 Add output-draft screenshot inside step 2 card on about page 2026-05-19 13:39:58 +02:00
daveadmin b554d62cd7 Fix: force single-column steps grid on mobile to remove stretch gap under step 2 2026-05-19 13:02:42 +02:00
daveadmin 7c4b161f04 Add 3 public Korrespond documentation pages with AI hero images
- korrespond-about.php: marketing/hype page with hero image, features,
  3-step pipeline, screenshot gallery, dbn-legal-agent LLM spotlight,
  authority coverage grid, and CTA strip
- korrespond-guide.php: step-by-step user guide covering mode selection,
  recipient body presets, output types, tone, all form fields, clarify
  gate, output columns, and Refine pass
- korrespond-tech.php: technical showcase — Hard-RAG pipeline diagram,
  corpus stats, CITE:N verification system, fine-tuned model details,
  formal citation style guide, privacy section
- 5 UI screenshots + 3 AI-generated hero images in assets/images/korrespond/
- korrespond.php: add "About · User guide · How it works" inline links
- preview.php: add korrespond to localizedContent (en+no) and samples;
  render doc-page links in preview CTA section for korrespond slug
- tools.css: +600 lines .kdoc-* CSS (hero, features, pipeline, guide
  steps, tech diagrams, finetune block, privacy block, stat cards)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:49:38 +02:00
daveadmin 28932297b3 Add user context notes field to timeline tool
Adds an optional textarea below the main text input where users can provide
clarifications to guide the LLM — e.g. year anchors, actor aliases, or focus
instructions. Notes are injected into the prompt as a clearly delimited block
and translated across all four UI languages (en/no/uk/pl).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:36:37 +02:00
daveadmin dfb9692f45 Korrespond: stop mixing UI languages — all chrome follows user UI lang
Drafts still come back in Norwegian + working language (that is intentional),
but every piece of *chrome* now respects the user's UI lang consistently:

- Pass 1 classify LLM now writes missing-fact questions in the user's language
  (not always Norwegian), fixing the case where an English-UI user got "Hva er
  saksnummeret?" in the clarify panel.
- All PHP-emitted progress/status messages go through DbnKorrespondAgent::L()
  with en/no/pl/uk variants instead of hardcoded Norwegian.
- JS introduces an I18N dictionary + t() helper covering status messages,
  button labels, column headers, flag labels, refine panel title/hint,
  jurisdiction radio labels, clarify panel title/hint/buttons, the empty-state
  "Ready" block, and Copy/Copied/Download .txt.
- Static clarify and empty-state chrome use [data-i18n] attributes resolved at
  init and re-applied on every lang-switcher click.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:11:16 +02:00
daveadmin 5d8ae6b447 Korrespond: add Refine pass with jurisdiction-scoped formal citations
After the first draft is rendered, a "Refine with citations" panel offers a
3rd-pass rewrite scoped to the user's choice of Norwegian law, ECHR (EMK +
HUDOC case law), or both. Refine pulls fresh corpus chunks limited to the
chosen jurisdiction's slices, rewrites inline cites in formal style ("jf.
forvaltningsloven § 17", "jf. Strand Lobben m.fl. mot Norge, EMD-37283/13,
§§ 207–214"), and appends a Rettskilder block listing every authority.
Hard-RAG grounding carries through — refine cannot cite anything that
wasn't retrieved. Costs 1 additional credit; the original draft stays in
place and the refined version appears below it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 11:50:36 +02:00
daveadmin b78a49e060 Add Korrespond tool: drafts replies & new correspondence to NO authorities
Two-pass wizard for drafting to NAV, Barnevernet, schools, Bufdir, kommune,
Statsforvalter, Trygderetten. Pass 1 (gpt-4o-mini) classifies the situation
and emits clarify questions if facts are missing; user answers inline and
resubmits without losing context. Pass 2 retrieves law passages via hard-RAG
(ClientRagPipeline with body-specific slice presets), drafts in Norwegian
bokmål with gpt-4o using [CITE:N] tokens, self-checks that every citation
maps to a real corpus passage, then translates to the working language.
Result is side-by-side Norwegian + EN/PL/UK with copy/download per side
and an expandable Cited Law panel.

Credit deducts only when Pass 2 actually runs, not on a clarify cycle.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 11:27:13 +02:00
daveadmin bc44b0eee2 Add My Documents panel to workbench + user-docs API
- api/user-docs.php: GET/DELETE shared dbn_user_docs table (SSO users only)
  connects to dobetternorge DB via DBN_DB_* env vars
- workbench.php: My Documents panel (section 05) for SSO/free-tier users;
  shows docs uploaded from either AI chat or tools, links to AI Chat for upload
- workbench.js: fetch + render doc list, delete with Qdrant cleanup
- tools.css: workbench-docs panel + item styles
- i18n.php: my_docs_* strings in all 4 languages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 09:37:19 +02:00
daveadmin 04555a96b1 Add Citation Explorer tool and graph-expansion badges to Advocate results
- citations.php + assets/js/citations.js: new tool page for browsing the
  FalkorDB citation graph by title/ID, with autocomplete, action pills
  (cites/cited_by/implements/chain), hop-by-hop navigation, and exploration trail
- advocate.js: tag graph-expanded source cards with 'via citation graph' badge
- DeepResearchAgent: propagate _graph_expanded flag through normalizeCorpusChunk
  and top_sources serialization so it reaches the frontend
- tools.css: add .dr-source-tag--graph variant (green pill)
- i18n.php: register 'citations' tool in all 4 languages with CIT icon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:30:04 +02:00
daveadmin e977bbb6b3 Add Document Discrepancy Finder tool
8-step NDJSON-streaming pipeline that compares two Barnevernet documents:
classifies each doc, extracts parties and timelines, cross-references both
for contradictions/deletions/additions, retrieves corpus legal context, and
synthesises a full discrepancy report with tabbed UI.

New files: DiscrepancyAgent.php, api/discrepancy.php, discrepancy.php,
discrepancy.js. Modified: FreeTier.php (cost=4), i18n.php (all 4 langs),
tool-svgs.php (DC icon), tools.css (dc-* component styles).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:30:38 +02:00
daveadmin 1246b7a804 feat(workbench): add DBN Case Workbench guided case-preparation hub
Additive-only change: new workbench.php authenticated page with guided
intake flow, evidence map, tool sequence, output checklist, and
sessionStorage-only note persistence. Dashboard and public index get
a new Case Workbench card. No existing tools, APIs, or prompts modified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:08:16 +02:00
daveadmin b495ff29fd feat(corpus): make source links visible on search result cards
- a.passage-card__title now shows teal+underline (was ink/no-decoration, undetectable)
- adds "View source ↗" link below each passage excerpt when source_url present

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:16:04 +02:00
daveadmin ffcf887428 feat(timeline): add live filter, actor chips, group headers, copy button, source toggle, count badge
- Live search/filter bar: filters events by keyword across event, actor, source_excerpt, date
- Actor filter chips: click to filter by actor, multi-select, teal active state
- Year/month group headers when sorted chronologically (── 2023 ──, Mar 2024 ──)
- Per-event copy button (hover-revealed 📋): copies "date · actor · event" to clipboard
- "Hide/show sources" toggle: collapses all source excerpts without re-rendering
- Count badge: "23 events · 3 actors · 2022–2025" above the list
- applyTimelineFilters() unifies sort + actor + text filters in one re-render pass
- CSV export now includes end_date column
- Reset all filter state on each new run

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:46:59 +02:00
daveadmin 59b39ff85b feat(redact): tag highlighting, inventory panel, before/after toggle, gpt-4o upgrade
- CSS: colour-coded [TAG] spans by entity type (person=pink, org=blue,
  place=green, date=amber, id=purple)
- Inventory panel: collapsible list showing tag → original text mappings
  with occurrence counts, sourced from new redaction_map API response key
- Before/after toggle: Redacted / Original view-switch buttons wired to
  lastOriginalText captured at submission time
- One-click gpt-4o upgrade button when mini or GPU engine was used
- Backend: redaction_map built from applied LLM entities (tag → originals
  + occurrence count via substr_count on final text)
- renderResults now calls setupRedactViewToggle() after DOM is written

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:22:41 +02:00
daveadmin 850937e4b3 feat(transcribe): UX improvements — progress bar, stats row, copy btn, char counter, batch errors
- Vocab textarea now shows live 0/500 char counter (turns amber at 450+)
- Animated progress bar during transcription; determinate for multi-clip, indeterminate for single
- Results card shows inline stats row (duration, language, speakers) and AI cleanup badge
- Copy button + Download TXT moved above transcript box; SRT/VTT remain below
- Speaker role legend repeats inside Segments panel for easy cross-reference
- Batch errors no longer halt the queue; remaining clips continue, failed files named in status bar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:21:19 +02:00
daveadmin c4362738c1 feat(transcribe): GPT cleanup pass + advanced options i18n
Adds optional post-transcription cleanup via GPT-4o/GPT-4o-mini to fix
mishearing errors, punctuation, and domain terms. Speaker role labelling
now accepts a deployment param. Adds i18n strings for advanced options
panel (task, VAD filter, Whisper model, AI cleanup) in all four languages.
Updates BvjAnalyzerAgent and DeepResearchAgent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 07:23:01 +02:00
daveadmin f2fbb69e0a feat: lightweight header/footer — IBM Plex Sans, slimmed nav badge, compact footer
Drops Roboto + IBM Plex Mono from Google Fonts, replaces with IBM Plex
Sans (matching dobetternorge.no). Nav badge loses bordered pill, becomes
plain uppercase label with slash separator. Footer cut from 3-column
text-wall (~300 words) to compact 2-column layout (~50 words) — logo +
tagline + privacy note on left, 5 links in 2 columns on right.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 07:10:46 +02:00
daveadmin f0b7d343a3 feat: unified landing page with auth-aware gate + /dashboard.php
Removes the logged-in vs logged-out page bifurcation. index.php now
always renders the public landing (tools overview, hero, trust section)
with auth-conditional nav/hero CTAs and a two-column member/register
gate shown only to unauthenticated visitors. Authenticated workbench
extracted to new dashboard.php. Adds 8 new i18n keys across all 4
languages and new CSS for auth-nav, hero CTA, two-column gate, and
register buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 06:45:44 +02:00
daveadmin 849a7cf434 feat: add public tool preview pages with realistic samples
Each landing card now links to preview.php?tool=SLUG — a dedicated
public page with an expanded pitch, 4 capability bullets, and a
realistic Norwegian-language sample input+output for all 7 tools.

- preview.php — new public page (no auth required), switch-driven content
- includes/tool-svgs.php — extracted $toolSvgs into shared include
- index.php — require tool-svgs.php, card href → preview.php?tool=SLUG
- assets/css/tools.css — lt-preview-* component styles appended

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 13:08:46 +02:00
daveadmin c350750b7e fix: serve logo locally to fix broken image on nav/footer
External URL was unreachable from tools subdomain (CSP or cross-origin block),
causing a grey placeholder rectangle. Logo now served from assets/images/ and
brightness/invert filter removed — logo is white-on-transparent, displays
correctly on dark nav and footer without filtering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:41:11 +02:00
daveadmin 38683cffc0 feat: rebrand landing page to match dobetternorge.no
- Add sticky navy nav with logo-header.webp, Legal Tools badge, lang switcher, red CTA
- Replace showcase-hero with full-bleed dark hero (Crimson Pro, IBM Plex Mono, stat pills)
- Redesign tool cards: 3-col grid, 178px illustrated SVG art per card (7 unique illustrations)
- Add lt-trust 3-col strip and lt-access navy gate panel
- Rebuild footer with 3-col navy layout matching main site
- Add Crimson Pro / Roboto / IBM Plex Mono Google Fonts via <link> + @import
- CSS: new lt-* variables, all new landing component styles appended to tools.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:33:31 +02:00
daveadmin 8b77acb828 feat: free-tier credit system + Syttende Mai access for Google users
- FreeTier.php: credit check/deduct/reset engine with hourly rate limit
- bootstrap.php: dbnmDb() singleton, dbnToolsIsFreeTier(), credit gate helpers
- index.php: store tier=free|approved in session from SSO JWT
- All 7 API endpoints: credit gate (402/429) + X-Credits-Remaining header
- layout.php: credit meta tag, JS balance var, Syttende Mai banner (05-17 only)
- tools.js: credit badge in topbar, 402 modal, 429 toast, dbnUpdateCredits()
- barnevernet.js + deep-research.js: wire 402/429 handling for NDJSON streams
- tools.css: styles for credit badge, no-credits modal, rate-limit toast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 21:05:08 +02:00
daveadmin 08d1e3cee3 feat: auto-select STT engine (Azure → Google Cloud → Whisper) and show provider in results
Removes user-facing engine/model/key/beam controls. The server now picks
the best available engine automatically:
1. Microsoft Azure Speech — short clips (≤1MB, no diarization, audio/*)
2. Google Cloud Speech v2 — long audio, diarization, all languages
3. OpenAI Whisper GPU — local fallback

Results display which provider was used (e.g. "Transcribed with Google
Cloud Speech") via transcript-engine-badge and traceMeta.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 13:22:24 +02:00
daveadmin c6a9cc9199 feat: add site footer with privacy statement, CaveauAI attribution, and AI disclaimer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:24:49 +02:00
daveadmin 13572e9dfb feat: extract and display event times on timeline (kl. HH:MM etc.)
Prompt now instructs the model to extract time of day (HH:MM) when
present in Norwegian formats: kl. 14:30, kl 09.00, 14:30, 14.30.
renderTimeline shows time as a muted inline annotation next to the date.
CSV export gains a Time column after Date.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:03:20 +02:00
daveadmin a3d46f9756 feat: Legal Tools v1 — multilingual landing, dashboard, SSO bridge
- Public landing page at / for unauthenticated users (EN/NO/UK/PL)
- Authenticated / shows Case Workbench dashboard with manifesto strip,
  stats, and launched-tool grid (Transcribe, Timeline, BVJ, Advocate,
  Deep Research, Corpus)
- Added includes/i18n.php with full 4-language translation layer
- Extended layout.php to Case Workbench shell with tool rail, lang switcher
- AI output language normalization extended to en/no/uk/pl in PHP agents
- SSO token validation in bootstrap.php / index.php (dobetternorge.no bridge)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 22:53:27 +02:00
daveadmin 9b8cb9c6dc fix: raise file upload limit from 4 MB to 8 MB
PHP constant and all JS client-side guards updated. Server PHP ini is 64M.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 20:57:25 +02:00
daveadmin 43cf5b8ce4 feat: Barnevernet Analyzer — document analysis + partisan RAG brief
7-step agent pipeline: document classification, party extraction, timeline
extraction, corpus RAG (child_welfare/echr/family_core/bufdir_guidance),
and synthesis using the user's chosen engine (including dbn-legal-agent).
Progressive NDJSON streaming renders doc_meta, parties, and timeline cards
before the final advocacy brief and procedural red flags arrive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 20:49:46 +02:00
daveadmin 343b19d0b4 Add sub-question branching + document summary modals
- Source modal now shows LLM-generated document summary (lazy-gen + cached
  in documents.summary) instead of raw chunk text; toggle reveals matched
  chunk; "View all chunks" button fetches every chunk of the document via
  new api/document-chunks.php endpoint
- Each sub-question card gets a "Branch ↓" button that pre-fills the query
  with that sub-question and shows a context panel with the prior brief
  summary; prior_context + branch_notes are injected into interpretSeed()
  and synthesise() so the LLM knows where the research is coming from
- Upload document summaries generated at synthesis time and attached to
  upload sources alongside corpus summaries
- DB: documents.summary TEXT column added to bnl_corpus on chloe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 19:44:27 +02:00
daveadmin 7bccd8c010 Expand corpus slices to 8: split ECHR/Hague, add Norwegian Courts, Bufdir, DBN Resources
- Replace combined echr_hague slice with echr (Art.8+9, HUDOC, NIM) and hague (INCADAT,
  cross-border abduction) as separate toggles; echr defaults ON, hague defaults OFF
- Add norwegian_courts slice: Domstol (src 5,26) + Rettspraksis.no (src 33, 482 docs)
- Add bufdir_guidance slice: Barneombudet (19), Bufdir (20), Statsforvalteren (31)
- Add dbn_resources slice: DBN website pages (flashcards, resource directory), defaults OFF
- Replace isWebsiteChunk() with slice-aware shouldExcludeChunk(): always strips EU AI Act
  chunks (EUR-Lex source 7 leaks through when Qdrant runs unconstrained) and DBN website
  pages unless dbn_resources slice is explicitly ON
- Update SLICE_DEFS in advocate.js and deep-research.js to match all 8 slices
- Backward compat: echr_hague key in incoming requests fans out to echr+hague

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 16:01:05 +02:00
daveadmin 640778454f Add Case Advocate tab — partisan brief grounded in Norwegian law
New /advocate.php tab: user selects who they represent (biological
father, mother, foster carer, CWS, etc.) and the agent takes their
side entirely. Adversarial sub-questions target supporting Lovdata
statutes + ECHR precedents; synthesis returns client_strengths[] and
opposing_weaknesses[] alongside the advocate brief.

- DeepResearchAgent: add advocateRole param to run(), interpretSeed(),
  expandQueries(), synthesise(). Neutral path unchanged (empty string).
- api/deep-research.php: extract + validate advocate_role from payload;
  telemetry logs tool='advocate' vs 'deep_research'.
- advocate.php: new page with role dropdown (presets + custom), same
  corpus slices/engine/controls/upload zone as deep research.
- assets/js/advocate.js: page-scoped JS; renders advocate banner,
  client strengths card (teal), advocate brief, opposing weaknesses
  card (amber), sub-Q cards, sources, uncertainty, next step.
- assets/css/tools.css: append .adv-* rules (~120 lines).
- includes/layout.php: add Advocate nav tab between Deep research and
  Summarize.
- index.php: add Advocate cap-card tile.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:26:05 +02:00
daveadmin 38255669a9 Add corpus explorer: search bar (Hybrid/BM25/Vector), category drill-down, source row expand
- api/corpus-search.php: new endpoint with three search modes (hybrid RAG, BM25 keyword, Qdrant vector)
- api/corpus-documents.php: paginated document browser by category or source name
- corpus.php: search bar with mode+language pills, Browse docs button on each category card with drill-down panel, expand toggle on each source row showing doc count and scraper class
- tools.css: all new corpus interactive styles appended

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:55:54 +02:00
daveadmin d2f9831472 feat: Corpus Intelligence page + timeline background events
Adds /corpus.php — a data transparency page showing what powers the
legal tools: 9 coverage categories with live doc counts, a full
sources table pulled from the corpus DB, the AI stack (LLMs, Whisper,
Qdrant, Azure AI Search, embeddings, chunking), and a pipeline flow
diagram. Stats are live via a new /api/corpus-stats.php endpoint
(queries dobetter_rag + bnl_admin). The reasoning sidebar is repurposed
as a Corpus health panel on this page.

Also ships the in-progress timeline background events toggle:
API and UI wired together via include_background param.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 11:31:24 +02:00
daveadmin e130db8119 Deep Research v2: exclude marketing site, deep-link sources, per-agent reports
Three user-flagged issues after the first real run with a 920KB sakkyndig PDF:

1. dobetternorge.no marketing-website chunks leaked into the retrieval pool.
   ClientRagPipeline::searchAll defaults include_beta_website=true; we now
   pass false for both website flags, AND defensively drop any returned
   chunk whose source_name contains "website" or title contains
   "dobetternorge.no" before it can pollute synthesis.

2. Brief returned was "just a paragraph". Bumped synthesis max_tokens
   2200→3200, raised timeout 120→180s, and rewrote the prompt to require
   400-900 words with min 4 paragraphs when source_count>=3, covering EACH
   sub-question in its own paragraph. Now also passes authority + jurisdiction
   into the sources block so the model can pinpoint statutes correctly.

3. No way to see what each "sub-question agent" researched or click through
   to the source articles. Restructured the results panel so per-sub-question
   report cards now render ABOVE the synthesised brief. Each report shows the
   question, the rationale, and the top 3 retrieved sources for that sub-Q
   with title→deep link + 1-line excerpt. Brief follows. Consolidated
   numbered sources list at the bottom, with titles as deep links too.

Deep-link construction: source_url is hydrated via dbnV6QueryDocumentMeta
in a single batched call after retrieval. For Lovdata sources with a
section_title containing §<n>, the link is path-anchored to that section
(/§43). For other hosts (HUDOC, Regjeringen, Bufdir, etc.) we link to the
document root URL.

Telemetry: trace_metadata now carries retrieval_counts {raw_corpus,
filtered_website, post_filter_corpus, raw_upload, after_dedupe, after_topk}
so future regressions are diagnosable from the metadata.jsonl log alone.
The completion status pill surfaces the corpus/website/upload split.
2026-05-15 11:12:13 +02:00