
HiddenSteps — eine Local-First-Plattform für persönliche Workflow-Intelligenz.
Dies ist die ehrliche, den aktuellen Stand abbildende Ergänzung zur Zielmodul-Karte aus docs/design/02-system-architecture.md. Sie sagt, was tatsächlich gebaut ist, was gegen ein echtes Backend statt gegen einen Mock verifiziert wurde und was wirklich noch fehlt — nicht, was geplant ist (dafür gibt es docs/roadmap/01-implementation-roadmap.md).
Führen Sie cargo build --workspace && cargo test --workspace && cargo clippy --workspace --all-targets -- -D warnings vom Repository-Stammverzeichnis aus. Zum Zeitpunkt dieses Schreibens: 12 Crates, 193 bestandene Tests, keine Clippy-Warnungen, cargo fmt --check sauber — 183 verteilt auf die 11 Crates, die weder ein Display noch einen externen Dienst benötigen, plus 10 in hiddensteps-observation, die ein aktives X11-Display benötigen (verifiziert, wo eines vorhanden ist; siehe diese Zeile). Vier Tests sind bewusst mit #[ignore] markiert (siehe unten) und zählen weder als Fehlschläge noch als Teil der 193.
Außerdem, außerhalb von crates/ (nicht Teil des Root-Workspace — siehe unten für die Begründung):
hiddensteps-event-store als einfache BLOBs gespeichert, wobei die Kosinus-Ähnlichkeit in Rust berechnet wird; sie dienen als Ersatz für die virtuelle sqlite-vec-Tabelle aus ADR-0007 (siehe den Kommentar am Anfang von event-store/src/schema.sql) — das Laden einer nativen SQLite-Erweiterung war in dieser Umgebung nicht verifizierbar, und ADR-0007 selbst merkt an, dass das Verhalten von sqlite-vec bei realistischen Einzelbenutzer-Volumina selbst eine Brute-Force-Exaktsuche ist. Gleiche Semantik, kein Risiko durch native Erweiterungen.hiddensteps-observation (src/macos/, src/windows/) sind echter, vollständiger Quellcode gegen seit langem stabile Plattform-APIs (CGWindowListCopyWindowInfo; GetForegroundWindow/GetWindowTextW/QueryFullProcessImageNameW), geschrieben ohne verfügbare macOS-/Windows-Toolchain — und beide kompilieren nun sauber, verifiziert durch die -Job-Matrix von . Das macOS-Modul benötigte zunächst eine echte Korrektur (die untypisierten Standard-Generik-Parameter von erfüllten die Trait-Bound von für einen -Schlüssel nicht — behoben durch explizite Typisierung als ); Windows kompilierte beim ersten Versuch sauber.crates/ liegencrates/* ist der Workspace des Root-Cargo.toml und in dieser Linux-Entwicklungsumgebung vollständig baubar/testbar, ohne Systemabhängigkeiten über das hinaus, was cargo herunterlädt. apps/desktop/src-tauri benötigt webkit2gtk-4.1 (Linux), um überhaupt zu kompilieren, was diese Umgebung nicht installieren kann (kein passwortloses sudo, kein funktionierender nix-/Paketmanager-Pfad — durch direkten Versuch bestätigt). Es außerhalb des Workspace zu halten, bedeutet, dass cargo build --workspace hier zu 100 % grün bleibt, statt wegen eines einzigen Crates dauerhaft rot zu sein, das in dieser Sandbox niemand reparieren kann. Aus demselben Grund benötigt es außerdem eine eigene leere [workspace]-Tabelle in seiner Cargo.toml — andernfalls versucht Cargo, es ohnehin an diesen übergeordneten Workspace anzuhängen, und schlägt mit "current package believes it's in a workspace when it's not" fehl. apps/desktop/ui hat keine solche Einschränkung und wird auf dieselbe Weise verifiziert wie der Rust-Kern. Beide Teile werden weiterhin End-to-End verifiziert — nur eben durch CI statt durch diese Sandbox.
#[ignore] markierten Testshiddensteps-security::keyring_store::tests::set_get_delete_round_trip_against_the_real_vault — benötigt einen echten OS-Anmeldedaten-Tresor bzw. eine Desktop-Sitzung.hiddensteps-observation::linux::shortcuts::tests::grabs_and_ungrabs_a_real_shortcut — führt ein echtes sitzungsweites XGrabKey aus, was bei einem automatischen Lauf in einer geteilten Umgebung störend wäre.tests/ollama_live.rs aus hiddensteps-llm-provider (2 Tests) — benötigt eine echt laufende Ollama-Instanz. Beide wurden während der Entwicklung tatsächlich gegen eine echte lokale qwen3:0.6b-Instanz (ein Hybrid-Reasoning-Modell mit 0,6 Mrd. Parametern) ausgeführt und bestanden in zusammen ~2 Sekunden; für ein anderes Setup können Modell/URL über die Umgebungsvariablen HIDDENSTEPS_TEST_OLLAMA_MODEL/HIDDENSTEPS_TEST_OLLAMA_URL überschrieben werden.Alle vier sind echte Tests, keine Relikte — docs/roadmap/03-testing-strategy.md §2 zieht genau diese Unterscheidung zwischen Logik, die in CI hinter einem Mock gehört, und OS-/Sitzungs-/Externdienst-Integration, die in bewusste, manuelle Verifikation gehört. Führen Sie jeden davon mit cargo test -p <crate> -- --ignored aus (fügen Sie <test name> hinzu, um nur einen auszuführen) auf einer Maschine, auf der das angemessen ist.
| Crate | Implementiert | Wie verifiziert |
|---|
hiddensteps-domain | Kern-Typen: PrivacyLevel/PrivacyState, EventSummary/SignalType, Pattern, Recommendation, AuditEntry und CapturedSignal — ein Typ, der strukturell nicht persistiert werden kann (kein Serialize), wodurch die Rohdaten-Regel aus ADR-0006 auf Typebene durchgesetzt wird | Unit-Tests: Level-Roundtrip/-Reihenfolge, TTL-Freigabesteuerung im Deep-Modus |
hiddensteps-security | SecretStore (ADR-0008): echte OS-Vault-Implementierung (KeyringSecretStore) sowie In-Memory-Implementierung (für Tests); CSPRNG-Master-Key-Erzeugung (in einem zeroize::Zeroizing-Wrapper zurückgegeben, sodass der Schlüssel beim Drop gelöscht wird, statt im freigegebenen Speicher zu verweilen); Argon2id-Passphrase-Ableitung für den Portable Mode (PassphraseKey löscht seinen abgeleiteten Schlüssel per Zeroize beim Drop und behält das nicht geheime Salt). hiddensteps-event-store hält ebenso den schlüsseltragenden SQL-Text von PRAGMA key/rekey in Zeroizing | Unit-Tests gegen den In-Memory-Store und die KDF; der Roundtrip gegen die echte Vault ist mit #[ignore] markiert (siehe unten) |
hiddensteps-event-store | SqlCipherEventStore (ADR-0003): das vollständige Schema aus docs/design/07-database-schema.md, CRUD für Datenschutzstatus, Ereignisse, Audit-Log, Patterns, Pattern↔Ereignis-Verknüpfungen, Pattern-Embeddings (siehe Hinweis unten), Empfehlungen, LLM-Provider-Konfiguration und allgemeine Einstellungen, plus delete_all_data (transaktional; führt auch rekey für ein "Alles löschen" durch, das einen Neustart übersteht)/export_data/count_rows (Diagnose)/delete_expired_events (die TTL-Bereinigung im Deep-Modus, aufgerufen aus der periodischen Empfehlungsschleife von apps/desktop/src-tauri — ttl_expires_at wurde seit v0.1.0 persistiert, aber zuvor löschte nichts eine Zeile, deren Zeitpunkt überschritten war); Fremdschlüssel-Erzwingung (PRAGMA foreign_keys = ON), sodass das ON DELETE CASCADE aus schema.sql für Pattern↔Ereignis-Verknüpfungen tatsächlich greift | 33 Tests gegen eine echte SQLCipher-Datei: falscher Schlüssel verhindert das Öffnen, derselbe Schlüssel öffnet korrekt erneut, Alles-löschen leert jede Tabelle einschließlich der neuesten, Rekey-Roundtrip funktioniert, TTL-Bereinigung lässt nicht abgelaufene Ereignisse unangetastet, Kaskadenlöschung hinterlässt keine verwaisten Pattern↔Ereignis-Verknüpfungen |
hiddensteps-redaction | Die Redaktions-Engine (docs/design/05-privacy-model.md §4): Regex- und Luhn-Detektoren für API-Schlüssel/Tokens/PEM-Schlüssel/E-Mails/SSNs/Kreditkarten, ein entropiebasierter Detektor für mehrdeutige Geheimnisse sowie die Richtlinie "Bei Unsicherheit verwerfen" | 30 Tests, einschließlich bewusst adversarischer Eingaben (Geheimnisse in Fließtext eingebettet, Beinahe-Nicht-Geheimnisse wie Git-SHAs, SSNs ohne Bindestriche/mit Leerzeichen, mit Ziffern aufgefüllte Kartennummern, durchgängig gleich geschriebene Hochenergie-Tokens) |
hiddensteps-pipeline | Die Ereignis-Pipeline (ADR-0006): Klassifizieren → Redigieren → Zusammenfassen, Freigabesteuerung nach Datenschutzstufe je Signaltyp, TTL-Zuweisung für den Deep-Modus | 8 Tests, die Verwerfungen durch Redaktion, Verwerfungen durch die Stufen-Freigabe und erfolgreiche Zusammenfassungen abdecken |
hiddensteps-observation | ObservationSource (ADR-0005) + Linux: ActiveWindowSource (X11 GetInputFocus), FileOperationSource (inotify über notify), ClipboardMetadataSource (X11-Auswahl, nur Metadaten), GlobalShortcutSource (X11 XGrabKey). Dazu macOS-/Windows-Quelldateien (siehe unten) | 10 von 11 Tests laufen in dieser Umgebung gegen echte Backends — ein aktives X11-Display (DISPLAY=:0 von WSLg) und echtes inotify, keine Mocks. 1 Test (der echte Grab von GlobalShortcutSource) ist bewusst mit #[ignore] markiert |
hiddensteps-llm-provider | LlmProvider (ADR-0004): Ollama-Client (mit einem think: Option<bool>-Request-Feld für Hybrid-Reasoning-Modelle), ein OpenAI-wire-kompatibler Client (deckt OpenAI/Azure/OpenRouter/Together/Groq/DeepSeek/LocalAI ab), ein Anthropic-Messages-Client sowie automatische Erkennung lokaler Laufzeitumgebungen. Jeder Client setzt ein Request-Timeout (build_http_client), sodass ein hängendes Remote-System einen Aufruf nicht für immer blockieren kann; Ollama leitet max_tokens als sein verschachteltes options.num_predict weiter | 19 Tests gegen wiremock-Mock-Server (einschließlich einer echten Prüfung, dass das Timeout auslöst, und der Prüfung, dass Ollama tatsächlich num_predict sendet), plus 2 echte Ollama-Integrationstests (tests/ollama_live.rs, mit #[ignore] markiert — siehe unten), die ein echtes Problem gefunden und behoben haben: Derselbe Prompt dauerte gegen ein echtes lokales Hybrid-Thinking-Modell mit auf den Standardwert belassenem think über zwei Minuten, mit think: Some(false) nur wenige Sekunden |
hiddensteps-patterns | Mustererkennung (Sliding-Window-n-Gramm-Sequenzabgleich) + Workflow-Graph (Übergangsgraph mit Kantengewichten) — Layer 1 aus ADR-0010 | 16 Tests, einschließlich eines direkten Analogons zum eigenen Beispiel "31 Mal beobachtet" aus PROMPT.md und eines Regressionstests, der sicherstellt, dass überlappende Fenster über eine durchgehende Wiederholung nicht doppelt gezählt werden |
hiddensteps-recommendations | Layer 2 der Empfehlungs-Engine (ADR-0010): LLM-Synthese mit einem strukturierten JSON-Prompt-Vertrag, einem Validator für erzählerische Widersprüche und einer Retry-Schleife — entscheidend: Die numerischen Felder (estimated_time_saved_minutes) werden überhaupt nie aus der LLM-Ausgabe geparst, sondern ausschließlich aus Layer 1 berechnet | 23 Tests, darunter Retry bei fehlerhaftem JSON, Retry bei erzählerischen Widersprüchen (abdeckend ausgeschriebene Zahlen und jedes von der LLM gesteuerte Feld, nicht nur why) sowie stringbewusste JSON-Extraktion, gegen einen skriptbasierten Test-Provider |
hiddensteps-privacy-engine | Das Cloud-Versand-Gate (docs/design/03-data-flow-diagrams.md §5) und die Einwilligungs-Versionierung (docs/design/05-privacy-model.md §5); PrivacyGatedProvider kapselt jeden LlmProvider, sodass das Gate über den normalen Aufrufpfad nicht umgangen werden kann | 13 Tests, darunter die Prüfung, dass Level-4-Inhalte selbst bei vollständig erteilter Einwilligung blockiert werden |
hiddensteps-plugin-host | Der WASM-Plugin-Host (ADR-0009): geschlossene Capability-Aufzählung, Manifest-Validierung, eine auf wasmtime basierende Sandbox, die nur Host-Funktionen gewährter Capabilities einbindet, plus Fuel-Metering und einen Speicher-ResourceLimiter, der CPU/Speicher einer Plugin-Instanz unabhängig davon begrenzt, welche Capabilities sie besitzt — die beiden Achsen, die der Denial-of-Service-Abschnitt von docs/research/06-threat-model.md als nicht durch bloße Capability-Durchsetzung lösbar benennt (ein Modul ohne Capabilities kann trotzdem endlos schleifen oder den Speicher unbegrenzt wachsen lassen). instantiate_from_manifest ist der sichere Einstiegspunkt: Er erzwingt die Manifest-Validierung (die Regel, dass für Screenshots Level 4 erforderlich ist) und lehnt das Gewähren von allem ab, was das Manifest nicht deklariert hat, bevor irgendeine Capability den Linker erreicht — das einfache instantiate mit seiner Capability-Liste hat dagegen keinerlei Verbindung zu einem Manifest | 20 Tests, einschließlich echter Capability-Escape-Versuche: zur Testzeit kompilierte, handgeschriebene WAT-Module, die beweisen, dass der Import einer nicht gewährten Capability tatsächlich unaufgelöst ist (Instanziierung schlägt fehl) und nicht nur ungenutzt; außerdem ein echtes Endlos-Schleifen-Modul und ein Modul mit unbegrenztem memory.grow, die einen Trap auslösen, statt zu hängen bzw. den Speicher zu erschöpfen |
hiddensteps-enterprise-policy | Policy-Schema (docs/design/05-privacy-model.md §6) mit genau zwei Stellschrauben (Mindest-Datenschutzstufe, Provider-Allowlist) — es gibt kein Feld für irgendetwas, das eine Policy sonst noch einschränken könnte. Wird aus einer Datei enterprise-policy.json im App-Datenverzeichnis geladen, sofern vorhanden (ein echter, wenn auch vorläufiger Mechanismus — der vollständige PolicyLoader-Plugin-Konnektor, den docs/design/08-plugin-architecture.md beschreibt, ist nicht gebaut), über die enterprise_policy-Tabelle von hiddensteps-event-store persistiert und tatsächlich in den Befehlen set_privacy_level/set_ai_provider von apps/desktop/src-tauri durchgesetzt — den beiden Mutationspunkten, über die eine Stufen-/Provider-Wahl jemals geschrieben wird | 6 Tests, darunter das Parsen einer maximal adversarischen Policy-Datei mit fünf zusätzlichen, bewusst ausgeschlossenen Schlüsseln und die Bestätigung, dass keiner davon das Parsen überlebt |
| Ort | Implementiert | Wie verifiziert |
|---|
../apps/desktop/ui | React/TypeScript-UI: OnboardingWizard (alle 8 Bildschirme, docs/ux/02), PrivacyDashboard (docs/ux/03), RecommendationCard (docs/ux/04), SettingsPage, DiagnosticsPage, in App.tsx verdrahtet — kommuniziert mit dem Kern ausschließlich über ein typisiertes tauriBridge.ts | 50 Tests über vitest + @testing-library/react gegen echtes jsdom-Rendering, einschließlich der Schritt-Freigabesteuerung des Onboarding-Assistenten (kein Fortschritt über die Validierung hinaus ohne erfolgreiche Prüfung, kein Start der Beobachtung ohne Ankreuzen der Einwilligung), Fehleranzeige an jeder Mutations-Aufrufstelle, das Reconsent-Banner, die Empfehlungs-Evidenzspur sowie ein axe-core-Barrierefreiheits-Gate; tsc -b typprüft sauber |
../apps/desktop/src-tauri | Die Tauri-Shell: ~21 IPC-Befehle (docs/design/09-api-specification.md), die alle oben genannten Crates miteinander verdrahten, plus eine echte Hintergrundschleife für Linux: Erfassung→Pipeline→Store→UI-Ereignis | Kompiliert sauber auf Linux, macOS und Windows in CI — nicht speziell in dieser Dev-Sandbox (siehe ../apps/desktop/README.md für den Grund), aber der frühere Vorbehalt "nicht verifiziert" ist verschwunden: Der erste echte CI-Lauf fand und behob 3 echte Bugs (ein fehlendes Serialize-Derive, ein fehlendes Cargo-Feature-Flag, eine fehlende generierte Icon-Datei), die keine noch so gründliche lokale Überprüfung entdeckt hätte |
core.github/workflows/ci.ymlCFDictionaryfind&CFStringCFDictionary<CFString, CFType>hiddensteps-observation/src/lib.rs — Erstere benötigt ein separates Browser-Erweiterungs-Artefakt, das dieses Repo nicht enthält; Letzteres (GlobalShortcutSource) ist implementiert, wird aber nie automatisch gestartet, da das sitzungsweite Erfassen einer Tastenkombination in einer geteilten Dev-Sandbox aktiv störend wäre.LlmProvider; getestet wurde er gegen einen skriptbasierten Ersatz-Provider (echte Assertions auf der Retry-/Validierungslogik). hiddensteps-llm-provider selbst hat jetzt echte Ollama-Abdeckung (siehe unten); den eigenen Prompt-Vertrag des Synthesizers End-to-End gegen ein echtes Modell auszuführen (statt gegen den zugrunde liegenden HTTP-Client) ist der nächste natürliche Schritt, aber noch nicht erledigt.get_diagnostics (die Tauri-Shell) meldet echte Ereignis-/Pattern-/Empfehlungs-/Audit-Log-Zählungen und die echte Dateigröße auf der Platte, aber keine GPU-/CPU-/Speicherauslastung, keinen OS-Berechtigungsstatus der Beobachtung und keinen Aktualisierungsstatus — die vollständige Self-Diagnostics-Liste aus PROMPT.md. Jede UI-Komponente, die dies darstellt, weist ausdrücklich darauf hin, statt ein erfundenes "OK" zu zeigen.