// Contexto
Uma investigação independente sobre o Logi Actions SDK, conduzida como desenvolvedor externo. O plugin está submetido ao Logi Marketplace e o código é público no GitHub — tudo neste case pode ser verificado.
Tacit — Um Vocabulário Háptico para Estado ao Longo do Tempo
Design HápticoExperiência do DesenvolvedorPesquisa de CampoPlugin Publicado
Um build, uma exportação, a execução de um agente — você aperta, e então ou fica olhando a tela ou troca de janela e esquece. O Tacit reporta o estado de uma tarefa longa pelo polegar: cinco estados semânticos, sentidos num MX Master 4 enquanto você trabalha em qualquer aplicativo que estiver na tela. O plugin é a prova; o case é a investigação que o tornou necessário — percorrer a jornada do desenvolvedor externo e registrar o que ela custa.
// O vocabulário rodando — batidas comprimidas de 15 s; o intervalo de 450 ms do failed é real
_VISÃO GERAL
Desafio
Existe uma classe de tarefa que esses dispositivos ainda não atendem bem: as tarefas que levam tempo. A Logitech já nomeou o território — a documentação de haptics define uma categoria Progress Indicator e entrega as primitivas. O que falta acima delas é uma camada semântica: um vocabulário para estado ao longo do tempo, e uma convenção compartilhada, para que plugins escritos por autores diferentes não ensinem duas línguas a um mesmo polegar.
Abordagem
Percorrer a jornada do desenvolvedor como um desenvolvedor externo e registrar cada tropeço em estado bruto — 39 linhas, nunca editadas, apenas acrescentadas. Matar a premissa primeiro: uma sonda de duas horas antes de duas semanas de design. Construir o vocabulário sobre pesquisa de percepção publicada, nunca sobre impressões n=1 das primitivas da própria plataforma. Testar às cegas o que uma mão consegue provar — e pré-registrar, em doze previsões datadas, o que ela não consegue.
Impacto
Um plugin funcional, submetido ao Logi Marketplace, com repositório público sob licença MIT. Dez observações de campo que um avaliador pode conferir — cinco legíveis na documentação pública em cerca de um minuto cada, cinco alcançáveis apenas construindo o plugin e tentando entregá-lo a alguém. 20/20 de discriminação às cegas no par terminal, no ajuste de intensidade Subtle.
_A PERGUNTA// 01
Tarefas que levam tempo
A tese inteira, dita de saída: isto não é uma descoberta. É ler o roadmap — e construir a próxima camada sobre ele.
A execução de um agente, um build, a exportação de um vídeo, um upload grande. Você aperta, e então ou fica olhando a tela ou troca de janela e esquece. O MX Master 4 coloca um atuador háptico sob o polegar da mão que faz esse trabalho, e o Logi Actions SDK permite que qualquer plugin fale com ele.
A Logitech já nomeou este território. A documentação de haptics define uma categoria Progress Indicator; oito das quinze waveforms entregues carregam essa classificação; “um evento acontecendo em segundo plano” aparece listado como gatilho. As primitivas existem e a categoria está nomeada.
// A lacuna
O que falta acima das primitivas é uma camada semântica: um vocabulário para estado ao longo do tempo em vez de para momentos isolados — e uma convenção compartilhada, para que plugins escritos por autores diferentes não ensinem duas línguas a um mesmo polegar.
Esse enquadramento é também a primeira regra de honestidade do método. A lacuna que este case defende é de transmissão, não de conhecimento — nada aqui afirma que as primitivas da própria plataforma não foram estudadas; afirma que o que se sabe não chega ao desenvolvedor que escolhe entre dois nomes de waveform. Isso se sustenta apenas em evidência pública, e cada contagem deste case pode ser conferida na documentação pública.
_PREMISSA// 02
Matar a premissa primeiro
Antes de duas semanas de design, duas horas para descobrir se a ideia era sequer possível.
Tudo se apoia numa premissa: um plugin precisa alcançar a mão enquanto o usuário trabalha em outro lugar. Se a entrega háptica fosse restrita ao aplicativo hospedeiro — como notificações, foco e teclas de mídia costumam ser —, nenhum vocabulário para tarefas em segundo plano poderia existir. Então o primeiro build não foi o plugin. Foi uma sonda desenhada para matar o projeto a baixo custo.
Fig. 02 — o ecossistema, cada aresta observada, nenhuma inferida
Onde estava a atenção do usuário · cinco aplicativos, nenhum deles o hospedeiro
WindowsTerminalclaudeFigmachromeexplorer
● dois deles trazem o próprio perfil Logi, e os eventos dispararam mesmo assim
Atenção acima · sensação abaixo
O ecossistema do plugin, como o SDK o descreve — e o desenvolvedor está dentro dele
Desenvolvedor externoo ator, não a plateia
Marketplacenunca percorrido
nada aqui está publicado ainda
registra uma fonte de eventos, HasHapticMapping declarado
Logi Plugin Servicecarrega aquilo para onde é apontado
um arquivo em que qualquer coisa pode escrever
TacitDefaultEventSource.yaml · eventMapping.yaml
Três escritoresuma linha de texto cada
MX Master 4um atuador
o polegar
a mesma pessoa, nas duas faixas ao mesmo tempoum arquivo .link — escrito num diretório que ainda não existia · fricção 09um nome semântico resolve para uma das quinze waveforms
A entrega não tem escopoo pulso chega qualquer que seja o dono da tela — e um perfil de terceiro ativo não o suprime14 ms · seis execuções · 31 eventos
Cada aresta sólida foi vista acontecendo numa única máquina: seis execuções, trinta e um eventos iniciados pelo plugin, cinco aplicativos em primeiro plano, nenhum deles o hospedeiro. A aresta tracejada é a rota que este projeto nunca percorreu — na época da sonda, nada construído aqui estava publicado. O desvio se manteve em 14 ms sobre o intervalo nominal de 10 s da sonda. O único tropeço numerado no desenho é uma linha do log bruto de fricção, que a próxima seção abre.
// Duas horas contra duas semanas
Duas horas de sonda responderam se valia gastar duas semanas de design. Execução e entrega ambas sem escopo — e se a resposta tivesse sido não, o projeto teria morrido antes do primeiro desenho. Essa ordem — premissa antes de ofício — é a decisão mais barata deste case.
_NOTAS DE CAMPO// 03
Percorrendo a jornada do desenvolvedor
A espinha dorsal do case: o plugin existe para que estas observações pudessem existir. Cada tropeço foi registrado em bruto, em ordem, nunca editado — e o log assume os nossos próprios erros na mesma tabela.
Fig. 03.1 — a jornada, desenhada como um service blueprinto que chega ao usuário fica uma linha acima do que a plataforma carrega
InstalarConfigurarIniciarEnquanto rodaPrecisa de vocêTerminaEvidênciao que de fato chega ao usuárioum card que não nomeia nada sobre o que reportaum único liga/desliga, dentro da preferência de intensidadeum pulsosharp_state_changeuma batida, a cada 15 ssubtle_collisionuma batida na porta, fora do compassoknockum pulso, ou três a 450 mscompleted / angry_alertUsuárioo que a pessoa fazinstala o pluginprocura as configurações deleinicia uma tarefa longatroca de aplicativo, e trabalhavolta para responderlê o desfecho no polegarLinha de interaçãoPalcoo que o usuário poderia ver ou sentir acontecendogerenciador de plugins do Options+o Tacit aparece, e não diz nadadiálogo Plugin Settings — metadados do manifesto, e o idioma em que o diálogo está escritoo atuador disparao atuador dispara na batidao atuador dispara fora da batidao atuador disparaLinha de visibilidadeBastidoreso que roda onde o usuário não vêo Logi Plugin Service carrega o plugin a partir de um arquivo .linkarmazenamento de configurações, criptografado e com chave, sem superfícieum escritor acrescenta uma linha ao canalRaiseEvent(taskStarted)o heartbeat, sequenciado no TaskRunnerRaiseEvent(taskTick)o único estado autorizado a interromperRaiseEvent(taskNeedsInput)a figura de três pulsos é sequenciada em códigoRaiseEvent(taskCompleted | taskFailed)Linha de interação internaSuportea plataforma por baixo, e o que ela carrega ou nãoLogiPluginTool · PluginApi.dllMarketplace, nunca percorridoAPI de configurações do plugin — ActionEditor, alcançável apenas a partir de uma ação vinculadaDefaultEventSource.yamlcinco nomes semânticos — nossos, não da plataformaHasHapticMappingdeclarado no LoupedeckPackage.yamleventMapping.yamlum nome semântico para uma primitivaquinze primitivas entregues, nenhuma delas pode ser criada
E abaixo das três linhas, o ator de quem a plataforma depende — os cinco achados, na ordem da jornada:
O desenvolvedorum terceiro, fora da empresa, trabalhando apenas com o que é publicado
1O modelo de configuração presume que um plugin é um conjunto de coisas que se apertampara o usuário, isso aparece como um controle que não está lá2A documentação silencia exatamente onde uma decisão depende deladecide se o plugin chega a ser tentado3A ferramenta reporta um estado que não é verdadeirodecide se o desenvolvedor confia no que construiu4O primeiro build do primeiro projeto não compiladecide se existe um plugin, para começo de conversa5Quinze primitivas, e nenhuma forma de saber como qualquer uma delas é sentidapara o usuário, isso aparece como o padrão errado para o estado
O blueprint é a razão pela qual este case nunca argumenta por adjetivo: cada afirmação acima está numa célula, sobre uma linha, num estágio — e as células vermelhas são os dois silêncios da jornada, ambos no momento em que o usuário encontra o plugin pela primeira vez.
O método é um log de fricção com três disciplinas. As linhas são acrescentadas no momento do tropeço, não reconstruídas depois. Uma coluna quem separa dois perfis de fricção — o do designer e o da IA, porque eles tropeçam de formas diferentes e a diferença é um dado. E uma coluna veredito marca a nossa própria inexperiência como nossa: de 39 linhas, 33 são lacunas de documentação ou plataforma, 5 são lacuna nossa, 1 fica indefinida.
Fig. 03.2 — das linhas cruas aos achadosapenas acréscimo; a curadoria veio depois e em separado
39 linhas, cruas33 lacuna de DX5 lacuna nossa1 indefinida
→
5achados de documentaçãolegíveis em páginas públicas em cerca de um minuto cada — e os cinco produzem um único reparo
5achados de superfície do produtoalcançáveis apenas construindo o plugin e tentando entregá-lo a alguém — cinco reparos diferentes
As cinco linhas de lacuna nossa são mostradas como nossas — apresentar inexperiência como defeito alheio é o jeito mais rápido de perder um leitor que conhece a plataforma.
// A regra do corte
Um achado é um reparo, não um assunto. Os cinco achados de documentação compartilham um único reparo — a página que documenta o recurso não carrega o vocabulário que o recurso exige — então contam como cinco observações, uma correção. O segundo conjunto exige cinco.
_VOCABULÁRIO// 04
Desenhando o vocabulário
O instrumento com que aquela caminhada foi feita, desenhado à vista de todos. Literatura antes do design: o vocabulário codifica pelo tempo, nunca pela textura — e a razão é um ranking, não uma questão de gosto.
Taxa de identificação, por eixo
ritmo93
contagem de pulsos90
amplitude70
e a amplitude é o eixo que degrada na intensidade Subtle — exatamente onde um usuário em fluxo deixa o controle
Fig. 04.1 — cinco estados, um eixoposição = tempo · altura = intensidade
starteduma marca seca, no zero
progressuma batida discreta, a cada 15 s
needsInputuma batida na porta, fora do compasso
completedum pulso cheio
failedtrês, a 450 ms
o áudio reproduz o ritmo · não o atuadorvibração onde o navegador suporta
O par terminal difere em forma, não em caráter — um pulso contra três — porque é a única decisão genuinamente difícil, tomada num momento em que o usuário já espera alguma coisa. É esse par que recebe o orçamento perceptual.
As decisões carregam suas razões. O silêncio é barato e perigoso — uma execução que termina em silêncio e uma que morreu são idênticas, e é por isso que completed existe como sinal positivo. needsInput viola a cadência de propósito: todo o resto cai na batida, então o único estado que precisa de você cai fora dela. A escalada para um pedido ignorado se contrai até um platô em vez de subir indefinidamente — um canal ambiente que cresce até virar alarme mudou de categoria.
Fig. 04.2 — três fluxos, uma gramáticacompleted · failed · needsInput
a execução, evento a evento — intervalos reais nomeados
janela de silêncio20 s reais — uma tarefa que termina aqui nunca fala
startedum pulso — anunciado depois da janela
progressa batida de 15 s — o silêncio entre batidas é informação
needsInputuma batida na porta, fora do compasso
escaladaas batidas seguintes contraem ×0,75 até um piso de 4 s — nunca desiste
resposta dadaa batida retoma
completedum pulso cheio, e o canal fecha
failedtrês a 450 ms, e então silêncio — uma figura, não um alarme
esperas comprimidas · figuras em velocidade realo som só começa com um toque
O estado que nunca desiste é o que custa mais caro ignorar — needsInput se contrai até um piso e se mantém. Os estados terminais falam uma vez e fecham: o silêncio depois de uma figura é o design, não um sinal perdido.
E um número foi encontrado na mão: o intervalo da figura é de 450 ms, não os 220 ms com que começou. A 220, o segundo e o terceiro pulsos de uma figura nunca chegavam ao atuador — o piso mecânico fica uma ordem de grandeza acima do piso perceptual de 10 ms que a literatura oferece. Nada na documentação do SDK menciona isso.
Fig. 04.3 — os dois padrões mais próximos são os dois que jamais podem ser confundidosquinze primitivas, ouvidas em sequência · 4 dos 105 pares soaram próximos
Uma mão, uma sessão, uma intensidade — uma impressão, não um resultado. O par mais próximo reportado foi completed contra mad, o próprio padrão de confirmação da documentação contra o exemplo dela para uma reunião a qual você não pôde participar: sucesso e falha, reportados como os dois mais próximos. O par de que o design depende foi então testado às cegas e separado 20/20 — os outros 101 pares seguem como parecem, sem nenhum teste.
A arquitetura tem três camadas, deliberadamente: nomes semânticos no código, o mapeamento nome→waveform na configuração — de modo que revisá-lo depois de um teste com usuários é uma edição, não um rebuild — e as quinze primitivas entregues por baixo. Uma ponte de design tokens, aplicada a um sentido que as ferramentas de design ainda não conseguem pré-visualizar. As duas camadas que entregamos são pequenas o bastante para serem lidas por inteiro:
Fig. 04.4 — não são cinco waveforms. São cinco significados.a camada que o SDK não entrega, declarada na configuração
events/DefaultEventSource.yaml — a camada semântica
events:
- name: taskStarted# dispara uma vez, e estabelece do que trata cada pulso seguinte
- name: taskTick# a batida, não uma mensagem — a ausência dela é que carrega sentido
- name: taskNeedsInput# o único estado autorizado a interromper
- name: taskCompleted# terminou, e deu certo
- name: taskFailed# terminou, e não deu certo
events/extra/eventMapping.yaml — a camada de mapeamento
haptics:
taskStarted: { DEFAULT: sharp_state_change }
taskTick: { DEFAULT: subtle_collision }
taskNeedsInput: { DEFAULT: knock }
taskCompleted: { DEFAULT: completed }
taskFailed: { DEFAULT: angry_alert }
# completed e mad nunca são o par — eles foram# reportados como os dois padrões mais próximos no dispositivo,# e são os dois estados que jamais podem ser confundidos.
O mapeamento vive na configuração em vez de no código, e é por isso que uma revisão depois de um teste com usuários é uma edição e não um rebuild. É também uma demonstração viva do argumento: a arquitetura de tokens em três camadas do SDK é boa — ela simplesmente não tem uma camada semântica em cima._EVIDÊNCIA// 05
Testar um sinal ambiente
Um sinal ambiente não pode testar a si mesmo: o autor já sabe qual estado escreveu no canal, e discriminação não é detecção. O aparato precisa remover esse saber.
O aparato cego escreve um estado terminal aleatório — completed ou failed — e só registra qual foi depois que o palpite é dito. Vinte tentativas em três rodadas, incluindo no ajuste de intensidade Subtle, aquele que um usuário em fluxo de fato manteria: 20 de 20. E uma vez, sem combinar, o vocabulário simplesmente foi usado por uma tarde de trabalho real — o que não é um resultado, mas é a razão pela qual o trabalho pareceu pronto.
Fig. 05 — o que foi testado, e o que foi apenas desenhadopreenchido é feito · vazado é devido
completed vs failed, às cegas — 20/20três rodadas · Subtle incluída · uma mão
P1–P6 para o protocolo de laboratório, F1–F6 para o modo de campo — cada uma escrita e datada antes de existir qualquer participante, de modo que uma execução futura é pontuada pelo registro, não pela memória.
// A metade honesta
Cada tentativa acima aconteceu em uma mão, e ela é a do designer. A aprendibilidade está em grande parte por testar — as tentativas medem se o design funciona, não se ele ensina. A retenção não foi testada. Os estudos que resolveriam as duas coisas estão desenhados, pré-registrados e à espera de mãos que não são as nossas — e o artefato diz isso nas próprias páginas em vez de deixar subentendido.
_PUBLICAÇÃO// 06
Publicar — os achados se voltam para nós mesmos
A publicação não foi um epílogo. Preparar o plugin para o Logi Marketplace virou as observações de campo contra o nosso próprio manifesto — e corrigiu ali o que o log havia reportado em todo o resto.
Fig. 06.1 — o laço que se fecha sobre nós mesmosfricção observada → decisão tomada, no nosso próprio plugin
o log39 linhas, observadas à vista de todos
→
o nosso manifestodecisões 37–40 — corrigidas aqui primeiro
→
o Marketplacesubmetido — a rota de instalação que funciona
→
outras mãoso estudo de campo, destravado
e o campo escreve as próximas linhas
Os quatro fechamentos, um a um
fricção 25 · o build só funcionava a partir de uma pasta→decisão 37 · intermediários fixados — a armadilha do próprio scaffold, resolvida pela correção que o log propôs
fricção 27 · o scaffold declara dispositivos que excluem justamente o dispositivo de que o haptics precisa→decisão 38 · o manifesto declara ActionsRing — corrigido no dia em que ganhou uma consequência visível
fricção 39 · o vocabulário de dispositivos aceito só existe dentro da DLL→encontrado por reflection no preparo da submissão — um nome desconhecido é lido como None, em silêncio
a alegação de macOS · empacotada, nunca executada→decisão 39 · a v1 declara apenas Windows — retirada sem teste em vez de submetida sem teste
O laço que mais importa: as fricções 33, 34 e 38 mostraram que a rota de instalação local reporta sucesso e não entrega nada — uma página no Marketplace é a rota de instalação que funciona, então publicar destrava o estudo de campo que esses defeitos bloqueavam.
Fig. 06.2 — a última mudança antes da submissãouma página de loja também é uma superfície
V1 · a barra é o ritmocortada — agora uma linha do registro
V2 · pulso atravessando a hastecortada — agora uma linha do registro
V3 · a contagem sob a marcaa escolhida — um T sobre três pontos
publicadoa peça de quebra-cabeça do scaffold, aposentada — decisão 40
As três marcas foram desenhadas e julgadas em renders de 48 pixels — aproximadamente o tamanho que uma página de loja mostra. V1 e V2 não foram apagadas: elas vivem como linhas do registro ATÉ ONDE FOI do workspace, cada uma com o critério medido que a matou._RESULTADOS// 07
O que existe agora
Tudo abaixo é alcançável hoje. Escolha um estado e siga um evento real o caminho inteiro — pelas três camadas entregues, até a quarta: a que a mão lê.
Fig. 07 — de uma linha escrita ao polegarcada estação é um arquivo real · escolha um estado
um escritort7 startedt7 progresst7 needsInputt7 completedt7 faileduma linha acrescentada ao canal — sem SDK, sem C#, sem projeto de plugin
camada semântica · events/DefaultEventSource.yaml- name: taskStarted- name: taskTick- name: taskNeedsInput- name: taskCompleted- name: taskFailedcinco nomes — nossos, não da plataforma
camada de mapeamento · events/extra/eventMapping.yamltaskStarted: { DEFAULT: sharp_state_change }taskTick: { DEFAULT: subtle_collision }taskNeedsInput: { DEFAULT: knock }taskCompleted: { DEFAULT: completed }taskFailed: { DEFAULT: angry_alert }por dispositivo, com fallback DEFAULT — revisar é uma edição, não um rebuild
primitiva · uma de quinzesharp_state_changesubtle_collisionknockcompletedangry_alertconjunto fixo — seleção, nunca síntese
a quarta — não é camada— no figure: one pulse, nothing to sequenceheartbeat: 15 s — TaskRunner.cs, not yamlinterval ×= 0.75 · floor 4 s — TaskRunner.csone pulse, then the channel closesSequence.Pulses(raise, "taskFailed", 3, 450)nada no sistema de tokens consegue expressar contagem ou intervalo
o polegaruma marca seca, no zerouma batida discreta, a cada 15 suma batida na porta, fora do compassoum pulso cheiotrês, a 450 ms
cada estação acima executou — nenhuma inferidao áudio reproduz o ritmo · não o atuador
Três camadas são entregues — um nome, um mapeamento, uma waveform — e cada uma é um arquivo que este repositório guarda hoje. A quarta camada é a que a mão de fato lê: a contagem, o intervalo e a contração vivem em código, porque nada no sistema de tokens consegue dizer três, nem 450 ms.
O plugin
Submetido ao Logi Marketplace em 3 de setembro de 2026 — em análise. Cinco estados semânticos, guiados por canal, sem aplicativo vinculado — e o par terminal separado 20/20 às cegas, no ajuste Subtle.
O registro
39 linhas de fricção · 40 decisões de design, cada uma com o que a forçou e o que ela preteriu · 12 previsões pré-registradas em dois desenhos de estudo · um workspace de evidências com 17 páginas
A contribuição
Uma camada semântica para estado ao longo do tempo — cinco nomes, uma convenção compartilhada para um polegar, e uma camada de mapeamento que torna a revisão uma edição em vez de um rebuild — proposta apenas sobre evidência pública
// o entregável, hojeclonar · buildar · sentir · MIT · público
A listagem na loja está em análise; o código não está esperando. O plugin, o kill test, 39 linhas de fricção, 40 decisões, dois protocolos de estudo — a investigação inteira, conferível.
_REFLEXÃO
// 08
O produto é invisível. O julgamento não é.
O código aqui foi escrito por uma IA sob a direção de um designer — dito com todas as letras,
porque o método faz parte do que está sendo mostrado. O que encolheu foi a distância entre uma
decisão de design e um artefato testável: uma ideia sobre ritmo virou uma coisa que um polegar
podia vetar no mesmo dia.
E um polegar é exatamente o limite: ele pode provar que um vocabulário funciona, nunca que ele ensina.
A metade honesta — pré-registrada, datada, por fazer — não é uma ressalva. Numa superfície
tão silenciosa quanto esta, ela é o design.