// 001

// 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áptico Experiência do Desenvolvedor Pesquisa de Campo Plugin 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.

[ Código no GitHub → ]
Função Product Designer, dirigindo IA
Cronograma 25 Ago — 3 Set 2026
Tipo Investigação · Publicado
Stack C# · Logi Actions SDK
O MX Master 4 desenhado de perfil em traços, o atuador háptico sob o polegar
Semântico → primitivo
taskStarted sharp_state_change
taskTick subtle_collision · a cada 15 s
taskNeedsInput knock · fora do compasso
taskCompleted completed · um pulso
taskFailed angry_alert · três, a 450 ms
// O vocabulário rodando — batidas comprimidas de 15 s; o intervalo de 450 ms do failed é real

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.

// 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.

// 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
WindowsTerminal claude Figma chrome explorer
● 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 externo o ator, não a plateia
Marketplace nunca percorrido
nada aqui está publicado ainda
registra uma fonte de eventos, HasHapticMapping declarado
Logi Plugin Service carrega aquilo para onde é apontado
um arquivo em que qualquer coisa pode escrever
Tacit DefaultEventSource.yaml · eventMapping.yaml
Três escritores uma linha de texto cada
MX Master 4 um atuador
o polegar
a mesma pessoa, nas duas faixas ao mesmo tempo um arquivo .link — escrito num diretório que ainda não existia · fricção 09 um nome semântico resolve para uma das quinze waveforms
A entrega não tem escopo o pulso chega qualquer que seja o dono da tela — e um perfil de terceiro ativo não o suprime 14 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.

// 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 blueprint o que chega ao usuário fica uma linha acima do que a plataforma carrega
Instalar Configurar Iniciar Enquanto roda Precisa de você Termina Evidênciao que de fato chega ao usuário um card que não nomeia nada sobre o que reporta um único liga/desliga, dentro da preferência de intensidade um pulsosharp_state_change uma batida, a cada 15 ssubtle_collision uma batida na porta, fora do compassoknock um pulso, ou três a 450 mscompleted / angry_alert Usuárioo que a pessoa faz instala o plugin procura as configurações dele inicia uma tarefa longa troca de aplicativo, e trabalha volta para responder lê o desfecho no polegar Linha de interação Palcoo que o usuário poderia ver ou sentir acontecendo gerenciador de plugins do Options+o Tacit aparece, e não diz nada diálogo Plugin Settings — metadados do manifesto, e o idioma em que o diálogo está escrito o atuador dispara o atuador dispara na batida o atuador dispara fora da batida o atuador dispara Linha de visibilidade Bastidoreso que roda onde o usuário não vê o Logi Plugin Service carrega o plugin a partir de um arquivo .link armazenamento de configurações, criptografado e com chave, sem superfície um 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 interna Suportea plataforma por baixo, e o que ela carrega ou não LogiPluginTool · PluginApi.dllMarketplace, nunca percorrido API de configurações do plugin — ActionEditor, alcançável apenas a partir de uma ação vinculada DefaultEventSource.yamlcinco nomes semânticos — nossos, não da plataforma HasHapticMappingdeclarado no LoupedeckPackage.yaml eventMapping.yamlum nome semântico para uma primitiva quinze 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 tentado 3A ferramenta reporta um estado que não é verdadeirodecide se o desenvolvedor confia no que construiu 4O primeiro build do primeiro projeto não compiladecide se existe um plugin, para começo de conversa 5Quinze 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 achados apenas acréscimo; a curadoria veio depois e em separado
39 linhas, cruas 33 lacuna de DX5 lacuna nossa1 indefinida
5 achados de documentação legíveis em páginas públicas em cerca de um minuto cada — e os cinco produzem um único reparo
5 achados de superfície do produto alcançá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.

// 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 eixo posição = tempo · altura = intensidade
started uma marca seca, no zero
progress uma batida discreta, a cada 15 s
needsInput uma batida na porta, fora do compasso
completed um pulso cheio
failed três, a 450 ms
o áudio reproduz o ritmo · não o atuador vibraçã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ática completed · 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 real o 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 confundidos quinze primitivas, ouvidas em sequência · 4 dos 105 pares soaram próximos
muito próximos próximos próximos muito sutis sharp_collision sharp_state_change knock damp_collision mad ringing subtle_collision completed jingle damp_state_change firework happy_alert wave angry_alert square nenhuma colisão reportada aqui
Progress indicator — 8 de 15 Precision enhancer — 4 Incoming event — 3
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.
// 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 desenhado preenchido é feito · vazado é devido
completed vs failed, às cegas — 20/20 três rodadas · Subtle incluída · uma mão
previsões, datadas de antemão — 12 dois estudos desenhados · nenhum executado
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.

// 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 mesmos fricção observada → decisão tomada, no nosso próprio plugin
o log 39 linhas, observadas à vista de todos
o nosso manifesto decisões 37–40 — corrigidas aqui primeiro
o Marketplace submetido — a rota de instalação que funciona
outras mãos o 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ão uma página de loja também é uma superfície
Variante de ícone V1 — a barra transversal carrega o ritmo V1 · a barra é o ritmo cortada — agora uma linha do registro
Variante de ícone V2 — um pulso atravessando a haste V2 · pulso atravessando a haste cortada — agora uma linha do registro
Variante de ícone V3 — um T sobre três pontos, a escolhida V3 · a contagem sob a marca a escolhida — um T sobre três pontos
O ícone do Tacit publicado, no tamanho da loja publicado a 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.
// 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 polegar cada estação é um arquivo real · escolha um estado
  1. um escritor t7 startedt7 progresst7 needsInputt7 completedt7 failed uma linha acrescentada ao canal — sem SDK, sem C#, sem projeto de plugin
  2. camada semântica · events/DefaultEventSource.yaml - name: taskStarted- name: taskTick- name: taskNeedsInput- name: taskCompleted- name: taskFailed cinco nomes — nossos, não da plataforma
  3. camada de mapeamento · events/extra/eventMapping.yaml taskStarted: { 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
  4. primitiva · uma de quinze sharp_state_changesubtle_collisionknockcompletedangry_alert conjunto fixo — seleção, nunca síntese
  5. 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
  6. o polegar uma 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 inferida o á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.

// 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.