* feat(mail): add Microsoft 365 Graph sync source with delta state
Adds a GET-only Microsoft Graph source to bin/mail/sync (client-credentials,
delta query). Wires it into the CLI (--source m365), the worker pool and the
compose stack:
- m365.go: M365Client (token cache, delta pagination, message normalization,
attachment download) + m365Source adapter (per-mailbox folders + delta link)
- sync.go: M365Credentials in SyncConfig; Committer interface so delta links
only advance after a fully successful run (no skips on failure)
- cli.go: --source m365 with M365_/MS_ env passthrough
- Dockerfile: mail-build stage produces /mail-sync into the index image
- docker-entrypoint: mail-sync loop (sync -> import -> index, default 10s)
- compose.yaml: mail-sync service (index image, kb-var volume, secrets ro)
* feat(mail): adapt M365 ETL loop for OO+Gmail bots.
Default compose mail-sync to onlyoffice,gmail every 300s with import on new
mail; gate full --rebuild behind MAIL_SYNC_INDEX. Fix mail-build stage order
and add bin/stack/start-mail-sync.
Store valid_from/valid_to on leafs and filter search by calendar day without
overloading D16 source staleness; stack start/start-assistant wires brain + PicoClaw.
* ci: recall@5 SoT is Zig bin/brain/eval.go.
GitHub Actions rebuilds the repo corpus and runs the Go eval gate
instead of Python bin/kb/eval. Audit self is a hard fail (Gitea #19).
* ci: point eval at the checkout and keep DevOps in the corpus.
/tmp/brain-eval cannot walk up to var/kb.lbug; KB_ROOT is required.
Recall fragments must exist in README/docs so a repo-only rebuild gates.
Parser no longer errors; hop 1 returns File, hop 3 reaches Person.
Rebuild writes Leaf-[:FROM_FILE]->File so the walk is not empty
on a fresh index (Gitea #17).
Ladybug 0.19 stays FTS/HNSW queryable on MERGE of new ids; DROP INDEX
was the fatal path. bin/brain/add.go and POST /ingest land facts+info
in one transaction so watch/mail/git can become leafs now (Gitea #14).
Read path is cgo like search. Control questions live in rank so CI can
test them without ladybug. Python bin/kb/{get,stats,eval} stays the
runner fallback.
bin/brain/serve.go (ladybug tags) calls internal/brain instead of exec.
HTTP tests inject a fake API so CI stays cgo-free. ExecSearcher remains
the fallback when the binary is built without system_ladybug.
Published docs and skills still taught bin/kb/search --hop 1. Search lives
at bin/brain/search.go; --hop errors until File edges exist. A unittest
gates the SoT so the lie cannot return.
- bin/chats/: env-based paths, no /mnt/ /home/ hardcodes
- bin/edelweiss-pilot: remove curasoft, use DOCS_BASE env var
- bin/facts/crm: use KNOWLEDGE_MESH_SEED env var
- compose.edelweiss.yml: remove curasoft volumes, use DOCS_BASE
- docs/chat-import-plan.md: link to Gitea issue, no secrets
- bin/seed-edelweiss-facts.py: removed (curasoft-only)