KeiSeiKit-1.0/_primitives/_rust
Parfii-bot 3f2aa1189b feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands
Parallel agent batch. All five tasks delivered functional + tested.
NOT deployed — user is in live conversation with the bot.

## Crates added (2 new)

### kei-contacts-google (466 LOC, 5 tests)
Thin Google People API client. Takes pre-acquired access_token from
kei-auth-google's OAuth flow; calls /v1/people/me/connections?personFields=...,
parses 200-entry first page (TODO: pagination via nextPageToken), maps
to kei_social_store::Person. Errors: Http / Auth(401) / Parse.

### kei-contacts-apple (593 LOC, 7 tests + 1 doc-test)
CardDAV client for iCloud Contacts using Basic Auth (Apple ID +
app-specific password). Sends REPORT with addressbook-query XML body,
parses multistatus → embedded vCards → AppleContact. Tiny vCard
parser (~150 LOC) handles FN/N/EMAIL/TEL/ORG/NOTE/UID, single-line
only (no line-folding for MVP). Discovery (PROPFIND .well-known/carddav
→ principal → addressbook-home-set) deferred — user supplies
addressbook URL via with_addressbook_url().

Both crates registered in workspace members.

## kei-buddy crate additions

### src/topic_classify.rs (116 LOC, 3 tests)
Free fn classify_and_store_topic(extractor, topics, chat_id, text)
called from process_text when state == OnboardState::Ready. Builds
classifier prompt → LLM → parses {slug, title} → validates slug
shape (kebab-case, ascii) → Topics::add_topic + add_digest. All
failure paths log + return; conversation never blocks.

### src/tick.rs (188 LOC, 3 integration tests) + src/bin/kei-buddy-tick.rs (67 LOC)
Second binary. Oneshot CLI for systemd timer: walks all known
chat_ids in BuddyStore → lists topics → searches recent chat
messages per topic (configurable window/limit) → LLM digest →
Topics::add_digest. Outputs JSON TickReport to stdout. Env-driven
config. NoOpExtractor fallback when no LLM creds (graceful degradation).

### src/commands.rs (146 LOC) + src/command_exec.rs (111 LOC, 7 tests)
Slash-commands intercepted BEFORE handle_step in process_text:
  /whois <name>   contacts.search_contacts + common_connections for hits
  /find <q>       chat_log.search scoped to chat_id
  /topics         topics.list_topics
  /contacts       contacts.search_contacts("", 10)
  /help           static usage text (Russian)
If command parsed, response built from stores, sent, logged to
chat_log — FSM skipped for that turn.

### src/serve_runner.rs (69 LOC) — refactor
run_serve + start_listener + init_tracing extracted out of serve.rs
to bring serve.rs back to 189 LOC (was 248 after previous wave).

### Wiring
BuddyContext gains `contacts: Arc<Contacts>` and `topics: Arc<Topics>`.
ServeConfig gains contacts_db_path + topics_db_path. Binary reads
KEI_BUDDY_CONTACTS_DB_PATH + KEI_BUDDY_TOPICS_DB_PATH env (defaults
./kei-buddy-contacts.db, ./kei-buddy-topics.db). cmd_migrate applies
schema for all three side-stores (chat_log + contacts + topics).

## Verify-before-commit (RULE 0.13 §)
  * cargo check -p kei-buddy (default + extractor-openai): PASS
  * cargo test -p kei-buddy --lib: 41 passed / 0 failed (was 31)
  * cargo test -p kei-buddy --tests: 3 passed (tick integration)
  * cargo build -p kei-buddy --features extractor-openai: PASS
    (builds both kei-buddy + kei-buddy-tick binaries)
  * cargo check -p kei-contacts-google: PASS (5 tests)
  * cargo check -p kei-contacts-apple: PASS (7 + 1 doc)
  * cargo check --workspace: PASS

## STATUS-TRUTH from all 5 agents: shipped=functional, behaviour-verified=yes

## Follow-up (deferred, non-blocking)
  * Google People API pagination (nextPageToken loop) — first 200 only
  * CardDAV auto-discovery (PROPFIND .well-known/carddav)
  * vCard line-folding (RFC 6350 §3.2)
  * Wire kei-contacts-google + kei-contacts-apple → Contacts.add_contact
    sync command (no glue yet)
  * systemd timer file for kei-buddy-tick (not shipped here — config only)
2026-05-12 16:33:58 +08:00
..
.cargo perf(ci): P1+P2 — thin-LTO + cu=16 + mold linker (~17min → ~4-5min) 2026-05-04 01:32:29 +08:00
firewall-diff chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
frustration-matrix chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-agent-runtime chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-artifact chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-atom-discovery chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-auth chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-auth-apple chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-auth-google fix(auth): Google OIDC account-takeover (CVE-2023-7028 class) — email_verified gate + sub as user_id + id_token cross-check 2026-05-03 15:38:53 +08:00
kei-auth-magiclink fix(security): cortex /term env_clear + bind guard, agent-stub-scan stdin, magiclink revoke 2026-05-03 15:38:23 +08:00
kei-auth-webauthn chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-backend-daytona chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-brain-view chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-buddy feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00
kei-cache chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-capability chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-changelog chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-chat-store chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-compute-baremetal chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-compute-digitalocean chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-compute-linode chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-compute-vultr chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-conflict-scan feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00
kei-contacts-apple feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00
kei-contacts-google feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00
kei-content-store chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-cortex fix(perf): bound per-user lock LRU + stream-cap atom subprocess output 2026-05-03 15:39:50 +08:00
kei-cron-scheduler chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-crossdomain chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-curator chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-db-contract chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-decision chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-decompose chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-diff chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-discover chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-dna-index chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-entity-store chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-export-trajectories chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-forge chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-fork chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-frustration-loop chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-gateway chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-gdrive-import chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-git-bitbucket chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-git-forgejo chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-git-gitea chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-git-gitlab chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-graph-check chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-graph-export chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-graph-stream chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-hibernate chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-import-project chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-leak-matrix chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-ledger chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-ledger-sign chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-llm-bridge-mlx chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-llm-llamacpp chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-llm-mlx chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-llm-ollama chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-llm-router chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-machine-probe chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-mcp fix(audit-batch): CI green + RULE 0.4/0.16/0.18 honesty pass 2026-05-03 19:09:59 +08:00
kei-memory chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-memory-postgres chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-memory-redis chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-memory-sled chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-memory-sqlite chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-migrate chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-model chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-model-router chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-net-ipsec chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-net-openvpn chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-net-wireguard chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-notify-discord chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-notify-slack chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-notify-sms chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-notify-telegram chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-pet chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-ping chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-pipe chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-projects-index chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-projects-watcher chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-provision chore: strip dangling sibling refs from Cargo.toml descriptions 2026-05-03 15:37:33 +08:00
kei-prune chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-refactor-engine chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-registry chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-replay chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-router chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-runtime fix(perf): bound per-user lock LRU + stream-cap atom subprocess output 2026-05-03 15:39:50 +08:00
kei-runtime-core chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-sage chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-scheduler chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-search-core chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-shared chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-skill-importer chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-skills chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-social-store chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-spawn chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-store chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-stt feat(kei-tts + kei-stt): TTS/STT abstractions with 4+3 backends 2026-05-12 13:47:35 +08:00
kei-svc-systemd chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-task chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-telegram-webhook feat(kei-telegram-webhook): inbound Telegram webhook handler 2026-05-12 13:33:31 +08:00
kei-tlog chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-token-tracker chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-tts feat(kei-tts + kei-stt): TTS/STT abstractions with 4+3 backends 2026-05-12 13:47:35 +08:00
kei-tty chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
kei-watch chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
keisei chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
mock-render chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
ssh-check chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
tokens-sync chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
visual-diff chore: author email + Cargo metadata SSoT (parfionovich@keilab.io) 2026-05-03 13:55:28 +08:00
.gitignore KeiSeiKit-public — clean state 2026-05-01 12:09:03 +08:00
Cargo.lock feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00
Cargo.toml feat(kei-buddy fleet): 5 atomics — google/apple contacts + classifier + tick + slash-commands 2026-05-12 16:33:58 +08:00