
HiddenSteps — uma plataforma pessoal de inteligência de fluxo de trabalho local-first
Este é o complemento honesto do estado atual ao mapa de módulos-alvo de docs/design/02-system-architecture.md. Ele descreve o que está realmente construído, o que foi verificado contra um backend real vs. um mock, e o que ainda está genuinamente faltando — não o que está planejado (isso está em docs/roadmap/01-implementation-roadmap.md).
Execute cargo build --workspace && cargo test --workspace && cargo clippy --workspace --all-targets -- -D warnings a partir da raiz do repositório. No momento em que isto foi escrito: 12 crates, 193 testes aprovados, zero avisos do clippy, cargo fmt --check limpo — 183 nos 11 crates que não precisam de display ou serviço externo, mais 10 em hiddensteps-observation que precisam de um display X11 ativo (verificados onde um existe; veja essa linha). Quatro testes estão marcados com #[ignore] por design (veja abaixo) e não são contados como falhas nem como parte dos 193.
Além disso, fora de crates/ (não faz parte do workspace raiz — veja o motivo abaixo):
hiddensteps-event-store com similaridade de cosseno calculada em Rust, substituindo a tabela virtual sqlite-vec da ADR-0007 (veja o comentário no topo de event-store/src/schema.sql) — carregar uma extensão SQLite nativa não era verificável neste ambiente, e a própria ADR-0007 observa que, em volumes realistas de usuário único, o comportamento do sqlite-vec é busca exata por força bruta. Mesma semântica, sem risco de extensão nativa.hiddensteps-observation (src/macos/, src/windows/) são código-fonte completo e real contra APIs de plataforma estáveis há muito tempo (CGWindowListCopyWindowInfo; GetForegroundWindow/GetWindowTextW/QueryFullProcessImageNameW), escritos sem um toolchain macOS/Windows disponível — e ambos agora compilam limpos, verificado pela matriz de jobs de . O módulo macOS precisou de uma correção real primeiro (os parâmetros genéricos padrão não tipados de não satisfaziam o trait bound de para uma chave — corrigido tipando-o explicitamente como ); o Windows compilou limpo na primeira tentativa.crates/crates/* é o workspace do Cargo.toml raiz e é totalmente compilável/testável neste ambiente de desenvolvimento Linux, sem nenhuma dependência de sistema além do que cargo baixa. apps/desktop/src-tauri precisa de webkit2gtk-4.1 (Linux) apenas para compilar, o que este ambiente não consegue instalar (sem sudo sem senha, sem caminho funcional via nix/gerenciador de pacotes — confirmado por tentativa direta). Mantê-lo fora do workspace significa que cargo build --workspace continua 100% verde aqui, em vez de ficar permanentemente vermelho por causa de um crate que ninguém consegue corrigir neste sandbox. Ele também precisa de sua própria tabela [workspace] vazia em seu Cargo.toml pelo mesmo motivo — caso contrário, o Cargo tenta anexá-lo a este workspace ancestral de qualquer forma e falha com "current package believes it's in a workspace when it's not." apps/desktop/ui não tem essa restrição e é verificado da mesma forma que o núcleo Rust. Ambas as partes ainda são verificadas de ponta a ponta — apenas pela CI em vez deste sandbox.
#[ignore]hiddensteps-security::keyring_store::tests::set_get_delete_round_trip_against_the_real_vault — precisa de um vault de credenciais do SO/sessão de desktop real.hiddensteps-observation::linux::shortcuts::tests::grabs_and_ungrabs_a_real_shortcut — executa um XGrabKey real em toda a sessão, o que seria disruptivo para executar automaticamente em um ambiente compartilhado.tests/ollama_live.rs de hiddensteps-llm-provider (2 testes) — precisam de uma instância Ollama real em execução. Ambos foram realmente executados durante o desenvolvimento contra uma instância local real qwen3:0.6b (modelo de raciocínio híbrido de 0,6B parâmetros) e passaram em ~2 segundos no total; substitua o modelo/URL por meio das variáveis de ambiente HIDDENSTEPS_TEST_OLLAMA_MODEL/HIDDENSTEPS_TEST_OLLAMA_URL para uma configuração diferente.Todos os quatro são testes reais, não vestigiais — docs/roadmap/03-testing-strategy.md §2 traça exatamente essa distinção entre lógica que pertence atrás de um mock na CI e integração com SO/sessão/serviço externo que pertence à verificação manual e deliberada. Execute qualquer um deles com cargo test -p <crate> -- --ignored (adicione <test name> para executar apenas um) em uma máquina onde isso seja apropriado.
| Crate | Implementa | Como foi verificado |
|---|
hiddensteps-domain | Tipos principais: PrivacyLevel/PrivacyState, EventSummary/SignalType, Pattern, Recommendation, AuditEntry, e CapturedSignal — um tipo que estruturalmente não pode ser persistido (sem Serialize), aplicando a regra de dados brutos da ADR-0006 no nível dos tipos | Testes unitários: round-tripping/ordenação de níveis, gating de TTL no modo Deep |
hiddensteps-security | SecretStore (ADR-0008): vault real do SO (KeyringSecretStore) + implementações em memória (de teste); geração de chave-mestre por CSPRNG (retornada em um wrapper zeroize::Zeroizing para que a chave seja apagada no drop em vez de permanecer na memória liberada); derivação de frase-passe Argon2id para o Modo Portátil (PassphraseKey zera sua chave derivada no drop, mantendo o salt não secreto). hiddensteps-event-store da mesma forma mantém o texto SQL PRAGMA key/rekey que contém a chave em Zeroizing | Testes unitários contra o armazenamento em memória e o KDF; o round-trip com o vault real está marcado com #[ignore] (veja abaixo) |
hiddensteps-event-store | SqlCipherEventStore (ADR-0003): o esquema completo de docs/design/07-database-schema.md, CRUD para estado de privacidade, eventos, log de auditoria, padrões, links padrão↔evento, embeddings de padrões (veja nota abaixo), recomendações, configuração do provedor de LLM e configurações genéricas, além de delete_all_data (transacional; também executa rekey para um "apagar tudo" que sobrevive a um relançamento)/export_data/count_rows (diagnóstico)/delete_expired_events (a varredura de TTL do modo Deep, chamada a partir do loop periódico de recomendações de apps/desktop/src-tauri — ttl_expires_at era persistido desde v0.1.0, mas nada excluía uma linha além dele antes disso); aplicação de chaves estrangeiras (PRAGMA foreign_keys = ON) para que o ON DELETE CASCADE de schema.sql nos links padrão↔evento realmente seja executado | 33 testes contra um arquivo SQLCipher real: chave errada falha ao abrir, a mesma chave reabre corretamente, delete-all limpa todas as tabelas incluindo as mais recentes, rekey faz round-trip, a varredura de TTL não afeta eventos não expirados, exclusão em cascata não deixa links padrão↔evento órfãos |
hiddensteps-redaction | O Mecanismo de Redação (docs/design/05-privacy-model.md §4): detectores de regex+Luhn para chaves de API/tokens/chaves PEM/e-mails/SSNs/cartões de crédito, um detector de segredos ambíguos baseado em entropia e a política de descarte diante da incerteza | 30 testes, incluindo entradas deliberadamente adversariais (segredos embutidos em prosa, não-segredos quase corretos como SHAs de git, SSNs sem traço/espaçados, números de cartão com dígitos adicionais, tokens de alta entropia em caixa uniforme) |
hiddensteps-pipeline | O Pipeline de Eventos (ADR-0006): Classificar → Redigir → Resumir, controle de nível de privacidade por tipo de sinal, atribuição de TTL do modo Deep | 8 testes cobrindo descartes acionados por redação, descartes por gating de nível e sumarização bem-sucedida |
hiddensteps-observation | ObservationSource (ADR-0005) + Linux: ActiveWindowSource (X11 GetInputFocus), FileOperationSource (inotify via notify), ClipboardMetadataSource (seleção X11, apenas metadados), GlobalShortcutSource (X11 XGrabKey). Além disso, arquivos de fonte para macOS/Windows (veja abaixo) | 10 dos 11 testes são executados contra backends reais neste ambiente — um display X11 ativo (DISPLAY=:0 do WSLg) e inotify real, não mocks. 1 teste (o grab real de GlobalShortcutSource) está marcado com #[ignore] por design |
hiddensteps-llm-provider | LlmProvider (ADR-0004): cliente Ollama (com um campo de requisição think: Option<bool> para modelos de raciocínio híbrido), um cliente compatível com o wire protocol da OpenAI (cobre OpenAI/Azure/OpenRouter/Together/Groq/DeepSeek/LocalAI), um cliente Anthropic Messages e detecção automática de runtime local. Cada cliente define um timeout de requisição (build_http_client) para que um remoto pendurado não bloqueie uma chamada para sempre; Ollama encaminha max_tokens como seu options.num_predict aninhado | 19 testes contra servidores mock wiremock (incluindo uma verificação real de que o timeout dispara e de que o Ollama realmente envia num_predict), mais 2 testes de integração com Ollama real (tests/ollama_live.rs, marcados com #[ignore] — veja abaixo) que encontraram e corrigiram um problema real: o mesmo prompt levava mais de dois minutos em um modelo local real de raciocínio híbrido com think no padrão, e alguns segundos com think: Some(false) |
hiddensteps-patterns | Detecção de Padrões (correspondência de sequências n-gram com janela deslizante) + Grafo de Workflow (grafo de transição com pesos nas arestas) — Camada 1 da ADR-0010 | 16 testes, incluindo um análogo direto do exemplo "observado 31 vezes" do próprio PROMPT.md e um teste de regressão garantindo que janelas sobrepostas em uma repetição contínua não são contadas duas vezes |
hiddensteps-recommendations | A Camada 2 do Mecanismo de Recomendações (ADR-0010): síntese por LLM com um contrato de prompt em JSON estruturado, um validador de contradições narrativas e um loop de tentativas — crucialmente, os campos numéricos (estimated_time_saved_minutes) nunca são extraídos da saída do LLM, apenas calculados a partir da Camada 1 | 23 testes, incluindo tentativa com JSON malformado, tentativa com contradição narrativa (cobrindo números por extenso e todos os campos controlados pelo LLM, não apenas why), e extração de JSON ciente de strings, contra um provedor de teste roteirizado |
hiddensteps-privacy-engine | O portão de despacho para a nuvem (docs/design/03-data-flow-diagrams.md §5) e o versionamento de consentimento (docs/design/05-privacy-model.md §5); PrivacyGatedProvider envolve qualquer LlmProvider para que o portão não possa ser contornado pelo caminho de chamada normal | 13 testes, incluindo que o conteúdo de Nível 4 é bloqueado mesmo com todos os consentimentos concedidos |
hiddensteps-plugin-host | O Host de Plugins WASM (ADR-0009): enumeração fechada de capacidades, validação de manifest, um sandbox baseado em wasmtime que vincula apenas as funções de host das capacidades concedidas, além de medição de combustível (fuel metering) e um ResourceLimiter de memória que limita CPU/memória de uma instância de plugin independentemente das capacidades que ela possui — os dois eixos que a seção Denial-of-Service de docs/research/06-threat-model.md aponta que não podem ser resolvidos apenas com a aplicação de capacidades (um módulo sem capacidades ainda pode fazer loop ou crescer memória para sempre). instantiate_from_manifest é o ponto de entrada seguro: ele força a validação do manifest (a regra de Nível 4 obrigatório para captura de tela) e rejeita conceder qualquer coisa que o manifest não declarou, antes que qualquer capacidade chegue ao linker — a fatia simples de capacidades de instantiate não tem nenhuma ligação com um manifest | 20 testes, incluindo tentativas reais de fuga de capacidades: módulos WAT escritos à mão e compilados no momento do teste, provando que o import de uma capacidade não concedida é genuinamente não resolvido (a instanciação falha), não meramente não usado; além de um módulo de loop infinito real e um módulo de memory.grow ilimitado que geram trap em vez de travar/esgotar memória |
hiddensteps-enterprise-policy | Esquema de política (docs/design/05-privacy-model.md §6) com exatamente duas alavancas (piso de nível de privacidade, allowlist de provedores) — não existe campo para qualquer outra coisa que uma política possa querer restringir. Carregado de um arquivo enterprise-policy.json no diretório de dados do aplicativo, se presente (um mecanismo real, ainda que provisório — o conector completo de plugin PolicyLoader que docs/design/08-plugin-architecture.md descreve não está construído), persistido por meio da tabela enterprise_policy de hiddensteps-event-store e de fato aplicado nos comandos set_privacy_level/set_ai_provider de apps/desktop/src-tauri — os dois pontos de mutação pelos quais uma escolha de nível/provedor é sempre gravada | 6 testes, incluindo o parsing de um arquivo de política maximamente adversarial com cinco chaves extras excluídas por design e confirmando que nenhuma delas sobrevive ao parsing |
| Local | Implementa | Como foi verificado |
|---|
../apps/desktop/ui | UI React/TypeScript: OnboardingWizard (todas as 8 telas, docs/ux/02), PrivacyDashboard (docs/ux/03), RecommendationCard (docs/ux/04), SettingsPage, DiagnosticsPage, interligados em App.tsx — comunicando-se com o núcleo apenas por meio de um tauriBridge.ts tipado | 50 testes via vitest + @testing-library/react contra renderização jsdom real, incluindo o gating de etapas do assistente de onboarding (não há avanço além da validação sem uma verificação bem-sucedida, não há início de observação sem marcar o consentimento), exibição de erros em todos os locais de chamada de mutação, o banner de reconsentimento, a trilha de evidências da recomendação e uma verificação de acessibilidade com axe-core; tsc -b faz a verificação de tipos sem erros |
../apps/desktop/src-tauri | O shell Tauri: ~21 comandos IPC (docs/design/09-api-specification.md) conectando todos os crates acima, além de um loop de captura→pipeline→armazenamento→evento de UI em segundo plano para Linux | Compila limpo no Linux, macOS e Windows em CI — não especificamente neste sandbox de desenvolvimento (veja ../apps/desktop/README.md para saber o motivo), mas a ressalva de "não verificado" que costumava estar aqui desapareceu: a primeira execução real da CI encontrou e corrigiu 3 bugs reais (um derive Serialize ausente, um recurso de Cargo ausente, um arquivo de ícone gerado ausente) que nenhuma quantidade de revisão local teria pegado |
core.github/workflows/ci.ymlCFDictionaryfind&CFStringCFDictionary<CFString, CFType>hiddensteps-observation/src/lib.rs — a primeira precisa de um artefato separado de extensão de navegador que este repositório não contém; a segunda (GlobalShortcutSource) está implementada, mas nunca é iniciada automaticamente, porque capturar uma combinação de teclas em toda a sessão em um sandbox de desenvolvimento compartilhado seria ativamente disruptivo.LlmProvider que estiver configurado; foi testada contra um provedor substituto roteirizado (asserções reais sobre a lógica de tentativa/validação). O próprio hiddensteps-llm-provider agora tem cobertura com Ollama real (veja abaixo); executar o contrato de prompt do próprio sintetizador contra um modelo real de ponta a ponta (em vez do cliente HTTP subjacente) é o próximo passo natural, ainda não feito.get_diagnostics (o shell Tauri) reporta contagens reais de eventos/padrões/recomendações/log de auditoria e o tamanho real do arquivo em disco, mas não o uso de GPU/CPU/memória, o status de permissão do SO para observação nem o status de atualização — a lista completa de Self-Diagnostics do PROMPT.md. Cada componente de UI que renderiza isso diz isso explicitamente, em vez de mostrar um "OK" fabricado.