From f877721b9037a1e94b1b11afac816aff2758c26d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste THERY Date: Mon, 29 Jun 2026 15:18:14 +0700 Subject: [PATCH 01/72] feat(product): add Mimir app and core hardening --- .github/workflows/ci.yml | 2 +- .github/workflows/npm-publish.yml | 6 +- .gitignore | 23 +- AGENTS.md | 55 +- CHANGELOG.md | 2 +- CLAUDE.md | 67 +- README.md | 57 +- RELEASING.md | 2 +- SECURITY-HARDENING.md | 2 +- biome.json | 2 +- docs/ux-dx-audit.md | 13 +- package.json | 6 +- packages/mimir-app/README.md | 17 + packages/mimir-app/index.html | 12 + packages/mimir-app/package.json | 38 + packages/mimir-app/src-tauri/Cargo.toml | 19 + packages/mimir-app/src-tauri/build.rs | 3 + .../src-tauri/capabilities/default.json | 7 + packages/mimir-app/src-tauri/src/lib.rs | 6 + packages/mimir-app/src-tauri/src/main.rs | 3 + packages/mimir-app/src-tauri/tauri.conf.json | 33 + packages/mimir-app/src/app.tsx | 162 + packages/mimir-app/src/main.tsx | 16 + packages/mimir-app/src/styles.css | 11 + packages/mimir-app/tsconfig.json | 16 + packages/mimir-app/vite.config.ts | 31 + packages/{mimir => mimir-core}/README.md | 2 + .../dist/access-log.d.ts | 0 .../dist/access-log.d.ts.map | 0 .../{mimir => mimir-core}/dist/access-log.js | 0 .../dist/access-log.js.map | 0 .../{mimir => mimir-core}/dist/chunking.d.ts | 0 .../dist/chunking.d.ts.map | 0 .../{mimir => mimir-core}/dist/chunking.js | 0 .../dist/chunking.js.map | 0 packages/{mimir => mimir-core}/dist/cli.d.ts | 0 .../{mimir => mimir-core}/dist/cli.d.ts.map | 0 packages/{mimir => mimir-core}/dist/cli.js | 39 +- packages/mimir-core/dist/cli.js.map | 1 + .../{mimir => mimir-core}/dist/config.d.ts | 0 .../dist/config.d.ts.map | 0 packages/{mimir => mimir-core}/dist/config.js | 0 .../{mimir => mimir-core}/dist/config.js.map | 0 .../{mimir => mimir-core}/dist/defaults.d.ts | 0 .../dist/defaults.d.ts.map | 0 .../{mimir => mimir-core}/dist/defaults.js | 4 +- .../dist/defaults.js.map | 0 .../{mimir => mimir-core}/dist/destroy.d.ts | 0 .../dist/destroy.d.ts.map | 0 .../{mimir => mimir-core}/dist/destroy.js | 0 .../{mimir => mimir-core}/dist/destroy.js.map | 0 .../{mimir => mimir-core}/dist/doctor.d.ts | 0 .../dist/doctor.d.ts.map | 2 +- packages/{mimir => mimir-core}/dist/doctor.js | 4 + packages/mimir-core/dist/doctor.js.map | 1 + .../dist/embeddings.d.ts | 5 + packages/mimir-core/dist/embeddings.d.ts.map | 1 + .../{mimir => mimir-core}/dist/embeddings.js | 17 + packages/mimir-core/dist/embeddings.js.map | 1 + .../{mimir => mimir-core}/dist/files.d.ts | 0 .../{mimir => mimir-core}/dist/files.d.ts.map | 0 packages/{mimir => mimir-core}/dist/files.js | 0 .../{mimir => mimir-core}/dist/files.js.map | 0 .../{mimir => mimir-core}/dist/gitignore.d.ts | 0 .../dist/gitignore.d.ts.map | 0 .../{mimir => mimir-core}/dist/gitignore.js | 0 .../dist/gitignore.js.map | 0 .../{mimir => mimir-core}/dist/index.d.ts | 1 + packages/mimir-core/dist/index.d.ts.map | 1 + packages/{mimir => mimir-core}/dist/index.js | 1 + packages/mimir-core/dist/index.js.map | 1 + .../{mimir => mimir-core}/dist/ingest.d.ts | 0 .../dist/ingest.d.ts.map | 2 +- packages/{mimir => mimir-core}/dist/ingest.js | 50 +- packages/mimir-core/dist/ingest.js.map | 1 + packages/{mimir => mimir-core}/dist/init.d.ts | 0 .../{mimir => mimir-core}/dist/init.d.ts.map | 0 packages/{mimir => mimir-core}/dist/init.js | 0 .../{mimir => mimir-core}/dist/init.js.map | 0 packages/{mimir => mimir-core}/dist/mcp.d.ts | 0 .../{mimir => mimir-core}/dist/mcp.d.ts.map | 0 packages/{mimir => mimir-core}/dist/mcp.js | 0 .../{mimir => mimir-core}/dist/mcp.js.map | 0 .../dist/package-manager.d.ts | 0 .../dist/package-manager.d.ts.map | 0 .../dist/package-manager.js | 0 .../dist/package-manager.js.map | 0 .../{mimir => mimir-core}/dist/parsing.d.ts | 0 .../dist/parsing.d.ts.map | 0 .../{mimir => mimir-core}/dist/parsing.js | 105 +- packages/mimir-core/dist/parsing.js.map | 1 + .../{mimir => mimir-core}/dist/query.d.ts | 0 packages/mimir-core/dist/query.d.ts.map | 1 + packages/mimir-core/dist/query.js | 185 + packages/mimir-core/dist/query.js.map | 1 + .../{mimir => mimir-core}/dist/redaction.d.ts | 0 .../dist/redaction.d.ts.map | 0 .../{mimir => mimir-core}/dist/redaction.js | 0 .../dist/redaction.js.map | 0 .../{mimir => mimir-core}/dist/security.d.ts | 0 .../dist/security.d.ts.map | 0 .../{mimir => mimir-core}/dist/security.js | 0 .../dist/security.js.map | 0 .../{mimir => mimir-core}/dist/setup.d.ts | 0 .../{mimir => mimir-core}/dist/setup.d.ts.map | 0 packages/{mimir => mimir-core}/dist/setup.js | 2 +- .../{mimir => mimir-core}/dist/setup.js.map | 2 +- .../{mimir => mimir-core}/dist/skill.d.ts | 0 .../{mimir => mimir-core}/dist/skill.d.ts.map | 0 packages/{mimir => mimir-core}/dist/skill.js | 0 .../{mimir => mimir-core}/dist/skill.js.map | 0 .../{mimir => mimir-core}/dist/store.d.ts | 1 + .../{mimir => mimir-core}/dist/store.d.ts.map | 2 +- packages/{mimir => mimir-core}/dist/store.js | 30 + packages/mimir-core/dist/store.js.map | 1 + .../{mimir => mimir-core}/dist/types.d.ts | 4 + packages/mimir-core/dist/types.d.ts.map | 1 + packages/{mimir => mimir-core}/dist/types.js | 0 .../{mimir => mimir-core}/dist/types.js.map | 0 .../{mimir => mimir-core}/dist/version.d.ts | 0 .../dist/version.d.ts.map | 0 .../{mimir => mimir-core}/dist/version.js | 0 .../{mimir => mimir-core}/dist/version.js.map | 0 .../examples/sovereign-rag-demo/.gitignore | 0 .../sovereign-rag-demo/.kb/config.json | 0 .../sovereign-rag-demo/.kb/sources.txt | 0 .../examples/sovereign-rag-demo/README.md | 2 +- .../raw/dataset-inventory.csv | 0 .../sovereign-rag-demo/raw/facility-scan.heic | 0 .../raw/incident-timeline.jsonl | 0 .../raw/operations-brief.md | 0 .../raw/review-notes.evidence | 0 .../raw/security-policy.yaml | 0 packages/{mimir => mimir-core}/package.json | 2 +- .../skills/mimir-audio-summary/SKILL.md | 0 .../skills/mimir-audio-summary/forge-voice.sh | 0 .../skills/mimir-audio-summary/split-lines.py | 0 .../skills/mimir-audio-summary/xtts-voice.py | 0 .../skills/mimir-markdown-report/SKILL.md | 0 .../skills/mimir/SKILL.md | 19 +- .../{mimir => mimir-core}/src/access-log.ts | 0 .../src/chunking.test.ts | 0 .../{mimir => mimir-core}/src/chunking.ts | 0 packages/{mimir => mimir-core}/src/cli.ts | 42 +- .../{mimir => mimir-core}/src/config.test.ts | 0 packages/{mimir => mimir-core}/src/config.ts | 0 .../{mimir => mimir-core}/src/defaults.ts | 4 +- packages/{mimir => mimir-core}/src/destroy.ts | 0 .../{mimir => mimir-core}/src/doctor.test.ts | 0 packages/{mimir => mimir-core}/src/doctor.ts | 7 + .../src/embeddings.test.ts | 0 .../{mimir => mimir-core}/src/embeddings.ts | 23 + .../{mimir => mimir-core}/src/files.test.ts | 0 packages/{mimir => mimir-core}/src/files.ts | 0 .../{mimir => mimir-core}/src/gitignore.ts | 0 packages/{mimir => mimir-core}/src/index.ts | 1 + .../{mimir => mimir-core}/src/ingest.test.ts | 20 + packages/{mimir => mimir-core}/src/ingest.ts | 61 +- packages/{mimir => mimir-core}/src/init.ts | 0 .../{mimir => mimir-core}/src/mcp.test.ts | 0 packages/{mimir => mimir-core}/src/mcp.ts | 0 .../src/package-manager.test.ts | 0 .../src/package-manager.ts | 0 .../{mimir => mimir-core}/src/parsing.test.ts | 11 +- packages/{mimir => mimir-core}/src/parsing.ts | 124 +- packages/mimir-core/src/query.test.ts | 76 + packages/mimir-core/src/query.ts | 239 ++ .../src/redaction.test.ts | 0 .../{mimir => mimir-core}/src/redaction.ts | 0 packages/mimir-core/src/security.test.ts | 58 + .../{mimir => mimir-core}/src/security.ts | 0 .../{mimir => mimir-core}/src/setup.test.ts | 0 packages/{mimir => mimir-core}/src/setup.ts | 2 +- .../{mimir => mimir-core}/src/skill.test.ts | 0 packages/{mimir => mimir-core}/src/skill.ts | 0 packages/mimir-core/src/store.test.ts | 50 + packages/mimir-core/src/store.ts | 77 + .../src/test-support/config.ts | 0 packages/{mimir => mimir-core}/src/types.ts | 4 + packages/{mimir => mimir-core}/src/version.ts | 0 packages/{mimir => mimir-core}/tsconfig.json | 0 packages/mimir-landing/README.md | 14 + packages/mimir-landing/astro.config.mjs | 19 + packages/mimir-landing/package.json | 33 + packages/mimir-landing/public/robots.txt | 2 + .../src/components/landing-hero.tsx | 128 + .../mimir-landing/src/layouts/layout.astro | 26 + packages/mimir-landing/src/pages/index.astro | 8 + packages/mimir-landing/src/styles/global.css | 12 + packages/mimir-landing/tsconfig.json | 12 + packages/mimir-ui/README.md | 15 + packages/mimir-ui/package.json | 48 + packages/mimir-ui/src/components/badge.tsx | 26 + packages/mimir-ui/src/components/button.tsx | 44 + packages/mimir-ui/src/components/card.tsx | 30 + packages/mimir-ui/src/components/input.tsx | 14 + packages/mimir-ui/src/components/progress.tsx | 25 + packages/mimir-ui/src/components/textarea.tsx | 14 + packages/mimir-ui/src/index.ts | 13 + packages/mimir-ui/src/lib/utils.ts | 6 + packages/mimir-ui/src/styles/globals.css | 101 + packages/mimir-ui/tsconfig.json | 18 + packages/mimir/dist/cli.js.map | 1 - packages/mimir/dist/doctor.js.map | 1 - packages/mimir/dist/embeddings.d.ts.map | 1 - packages/mimir/dist/embeddings.js.map | 1 - packages/mimir/dist/index.d.ts.map | 1 - packages/mimir/dist/index.js.map | 1 - packages/mimir/dist/ingest.js.map | 1 - packages/mimir/dist/parsing.js.map | 1 - packages/mimir/dist/query.d.ts.map | 1 - packages/mimir/dist/query.js | 64 - packages/mimir/dist/query.js.map | 1 - packages/mimir/dist/store.js.map | 1 - packages/mimir/dist/types.d.ts.map | 1 - packages/mimir/src/query.ts | 81 - packages/mimir/src/store.ts | 35 - pnpm-lock.yaml | 3543 ++++++++++++++++- pnpm-workspace.yaml | 1 + scripts/release-artifacts.mjs | 2 +- scripts/smoke.mjs | 2 +- 221 files changed, 5768 insertions(+), 483 deletions(-) create mode 100644 packages/mimir-app/README.md create mode 100644 packages/mimir-app/index.html create mode 100644 packages/mimir-app/package.json create mode 100644 packages/mimir-app/src-tauri/Cargo.toml create mode 100644 packages/mimir-app/src-tauri/build.rs create mode 100644 packages/mimir-app/src-tauri/capabilities/default.json create mode 100644 packages/mimir-app/src-tauri/src/lib.rs create mode 100644 packages/mimir-app/src-tauri/src/main.rs create mode 100644 packages/mimir-app/src-tauri/tauri.conf.json create mode 100644 packages/mimir-app/src/app.tsx create mode 100644 packages/mimir-app/src/main.tsx create mode 100644 packages/mimir-app/src/styles.css create mode 100644 packages/mimir-app/tsconfig.json create mode 100644 packages/mimir-app/vite.config.ts rename packages/{mimir => mimir-core}/README.md (93%) rename packages/{mimir => mimir-core}/dist/access-log.d.ts (100%) rename packages/{mimir => mimir-core}/dist/access-log.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/access-log.js (100%) rename packages/{mimir => mimir-core}/dist/access-log.js.map (100%) rename packages/{mimir => mimir-core}/dist/chunking.d.ts (100%) rename packages/{mimir => mimir-core}/dist/chunking.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/chunking.js (100%) rename packages/{mimir => mimir-core}/dist/chunking.js.map (100%) rename packages/{mimir => mimir-core}/dist/cli.d.ts (100%) rename packages/{mimir => mimir-core}/dist/cli.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/cli.js (91%) create mode 100644 packages/mimir-core/dist/cli.js.map rename packages/{mimir => mimir-core}/dist/config.d.ts (100%) rename packages/{mimir => mimir-core}/dist/config.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/config.js (100%) rename packages/{mimir => mimir-core}/dist/config.js.map (100%) rename packages/{mimir => mimir-core}/dist/defaults.d.ts (100%) rename packages/{mimir => mimir-core}/dist/defaults.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/defaults.js (96%) rename packages/{mimir => mimir-core}/dist/defaults.js.map (100%) rename packages/{mimir => mimir-core}/dist/destroy.d.ts (100%) rename packages/{mimir => mimir-core}/dist/destroy.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/destroy.js (100%) rename packages/{mimir => mimir-core}/dist/destroy.js.map (100%) rename packages/{mimir => mimir-core}/dist/doctor.d.ts (100%) rename packages/{mimir => mimir-core}/dist/doctor.d.ts.map (88%) rename packages/{mimir => mimir-core}/dist/doctor.js (94%) create mode 100644 packages/mimir-core/dist/doctor.js.map rename packages/{mimir => mimir-core}/dist/embeddings.d.ts (56%) create mode 100644 packages/mimir-core/dist/embeddings.d.ts.map rename packages/{mimir => mimir-core}/dist/embeddings.js (86%) create mode 100644 packages/mimir-core/dist/embeddings.js.map rename packages/{mimir => mimir-core}/dist/files.d.ts (100%) rename packages/{mimir => mimir-core}/dist/files.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/files.js (100%) rename packages/{mimir => mimir-core}/dist/files.js.map (100%) rename packages/{mimir => mimir-core}/dist/gitignore.d.ts (100%) rename packages/{mimir => mimir-core}/dist/gitignore.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/gitignore.js (100%) rename packages/{mimir => mimir-core}/dist/gitignore.js.map (100%) rename packages/{mimir => mimir-core}/dist/index.d.ts (95%) create mode 100644 packages/mimir-core/dist/index.d.ts.map rename packages/{mimir => mimir-core}/dist/index.js (92%) create mode 100644 packages/mimir-core/dist/index.js.map rename packages/{mimir => mimir-core}/dist/ingest.d.ts (100%) rename packages/{mimir => mimir-core}/dist/ingest.d.ts.map (62%) rename packages/{mimir => mimir-core}/dist/ingest.js (74%) create mode 100644 packages/mimir-core/dist/ingest.js.map rename packages/{mimir => mimir-core}/dist/init.d.ts (100%) rename packages/{mimir => mimir-core}/dist/init.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/init.js (100%) rename packages/{mimir => mimir-core}/dist/init.js.map (100%) rename packages/{mimir => mimir-core}/dist/mcp.d.ts (100%) rename packages/{mimir => mimir-core}/dist/mcp.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/mcp.js (100%) rename packages/{mimir => mimir-core}/dist/mcp.js.map (100%) rename packages/{mimir => mimir-core}/dist/package-manager.d.ts (100%) rename packages/{mimir => mimir-core}/dist/package-manager.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/package-manager.js (100%) rename packages/{mimir => mimir-core}/dist/package-manager.js.map (100%) rename packages/{mimir => mimir-core}/dist/parsing.d.ts (100%) rename packages/{mimir => mimir-core}/dist/parsing.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/parsing.js (65%) create mode 100644 packages/mimir-core/dist/parsing.js.map rename packages/{mimir => mimir-core}/dist/query.d.ts (100%) create mode 100644 packages/mimir-core/dist/query.d.ts.map create mode 100644 packages/mimir-core/dist/query.js create mode 100644 packages/mimir-core/dist/query.js.map rename packages/{mimir => mimir-core}/dist/redaction.d.ts (100%) rename packages/{mimir => mimir-core}/dist/redaction.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/redaction.js (100%) rename packages/{mimir => mimir-core}/dist/redaction.js.map (100%) rename packages/{mimir => mimir-core}/dist/security.d.ts (100%) rename packages/{mimir => mimir-core}/dist/security.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/security.js (100%) rename packages/{mimir => mimir-core}/dist/security.js.map (100%) rename packages/{mimir => mimir-core}/dist/setup.d.ts (100%) rename packages/{mimir => mimir-core}/dist/setup.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/setup.js (96%) rename packages/{mimir => mimir-core}/dist/setup.js.map (52%) rename packages/{mimir => mimir-core}/dist/skill.d.ts (100%) rename packages/{mimir => mimir-core}/dist/skill.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/skill.js (100%) rename packages/{mimir => mimir-core}/dist/skill.js.map (100%) rename packages/{mimir => mimir-core}/dist/store.d.ts (83%) rename packages/{mimir => mimir-core}/dist/store.d.ts.map (73%) rename packages/{mimir => mimir-core}/dist/store.js (51%) create mode 100644 packages/mimir-core/dist/store.js.map rename packages/{mimir => mimir-core}/dist/types.d.ts (97%) create mode 100644 packages/mimir-core/dist/types.d.ts.map rename packages/{mimir => mimir-core}/dist/types.js (100%) rename packages/{mimir => mimir-core}/dist/types.js.map (100%) rename packages/{mimir => mimir-core}/dist/version.d.ts (100%) rename packages/{mimir => mimir-core}/dist/version.d.ts.map (100%) rename packages/{mimir => mimir-core}/dist/version.js (100%) rename packages/{mimir => mimir-core}/dist/version.js.map (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/.gitignore (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/.kb/config.json (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/.kb/sources.txt (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/README.md (98%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/dataset-inventory.csv (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/facility-scan.heic (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/incident-timeline.jsonl (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/operations-brief.md (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/review-notes.evidence (100%) rename packages/{mimir => mimir-core}/examples/sovereign-rag-demo/raw/security-policy.yaml (100%) rename packages/{mimir => mimir-core}/package.json (97%) rename packages/{mimir => mimir-core}/skills/mimir-audio-summary/SKILL.md (100%) rename packages/{mimir => mimir-core}/skills/mimir-audio-summary/forge-voice.sh (100%) rename packages/{mimir => mimir-core}/skills/mimir-audio-summary/split-lines.py (100%) rename packages/{mimir => mimir-core}/skills/mimir-audio-summary/xtts-voice.py (100%) rename packages/{mimir => mimir-core}/skills/mimir-markdown-report/SKILL.md (100%) rename packages/{mimir => mimir-core}/skills/mimir/SKILL.md (92%) rename packages/{mimir => mimir-core}/src/access-log.ts (100%) rename packages/{mimir => mimir-core}/src/chunking.test.ts (100%) rename packages/{mimir => mimir-core}/src/chunking.ts (100%) rename packages/{mimir => mimir-core}/src/cli.ts (91%) rename packages/{mimir => mimir-core}/src/config.test.ts (100%) rename packages/{mimir => mimir-core}/src/config.ts (100%) rename packages/{mimir => mimir-core}/src/defaults.ts (97%) rename packages/{mimir => mimir-core}/src/destroy.ts (100%) rename packages/{mimir => mimir-core}/src/doctor.test.ts (100%) rename packages/{mimir => mimir-core}/src/doctor.ts (94%) rename packages/{mimir => mimir-core}/src/embeddings.test.ts (100%) rename packages/{mimir => mimir-core}/src/embeddings.ts (85%) rename packages/{mimir => mimir-core}/src/files.test.ts (100%) rename packages/{mimir => mimir-core}/src/files.ts (100%) rename packages/{mimir => mimir-core}/src/gitignore.ts (100%) rename packages/{mimir => mimir-core}/src/index.ts (95%) rename packages/{mimir => mimir-core}/src/ingest.test.ts (64%) rename packages/{mimir => mimir-core}/src/ingest.ts (74%) rename packages/{mimir => mimir-core}/src/init.ts (100%) rename packages/{mimir => mimir-core}/src/mcp.test.ts (100%) rename packages/{mimir => mimir-core}/src/mcp.ts (100%) rename packages/{mimir => mimir-core}/src/package-manager.test.ts (100%) rename packages/{mimir => mimir-core}/src/package-manager.ts (100%) rename packages/{mimir => mimir-core}/src/parsing.test.ts (80%) rename packages/{mimir => mimir-core}/src/parsing.ts (64%) create mode 100644 packages/mimir-core/src/query.test.ts create mode 100644 packages/mimir-core/src/query.ts rename packages/{mimir => mimir-core}/src/redaction.test.ts (100%) rename packages/{mimir => mimir-core}/src/redaction.ts (100%) create mode 100644 packages/mimir-core/src/security.test.ts rename packages/{mimir => mimir-core}/src/security.ts (100%) rename packages/{mimir => mimir-core}/src/setup.test.ts (100%) rename packages/{mimir => mimir-core}/src/setup.ts (97%) rename packages/{mimir => mimir-core}/src/skill.test.ts (100%) rename packages/{mimir => mimir-core}/src/skill.ts (100%) create mode 100644 packages/mimir-core/src/store.test.ts create mode 100644 packages/mimir-core/src/store.ts rename packages/{mimir => mimir-core}/src/test-support/config.ts (100%) rename packages/{mimir => mimir-core}/src/types.ts (97%) rename packages/{mimir => mimir-core}/src/version.ts (100%) rename packages/{mimir => mimir-core}/tsconfig.json (100%) create mode 100644 packages/mimir-landing/README.md create mode 100644 packages/mimir-landing/astro.config.mjs create mode 100644 packages/mimir-landing/package.json create mode 100644 packages/mimir-landing/public/robots.txt create mode 100644 packages/mimir-landing/src/components/landing-hero.tsx create mode 100644 packages/mimir-landing/src/layouts/layout.astro create mode 100644 packages/mimir-landing/src/pages/index.astro create mode 100644 packages/mimir-landing/src/styles/global.css create mode 100644 packages/mimir-landing/tsconfig.json create mode 100644 packages/mimir-ui/README.md create mode 100644 packages/mimir-ui/package.json create mode 100644 packages/mimir-ui/src/components/badge.tsx create mode 100644 packages/mimir-ui/src/components/button.tsx create mode 100644 packages/mimir-ui/src/components/card.tsx create mode 100644 packages/mimir-ui/src/components/input.tsx create mode 100644 packages/mimir-ui/src/components/progress.tsx create mode 100644 packages/mimir-ui/src/components/textarea.tsx create mode 100644 packages/mimir-ui/src/index.ts create mode 100644 packages/mimir-ui/src/lib/utils.ts create mode 100644 packages/mimir-ui/src/styles/globals.css create mode 100644 packages/mimir-ui/tsconfig.json delete mode 100644 packages/mimir/dist/cli.js.map delete mode 100644 packages/mimir/dist/doctor.js.map delete mode 100644 packages/mimir/dist/embeddings.d.ts.map delete mode 100644 packages/mimir/dist/embeddings.js.map delete mode 100644 packages/mimir/dist/index.d.ts.map delete mode 100644 packages/mimir/dist/index.js.map delete mode 100644 packages/mimir/dist/ingest.js.map delete mode 100644 packages/mimir/dist/parsing.js.map delete mode 100644 packages/mimir/dist/query.d.ts.map delete mode 100644 packages/mimir/dist/query.js delete mode 100644 packages/mimir/dist/query.js.map delete mode 100644 packages/mimir/dist/store.js.map delete mode 100644 packages/mimir/dist/types.d.ts.map delete mode 100644 packages/mimir/src/query.ts delete mode 100644 packages/mimir/src/store.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e15a27b..4c2965f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: run: pnpm smoke - name: Verify generated dist is committed - run: git diff --exit-code -- packages/mimir/dist packages/mimir-tts/dist + run: git diff --exit-code -- packages/mimir-core/dist packages/mimir-tts/dist - name: Verify npm package metadata run: pnpm package:check diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 87947b2..19bc2e3 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -47,7 +47,7 @@ jobs: - name: Verify version input run: | - test "$(node -p "require('./packages/mimir/package.json').version")" = "${{ inputs.version }}" + test "$(node -p "require('./packages/mimir-core/package.json').version")" = "${{ inputs.version }}" test "$(node -p "require('./packages/mimir-tts/package.json').version")" = "${{ inputs.version }}" - name: Install dependencies @@ -69,7 +69,7 @@ jobs: run: pnpm smoke - name: Verify generated dist is committed - run: git diff --exit-code -- packages/mimir/dist packages/mimir-tts/dist + run: git diff --exit-code -- packages/mimir-core/dist packages/mimir-tts/dist - name: Verify npm package metadata run: pnpm package:check @@ -89,6 +89,6 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish Mimir - run: pnpm --dir packages/mimir publish --access public --provenance --no-git-checks + run: pnpm --dir packages/mimir-core publish --access public --provenance --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 81d3077..3def448 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,20 @@ private/** .mimir/ *.tgz release-artifacts/ +*.pid + +packages/mimir-app/dist/ +packages/mimir-app/src-tauri/target/ +packages/mimir-app/src-tauri/gen/ +packages/mimir-landing/.astro/ +packages/mimir-landing/dist/ # Tracked synthetic examples. Keep generated example runtime state ignored. -!packages/mimir/examples/ -!packages/mimir/examples/**/ -!packages/mimir/examples/**/.kb/ -!packages/mimir/examples/**/.kb/config.json -!packages/mimir/examples/**/.kb/sources.txt -packages/mimir/examples/**/.kb/storage/ -packages/mimir/examples/**/.kb/access.log -packages/mimir/examples/**/.mimir/ +!packages/mimir-core/examples/ +!packages/mimir-core/examples/**/ +!packages/mimir-core/examples/**/.kb/ +!packages/mimir-core/examples/**/.kb/config.json +!packages/mimir-core/examples/**/.kb/sources.txt +packages/mimir-core/examples/**/.kb/storage/ +packages/mimir-core/examples/**/.kb/access.log +packages/mimir-core/examples/**/.mimir/ diff --git a/AGENTS.md b/AGENTS.md index 760a4e2..d179f3d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,16 @@ - Keep product documentation canonical in the root `README.md`. Package README files under `packages/*/README.md` are intentionally minimal npm entrypoints and must link clearly to the GitHub root README because npm displays package README files separately. +- Keep user-facing titles and marketing surfaces branded as `Mimir`. Use `Mimir Core` only for the + technical core package and developer-facing metadata. +- `packages/mimir-ui` is the shared UI/style foundation adapted from the WorkoutGen landing/UI + approach. It provides the common Tailwind theme and React primitives for both the landing and the + Tauri app; do not import WorkoutGen product copy, assets, analytics, or secrets. +- `packages/mimir-landing` is the Astro static landing package. It must stay telemetry-free by + default; do not add PostHog. If analytics are needed later, prefer Cloudflare Web Analytics. +- `packages/mimir-app` is the cross-platform Tauri desktop/mobile shell. Root `pnpm build` validates + the frontend bundle only; native `tauri build`, `tauri ios *`, and `tauri android *` commands stay + explicit and are not part of npm release validation. - Keep optional audio summaries separate from core ingestion/query behavior. The `mimir-audio-summary` skill must prefer `kb audio` / `@jcode.labs/mimir-tts`, default to the Transformers.js WAV path for offline/confidential rendering, use the Edge MP3 path for global @@ -45,7 +55,7 @@ - Keep Mimir core free of Ollama. `embeddingProvider: "local-hash"` supports ingestion, search, MCP, and cited retrieval without a model server, but it must not be described as equivalent to semantic retrieval. `embeddingProvider: "transformers"` is the optional semantic embedding path. -- Keep `packages/mimir/examples/sovereign-rag-demo` synthetic and safe to commit. It exists for +- Keep `packages/mimir-core/examples/sovereign-rag-demo` synthetic and safe to commit. It exists for package/user testing only; never place real confidential documents there. - Use Context7 before changing dependencies or public APIs that rely on external libraries. - Run `pnpm validate` before opening a release pull request or publishing. It covers @@ -54,6 +64,8 @@ - Do not publish from a local machine or direct push to `main`. npm releases must go through the protected manual `Publish npm` GitHub Actions workflow after `main` has green CI. The workflow publishes `@jcode.labs/mimir-tts` first, then `@jcode.labs/mimir`. +- Use Git Flow locally: `main` is production, `develop` is integration, feature work starts from + `develop` under `feature/*`. Do not deploy or publish from feature branches. ## Coding Conventions @@ -68,7 +80,7 @@ General principles (KISS, DRY, YAGNI, SOLID) as applied in this codebase. Match - No dead or obsolete code. Delete replaced code, unused exports, and commented-out blocks in the same change; a deletion must cover both source and the regenerated package `dist/`. - No magic strings or numbers. Name meaningful literals as constants, and put shared paths, provider - defaults, and ignore constants in `packages/mimir/src/defaults.ts` rather than copying them across + defaults, and ignore constants in `packages/mimir-core/src/defaults.ts` rather than copying them across modules. - Validate at the boundary, narrow inside. Use Zod at external edges (config in `config.ts`, MCP inputs in `mcp.ts`) and CLI parsers (`parsePositiveInt`); trust the types past that point. @@ -82,28 +94,33 @@ General principles (KISS, DRY, YAGNI, SOLID) as applied in this codebase. Match ## Architecture -- `packages/mimir` is the core package published as `@jcode.labs/mimir`. -- `packages/mimir/src/cli.ts` exposes the `kb` CLI. -- `packages/mimir/src/doctor.ts` owns the user-facing readiness diagnosis behind `kb doctor`. -- `packages/mimir/src/config.ts` resolves `.kb/config.json` from the target repository. -- `packages/mimir/src/defaults.ts` owns shared default paths, provider defaults, and generated-state ignore +- `packages/mimir-core` is Mimir Core, published as `@jcode.labs/mimir`. +- `packages/mimir-core/src/cli.ts` exposes the `kb` CLI. +- `packages/mimir-core/src/doctor.ts` owns the user-facing readiness diagnosis behind `kb doctor`. +- `packages/mimir-core/src/config.ts` resolves `.kb/config.json` from the target repository. +- `packages/mimir-core/src/defaults.ts` owns shared default paths, provider defaults, and generated-state ignore constants. Keep config/init/security/gitignore aligned through this module instead of copying literals. -- `packages/mimir/src/ingest.ts` parses supported files, chunks text, embeds chunks, and rebuilds the - local LanceDB table. -- `packages/mimir/src/query.ts` performs vector search and returns cited retrieval context; LLM synthesis belongs - outside Mimir core. -- `packages/mimir/src/mcp.ts` exposes Mimir as an MCP stdio server for agents. +- `packages/mimir-core/src/ingest.ts` parses supported files, chunks text, embeds chunks, and rebuilds the + local LanceDB table. Normal ingest is incremental and reuses rows whose checksum/provider/model + still match; `--rebuild` forces a full re-index. +- `packages/mimir-core/src/query.ts` performs hybrid retrieval (vector candidates plus bounded lexical + BM25 scoring) and returns cited retrieval context; LLM synthesis belongs outside Mimir core. +- `packages/mimir-core/src/mcp.ts` exposes Mimir as an MCP stdio server for agents. - `packages/mimir-tts` is the standalone TTS package used by `kb audio`; it uses `edge-tts` for high-quality MP3 when available and Transformers.js for offline WAV rendering. -- `packages/mimir/src/gitignore.ts` owns target-repository `.gitignore` entries for local generated Mimir +- `packages/mimir-ui` owns shared React UI primitives and Tailwind theme tokens used by Mimir + product surfaces. +- `packages/mimir-landing` owns the static Astro landing page. +- `packages/mimir-app` owns the Tauri app shell for desktop and mobile. +- `packages/mimir-core/src/gitignore.ts` owns target-repository `.gitignore` entries for local generated Mimir state. -- `packages/mimir/src/security.ts`, `packages/mimir/src/redaction.ts`, and - `packages/mimir/src/access-log.ts` own the +- `packages/mimir-core/src/security.ts`, `packages/mimir-core/src/redaction.ts`, and + `packages/mimir-core/src/access-log.ts` own the privacy and confidentiality hardening layer. -- `packages/mimir/skills/mimir/SKILL.md` is the bundled portable agent skill. -- `packages/mimir/skills/mimir-audio-summary/SKILL.md` is the optional bundled audio-summary skill. -- `packages/mimir/skills/mimir-markdown-report/SKILL.md` is the optional bundled Markdown-report +- `packages/mimir-core/skills/mimir/SKILL.md` is the bundled portable agent skill. +- `packages/mimir-core/skills/mimir-audio-summary/SKILL.md` is the optional bundled audio-summary skill. +- `packages/mimir-core/skills/mimir-markdown-report/SKILL.md` is the optional bundled Markdown-report skill. - `kb setup` must keep generating agent-specific MCP helpers for easy local use: `.mimir/claude-mcp-server.json` for `claude mcp add-json`, `.mimir/codex-mcp.toml` for Codex @@ -115,7 +132,7 @@ General principles (KISS, DRY, YAGNI, SOLID) as applied in this codebase. Match - Keep `.mimir/skills/` as the canonical skill source in target repositories. Native agent folders created by `kb install-agent` should link to that source by default; use copy mode only as a compatibility fallback for runtimes or filesystems that cannot follow symlinks. -- `packages/mimir/examples/sovereign-rag-demo` is the tracked synthetic test workspace for manual +- `packages/mimir-core/examples/sovereign-rag-demo` is the tracked synthetic test workspace for manual and package validation. - `.kb/`, `.mimir/`, and project `private/` folders are local user data or generated agent state in target repositories and must not be committed. diff --git a/CHANGELOG.md b/CHANGELOG.md index eb5b333..32452c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,7 @@ - Add optional Transformers.js semantic embeddings through `embeddingProvider: "transformers"`. - Remove Ollama providers and keep `embeddingProvider: "local-hash"` as the no-model default. - Move the repository to a simple pnpm workspace monorepo without adding Turbo. -- Move the core `@jcode.labs/mimir` package into `packages/mimir`. +- Move the core `@jcode.labs/mimir` package into `packages/mimir-core`. - Add `@jcode.labs/mimir-tts` for plug-and-play JS/ONNX WAV rendering without Python or ffmpeg. - Add `kb audio` and update the audio-summary skill to use Mimir TTS before advanced fallback engines. diff --git a/CLAUDE.md b/CLAUDE.md index be50e5d..4353001 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,12 +9,14 @@ non-obvious traps that matter when editing here, without duplicating `AGENTS.md` ## Commands ```bash -pnpm build # builds packages/mimir-tts, then packages/mimir; package dist is committed -pnpm check # typecheck only (tsc --noEmit) +pnpm build # builds UI, app frontend, landing, TTS, then Mimir Core +pnpm check # typecheck UI/app/landing/TTS/core +pnpm dev:app # run the Vite frontend for the Tauri shell +pnpm dev:landing # run the Astro landing locally pnpm lint # Biome CI (format + lint check, no writes) pnpm lint:fix # Biome auto-fix pnpm format # Biome format --write -pnpm test # vitest run for packages/mimir-tts, then packages/mimir +pnpm test # vitest run for packages/mimir-tts, then packages/mimir-core pnpm smoke # build production CLI + MCP smoke test (scripts/smoke.mjs) pnpm validate # full release gate: lint + check + test + build + smoke + package:check + release:artifacts ``` @@ -27,18 +29,23 @@ Tests are colocated as `packages/*/src/*.test.ts` and run on the TypeScript sour ## Committed `dist/` — critical -`packages/mimir/dist/` and `packages/mimir-tts/dist/` are checked into Git. CI enforces -`git diff --exit-code -- packages/mimir/dist packages/mimir-tts/dist`. After any change under -`packages/mimir/src/` or `packages/mimir-tts/src/`, run `pnpm build` and commit the regenerated +`packages/mimir-core/dist/` and `packages/mimir-tts/dist/` are checked into Git. CI enforces +`git diff --exit-code -- packages/mimir-core/dist packages/mimir-tts/dist`. After any change under +`packages/mimir-core/src/` or `packages/mimir-tts/src/`, run `pnpm build` and commit the regenerated output in the same commit, or CI fails. This is the single easiest mistake to make in this repo. +`packages/mimir-app/dist/` and `packages/mimir-landing/dist/` are build artifacts and stay ignored. ## Naming map (the package has several names on purpose) -- Product / core package: **Mimir**, published as `@jcode.labs/mimir` from `packages/mimir`. +- Product name: **Mimir** on the landing, app, README title, and user-facing copy. +- Core package: **Mimir Core**, published as `@jcode.labs/mimir` from `packages/mimir-core`. - TTS package: **Mimir TTS**, published as `@jcode.labs/mimir-tts`. -- CLI binary: **`kb`** (`packages/mimir/bin.kb` -> `packages/mimir/dist/cli.js`). Commands: `init`, - `ingest`, `search`, `ask`, `audit`, `status`, `security-audit`, `destroy-index`, `audio`, - `doctor`, `serve-mcp`, `skill-path`, `install-skill`. +- UI package: **Mimir UI**, private workspace package `@jcode.labs/mimir-ui`. +- Landing package: private workspace package `@jcode.labs/mimir-landing`. +- App package: private workspace package `@jcode.labs/mimir-app`. +- CLI binary: **`kb`** (`packages/mimir-core/bin.kb` -> `packages/mimir-core/dist/cli.js`). Commands: `init`, + `ingest`, `models pull`, `search`, `ask`, `audit`, `status`, `security-audit`, `destroy-index`, + `audio`, `doctor`, `serve-mcp`, `skill-path`, `install-skill`. - TTS CLI binary: **`mimir-tts`** (`packages/mimir-tts/dist/cli.js`). Commands: `doctor`, `render`. - Project config/state in the target repo: **`.kb/`** (`config.json`, `sources.txt`, `access.log`, `storage/`), raw documents in **`private/`**, agent kit in **`.mimir/`**. @@ -48,25 +55,35 @@ output in the same commit, or CI fails. This is the single easiest mistake to ma ## Architecture and data flow -This is a pnpm workspace monorepo with the core package in `packages/mimir` and TTS in -`packages/mimir-tts`. Do not add Turbo unless `pnpm --filter` stops being enough. +This is a pnpm workspace monorepo. `packages/mimir-core` and `packages/mimir-tts` are the published +npm packages. `packages/mimir-ui`, `packages/mimir-landing`, and `packages/mimir-app` are private +workspace packages for product surfaces. Do not add Turbo unless `pnpm --filter` stops being enough. +`@jcode.labs/mimir` depends on `@jcode.labs/mimir-tts` (`workspace:*`), so release builds still keep +TTS and core in sync. The core package is an ESM-only TypeScript library + CLI + MCP server. Same core, three entry -points: `packages/mimir/src/cli.ts` (commander), `packages/mimir/src/index.ts` (public library -exports), `packages/mimir/src/mcp.ts` (stdio MCP server). +points: `packages/mimir-core/src/cli.ts` (commander), `packages/mimir-core/src/index.ts` (public library +exports), `packages/mimir-core/src/mcp.ts` (stdio MCP server). -The ingest pipeline (`packages/mimir/src/ingest.ts`) chains single-responsibility modules: +The ingest pipeline (`packages/mimir-core/src/ingest.ts`) chains single-responsibility modules: `files.ts` (discover supported files via fast-glob, with sha256 checksums) → `parsing.ts` (extract text per format: PDF/Office/HTML/etc.) → `redaction.ts` (strip secrets/PII *before* anything is embedded) → `chunking.ts` (split into overlapping chunks) → -`embeddings.ts` (vectorize) → `store.ts` (LanceDB). `query.ts` embeds the query and runs vector -search; `ask` returns cited passages only (no LLM synthesis in core). +`embeddings.ts` (vectorize) → `store.ts` (LanceDB). `query.ts` embeds the query, combines vector +candidates with bounded lexical BM25 scoring, and `ask` returns cited passages only (no LLM +synthesis in core). `packages/mimir-tts` is a separate ESM package. It defaults to Transformers.js for offline WAV rendering without Python or ffmpeg, and uses `edge-tts` for high-quality MP3 only when explicitly requested. Core `kb audio` imports it dynamically. +`packages/mimir-ui` is the shared Tailwind 4 + React UI layer adapted from the WorkoutGen UI/landing +foundation, but with Mimir tokens and no WorkoutGen product copy, analytics, CDN paths, or secrets. +`packages/mimir-landing` is an Astro static site using that UI package. `packages/mimir-app` is a +Tauri v2 shell using the same UI package; root build validates its Vite frontend, while native Tauri +desktop/mobile builds are explicit `pnpm --filter @jcode.labs/mimir-app tauri:*` commands. + Key behaviors to keep in mind before editing: - **Config resolution is caller-relative.** `loadConfig` walks up from `cwd` looking for @@ -74,11 +91,12 @@ Key behaviors to keep in mind before editing: working directory, never from its own install path. Zod validates config; `KB_*` env vars override. - **Two embedding providers, not interchangeable at runtime.** `local-hash` (default) is a 384-dim sha256 lexical embedding — fully offline, no model, *not semantic*. `transformers` lazily - `import()`s `@huggingface/transformers` with `allowRemoteModels` off by default. The two produce - different vectors, so **switching providers requires a full re-ingest**. -- **Ingest always full-rebuilds** the LanceDB table (`mode: "overwrite"`). The `--rebuild` flag is a - no-op kept for compatibility. There is no incremental indexing; `audit` only *reports* missing/stale - files against the current index. + `import()`s `@huggingface/transformers` with `allowRemoteModels` off by default. `kb models pull` + is the explicit one-time remote-download path for preloading the configured embedding model. The + two providers produce different vectors, so **switching providers requires `kb ingest --rebuild`**. +- **Ingest is incremental by default.** It reuses rows whose checksum, embedding provider, and model + still match, then overwrites the LanceDB table with reused + rebuilt rows. Use `--rebuild` to force + every supported file through parsing, redaction, chunking, and embedding again. - **Privacy is a feature, not a side effect.** Redaction runs before embedding, the access log stores query hashes/metadata only (`access-log.ts`), MCP top-K is clamped to `mcpMaxTopK`, and `gitignore.ts` keeps `.kb/`, `.mimir/`, `private/**` ignored in target repos. `security-audit` @@ -88,8 +106,9 @@ Coding conventions (KISS, DRY, YAGNI, SOLID as applied here) live in `AGENTS.md` ## Toolchain constraints -- Strict TypeScript with `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes`; module mode is - `NodeNext`, so relative imports use `.js` extensions even from `.ts` sources. +- Strict TypeScript (`tsconfig.base.json`) with `noUncheckedIndexedAccess`, + `exactOptionalPropertyTypes`, `noUnusedLocals`, and `noUnusedParameters`; module mode is `NodeNext`, + so relative imports use `.js` extensions even from `.ts` sources. - Biome is the formatter and linter (not ESLint/Prettier): 2-space indent, width 100, double quotes, semicolons as-needed, trailing commas all. - Conventional Commits are enforced by commitlint in CI. diff --git a/README.md b/README.md index 4149662..dc59299 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,16 @@ This root README is the canonical product documentation for the public npm packa | --- | --- | | `@jcode.labs/mimir` | Mimir Core: CLI, library, MCP server, bundled agent skills, and synthetic examples. | | `@jcode.labs/mimir-tts` | Mimir add-on for Edge-quality MP3 and offline Transformers.js WAV rendering through `kb audio`. | +| `@jcode.labs/mimir-ui` | Private workspace UI package adapted from the WorkoutGen design foundation for Mimir surfaces. | +| `@jcode.labs/mimir-landing` | Private Astro static landing package. Product-facing titles stay `Mimir`. | +| `@jcode.labs/mimir-app` | Private Tauri desktop/mobile shell package. Native builds are explicit app commands. | The package README files are intentionally short because npm displays each package README separately. They point npm readers back to this GitHub documentation. +The product name visible to users is **Mimir**. The technical core package is **Mimir Core** and now +lives under `packages/mimir-core`; the public npm package name remains `@jcode.labs/mimir`. + ## Open Source Mimir is a public open-source project under the MIT License. It is designed to be inspectable, @@ -96,7 +102,8 @@ context. - A repository where generated local folders can be ignored by Git. - No model runtime is required for the default `embeddingProvider: "local-hash"` mode. - Optional semantic embeddings use Transformers.js with local model files under `.mimir/models` by - default. + default. Use `kb models pull` when remote model download is acceptable, then keep + `transformersAllowRemoteModels` false for confidential indexing. - Generated answers are intentionally outside Mimir core. Use Claude, Codex, OpenAI, a local model MCP server, or another trusted model runtime to synthesize from Mimir's cited context. - Optional audio summaries use `@jcode.labs/mimir-tts`. For highest-quality MP3, install the @@ -280,13 +287,15 @@ Use this when you want better semantic retrieval while keeping Mimir core free o Commands: ```bash +pnpm exec kb models pull pnpm exec kb ingest pnpm exec kb ask "Which passages support offline operation?" ``` -Keep `transformersAllowRemoteModels` false for confidential or air-gapped work and preload model -files into `embeddingModelPath`. Set it to true only when you explicitly allow Transformers.js to -download model files from Hugging Face. +`kb models pull` intentionally allows a one-time download from Hugging Face into +`embeddingModelPath`. Keep `transformersAllowRemoteModels` false for confidential or air-gapped +indexing after the model files are present. Re-run `kb ingest --rebuild` after changing embedding +provider or model so stored vectors match the active configuration. ## Agent Skills And MCP @@ -620,9 +629,9 @@ Default `.kb/config.json`: }, "accessLog": true, "mcpMaxTopK": 10, - "topK": 5, + "topK": 8, "chunkSize": 1200, - "chunkOverlap": 150, + "chunkOverlap": 200, "maxFileBytes": 50000000, "ingestConcurrency": 4, "embeddingBatchSize": 32, @@ -666,8 +675,10 @@ Mimir ships two CLIs: | `kb setup` | Initialize Mimir, install the agent kit, run doctor, and ingest when safe. | | `kb init` | Create `.kb/config.json`, `.kb/sources.txt`, `private/`, and Git ignore rules. | | `kb doctor` | Diagnose setup, index freshness, security warnings, and the next command to run. | -| `kb doctor --fix` | Create missing scaffolding, install skills/MCP config, and rebuild stale indexes when safe. | -| `kb ingest` | Parse source files, redact, chunk, embed, and rebuild the local LanceDB index. | +| `kb doctor --fix` | Create missing scaffolding, install skills/MCP config, and update stale indexes when safe. | +| `kb models pull` | Download the configured Transformers.js embedding model into `embeddingModelPath`. | +| `kb ingest` | Parse changed source files, redact, chunk, embed, and update the local LanceDB index. | +| `kb ingest --rebuild` | Force a full re-index, required after switching embedding provider or model. | | `kb audit` | Check whether supported source files are missing from or stale in the index. | | `kb audit --unsupported` | List files skipped because they are unsupported, too large, or secret-like. | | `kb search ""` | Retrieve ranked passages without asking an LLM to write an answer. | @@ -787,10 +798,16 @@ working offline: } ``` +When remote download is acceptable, preload the configured embedding model first: + +```bash +pnpm exec kb models pull +``` + Switching providers requires a full re-ingest: ```bash -pnpm exec kb ingest +pnpm exec kb ingest --rebuild pnpm exec kb doctor ``` @@ -803,14 +820,15 @@ pnpm exec kb ingest pnpm exec kb audit ``` -Or let doctor perform the safe rebuild: +Or let doctor perform the safe incremental update: ```bash pnpm exec kb doctor --fix ``` -Mimir rebuilds the index on each ingest. The `--rebuild` flag is accepted for compatibility, but -ingest already rebuilds. +Mimir incrementally reuses unchanged indexed rows on normal `kb ingest`. Use `kb ingest --rebuild` +after switching embedding provider/model, after changing chunking settings, or when you want to +discard and recreate the whole local index. ### `security-audit --strict` Fails @@ -895,7 +913,7 @@ choose `local-hash`, while preserving richer parsing, MCP support, and optional ## Example Test Workspace This repository includes a synthetic example under -[`packages/mimir/examples/sovereign-rag-demo`](./packages/mimir/examples/sovereign-rag-demo). It can +[`packages/mimir-core/examples/sovereign-rag-demo`](./packages/mimir-core/examples/sovereign-rag-demo). It can be used to test ingestion, retrieval, `security-audit`, and custom text extensions without using private documents. @@ -903,7 +921,7 @@ From a local checkout: ```bash pnpm build -cd packages/mimir/examples/sovereign-rag-demo +cd packages/mimir-core/examples/sovereign-rag-demo node ../../dist/cli.js security-audit node ../../dist/cli.js ingest node ../../dist/cli.js search "offline retrieval approval" @@ -927,12 +945,15 @@ Useful filtered commands: ```bash pnpm --filter @jcode.labs/mimir test pnpm --filter @jcode.labs/mimir-tts test +pnpm --filter @jcode.labs/mimir-app build +pnpm --filter @jcode.labs/mimir-landing build pnpm --filter @jcode.labs/mimir build pnpm --filter @jcode.labs/mimir-tts build ``` -`packages/mimir/dist/` and `packages/mimir-tts/dist/` are committed. After changing TypeScript -sources, run: +`packages/mimir-core/dist/` and `packages/mimir-tts/dist/` are committed. `packages/mimir-app/dist/` +and `packages/mimir-landing/dist/` are ignored build artifacts. After changing TypeScript sources in +published packages, run: ```bash pnpm build @@ -957,14 +978,14 @@ pnpm build Use a local checkout in another repository: ```bash -pnpm add -D file:../jcode-mimir/packages/mimir +pnpm add -D file:../jcode-mimir/packages/mimir-core ``` Create a local npm tarball: ```bash pnpm build -pnpm --dir packages/mimir pack +pnpm --dir packages/mimir-core pack ``` ## Supporting Documents diff --git a/RELEASING.md b/RELEASING.md index 0616e7b..2dafce8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -11,7 +11,7 @@ and approved by Jean-Baptiste Thery through the protected `npm-publish` environm 2. Wait for the required CI checks to pass. 3. Merge only after approval and green checks. 4. Trigger the `Publish npm` workflow manually from `main`. -5. Enter the version already committed in `packages/mimir/package.json` and +5. Enter the version already committed in `packages/mimir-core/package.json` and `packages/mimir-tts/package.json`. 6. Approve the protected `npm-publish` environment when GitHub asks for review. diff --git a/SECURITY-HARDENING.md b/SECURITY-HARDENING.md index 58f15b7..73057e7 100644 --- a/SECURITY-HARDENING.md +++ b/SECURITY-HARDENING.md @@ -212,7 +212,7 @@ workspace packages with provenance: ```bash pnpm --dir packages/mimir-tts publish --access public --provenance --no-git-checks -pnpm --dir packages/mimir publish --access public --provenance --no-git-checks +pnpm --dir packages/mimir-core publish --access public --provenance --no-git-checks ``` Release artifacts include: diff --git a/biome.json b/biome.json index 749fded..8f0b485 100644 --- a/biome.json +++ b/biome.json @@ -6,7 +6,7 @@ "useIgnoreFile": true }, "files": { - "includes": ["*.cjs", "*.json", "scripts/**/*.mjs", "packages/*/src/**/*.ts"] + "includes": ["*.cjs", "*.json", "scripts/**/*.mjs", "packages/*/src/**/*.{ts,tsx}"] }, "formatter": { "enabled": true, diff --git a/docs/ux-dx-audit.md b/docs/ux-dx-audit.md index 9b134c7..0270bd6 100644 --- a/docs/ux-dx-audit.md +++ b/docs/ux-dx-audit.md @@ -6,10 +6,10 @@ developer and agent workflow around installation, indexing, querying, safety, au ## Evidence Reviewed - Root product README: `README.md` -- npm package entrypoint READMEs: `packages/mimir/README.md`, `packages/mimir-tts/README.md` -- CLI implementation: `packages/mimir/src/cli.ts` +- npm package entrypoint READMEs: `packages/mimir-core/README.md`, `packages/mimir-tts/README.md` +- CLI implementation: `packages/mimir-core/src/cli.ts` - TTS implementation: `packages/mimir-tts/src/index.ts` -- Agent skills: `packages/mimir/skills/**/SKILL.md` +- Agent skills: `packages/mimir-core/skills/**/SKILL.md` - Security docs: `SECURITY-HARDENING.md`, `SECURITY.md` - Release workflow: `.github/workflows/ci.yml`, `.github/workflows/npm-publish.yml` - Runtime smoke path through a temporary repository @@ -27,6 +27,7 @@ developer and agent workflow around installation, indexing, querying, safety, au | Ingestion visibility | Unsupported files were ignored silently, which made users overestimate coverage. | Fixed: `ingest`, `audit`, and `audit --unsupported` report skipped files by reason. | | Report generation | Users had audio summaries but no dedicated Markdown-report workflow. | Fixed: `mimir-markdown-report` skill writes cited reports under ignored local state. | | Stale detection | Audit compared paths but did not detect changed file content. | Fixed: audit now uses stored checksums to flag stale indexed content. | +| Semantic model preload | Users had to infer how to warm the Transformers.js cache. | Fixed: `kb models pull` downloads the configured embedding model into `embeddingModelPath`. | ## DX Findings @@ -43,8 +44,8 @@ developer and agent workflow around installation, indexing, querying, safety, au - `local-hash` is intentionally low-friction but not semantic. The docs must continue to say this clearly so users do not overtrust retrieval quality. -- Transformers.js offline TTS still depends on preloaded model files. The install path is easy, but - fully air-gapped operation requires a documented model-preload workflow. +- Transformers.js offline TTS still depends on preloaded model files. Embedding preload now has + `kb models pull`, but fully air-gapped TTS still needs a dedicated preload workflow. - MCP access is read-focused but still exposes private retrieved passages to the connected agent. Team/RBAC support remains out of scope. - `audit --unsupported` intentionally lists relative paths only; users still need to avoid pasting @@ -55,5 +56,5 @@ developer and agent workflow around installation, indexing, querying, safety, au 1. Add API reference docs for exported functions and result types. 2. Add MCP tool schema examples for agent developers. -3. Add a model-preload guide for semantic embeddings and offline TTS. +3. Add a model-preload guide for offline TTS. 4. Add deeper API reference docs for external library consumers once the public API grows. diff --git a/package.json b/package.json index 3c2e8c8..a9592a6 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "license": "MIT", "packageManager": "pnpm@11.9.0", "scripts": { - "build": "pnpm --filter @jcode.labs/mimir-tts build && pnpm --filter @jcode.labs/mimir build", - "check": "pnpm --filter @jcode.labs/mimir-tts check && pnpm --filter @jcode.labs/mimir check", + "build": "pnpm --filter @jcode.labs/mimir-ui build && pnpm --filter @jcode.labs/mimir-app build && pnpm --filter @jcode.labs/mimir-landing build && pnpm --filter @jcode.labs/mimir-tts build && pnpm --filter @jcode.labs/mimir build", + "check": "pnpm --filter @jcode.labs/mimir-ui check && pnpm --filter @jcode.labs/mimir-app check && pnpm --filter @jcode.labs/mimir-landing check && pnpm --filter @jcode.labs/mimir-tts check && pnpm --filter @jcode.labs/mimir check", "commitlint": "commitlint --from=HEAD~1 --to=HEAD --verbose", + "dev:app": "pnpm --filter @jcode.labs/mimir-app dev", + "dev:landing": "pnpm --filter @jcode.labs/mimir-landing dev", "format": "biome format --write .", "lint": "biome ci .", "lint:fix": "biome check --write .", diff --git a/packages/mimir-app/README.md b/packages/mimir-app/README.md new file mode 100644 index 0000000..1fd4e3d --- /dev/null +++ b/packages/mimir-app/README.md @@ -0,0 +1,17 @@ +# Mimir App + +Private Tauri desktop/mobile shell for Mimir. + +Root `pnpm build` validates the Vite frontend bundle. Native desktop/mobile builds stay explicit: + +```bash +pnpm --filter @jcode.labs/mimir-app tauri:dev +pnpm --filter @jcode.labs/mimir-app tauri:build +pnpm --filter @jcode.labs/mimir-app tauri:ios:init +pnpm --filter @jcode.labs/mimir-app tauri:ios:dev +pnpm --filter @jcode.labs/mimir-app tauri:android:init +pnpm --filter @jcode.labs/mimir-app tauri:android:dev +``` + +The app uses `@jcode.labs/mimir-ui` for shared styling and should keep privacy controls visible by +default. diff --git a/packages/mimir-app/index.html b/packages/mimir-app/index.html new file mode 100644 index 0000000..ad23fba --- /dev/null +++ b/packages/mimir-app/index.html @@ -0,0 +1,12 @@ + + + + + + Mimir + + +
+ + + diff --git a/packages/mimir-app/package.json b/packages/mimir-app/package.json new file mode 100644 index 0000000..3995449 --- /dev/null +++ b/packages/mimir-app/package.json @@ -0,0 +1,38 @@ +{ + "name": "@jcode.labs/mimir-app", + "version": "0.4.10", + "private": true, + "description": "Cross-platform Mimir desktop and mobile shell built with Tauri.", + "type": "module", + "license": "MIT", + "scripts": { + "build": "tsc -p tsconfig.json --noEmit && vite build", + "check": "tsc -p tsconfig.json --noEmit", + "dev": "vite", + "preview": "vite preview", + "tauri": "tauri", + "tauri:android:dev": "tauri android dev", + "tauri:android:init": "tauri android init", + "tauri:build": "tauri build", + "tauri:dev": "tauri dev", + "tauri:ios:dev": "tauri ios dev", + "tauri:ios:init": "tauri ios init" + }, + "dependencies": { + "@jcode.labs/mimir-ui": "workspace:*", + "@tauri-apps/api": "^2.10.0", + "lucide-react": "^1.21.0", + "react": "19.2.7", + "react-dom": "19.2.7" + }, + "devDependencies": { + "@tauri-apps/cli": "^2.10.0", + "@tailwindcss/vite": "^4.3.1", + "@types/react": "19.2.17", + "@types/react-dom": "19.2.3", + "@vitejs/plugin-react": "^5.2.0", + "tailwindcss": "^4.3.1", + "typescript": "^5.9.3", + "vite": "^8.0.13" + } +} diff --git a/packages/mimir-app/src-tauri/Cargo.toml b/packages/mimir-app/src-tauri/Cargo.toml new file mode 100644 index 0000000..1dc53d5 --- /dev/null +++ b/packages/mimir-app/src-tauri/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "mimir-app" +version = "0.4.10" +description = "Mimir desktop and mobile shell" +authors = ["Jean-Baptiste Thery"] +edition = "2021" +license = "MIT" + +[lib] +name = "mimir_app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2", features = [] } + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +tauri = { version = "2", features = [] } diff --git a/packages/mimir-app/src-tauri/build.rs b/packages/mimir-app/src-tauri/build.rs new file mode 100644 index 0000000..d860e1e --- /dev/null +++ b/packages/mimir-app/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/packages/mimir-app/src-tauri/capabilities/default.json b/packages/mimir-app/src-tauri/capabilities/default.json new file mode 100644 index 0000000..13cae5e --- /dev/null +++ b/packages/mimir-app/src-tauri/capabilities/default.json @@ -0,0 +1,7 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Default Mimir app capabilities.", + "windows": ["main"], + "permissions": ["core:default"] +} diff --git a/packages/mimir-app/src-tauri/src/lib.rs b/packages/mimir-app/src-tauri/src/lib.rs new file mode 100644 index 0000000..2e6c5ac --- /dev/null +++ b/packages/mimir-app/src-tauri/src/lib.rs @@ -0,0 +1,6 @@ +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .run(tauri::generate_context!()) + .expect("error while running Mimir") +} diff --git a/packages/mimir-app/src-tauri/src/main.rs b/packages/mimir-app/src-tauri/src/main.rs new file mode 100644 index 0000000..59c1d4d --- /dev/null +++ b/packages/mimir-app/src-tauri/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + mimir_app_lib::run() +} diff --git a/packages/mimir-app/src-tauri/tauri.conf.json b/packages/mimir-app/src-tauri/tauri.conf.json new file mode 100644 index 0000000..4151c97 --- /dev/null +++ b/packages/mimir-app/src-tauri/tauri.conf.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.tauri.app/config/2", + "productName": "Mimir", + "version": "0.4.10", + "identifier": "works.jcode.mimir", + "build": { + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build", + "devUrl": "http://localhost:5173", + "frontendDist": "../dist" + }, + "app": { + "windows": [ + { + "title": "Mimir", + "width": 1180, + "height": 820, + "minWidth": 390, + "minHeight": 720 + } + ], + "security": { + "csp": null + } + }, + "bundle": { + "active": true, + "targets": "all", + "category": "Productivity", + "shortDescription": "Sovereign local RAG for confidential dossiers.", + "longDescription": "Mimir is a local-first document retrieval app for confidential dossiers and AI agents." + } +} diff --git a/packages/mimir-app/src/app.tsx b/packages/mimir-app/src/app.tsx new file mode 100644 index 0000000..4c901e1 --- /dev/null +++ b/packages/mimir-app/src/app.tsx @@ -0,0 +1,162 @@ +import { + Badge, + Button, + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, + Input, + Progress, + Textarea, +} from "@jcode.labs/mimir-ui" +import { + Database, + FileSearch, + FolderOpen, + HardDrive, + LockKeyhole, + MessageSquareText, + RefreshCw, + ShieldCheck, +} from "lucide-react" + +const sources = [ + { name: "Client RFP", files: 128, status: "Indexed" }, + { name: "Architecture notes", files: 42, status: "Watching" }, + { name: "Legal review", files: 17, status: "Local only" }, +] + +const citations = [ + { + source: "operations-brief.md", + text: "approved runtime: encrypted disk, local retrieval, no telemetry", + }, + { + source: "security-policy.yaml", + text: "remote model loading disabled; access log stores metadata only", + }, +] + +export function App(): React.JSX.Element { + return ( +
+
+ + +
+
+
+
+ Tauri desktop + mobile shell +

Talk to local documents.

+

+ Mimir Core stays MIT. This app is the installable product surface for folders, + ingestion, retrieval, and visible privacy controls. +

+
+ +
+
+ +
+ + + Projects + Local knowledge bases stored per workspace. + + + {sources.map((source) => ( +
+
+

{source.name}

+

{source.files} files

+
+ {source.status} +
+ ))} +
+
+ + + + Ask with citations + + Retrieval context only; synthesis remains your agent's job. + + + +
+ + +
+