Skip to content

docs: plano e decisões do Project Wiki desktop - #1

Merged
protonspy merged 1 commit into
mainfrom
docs/project-wiki-plan
Jul 31, 2026
Merged

docs: plano e decisões do Project Wiki desktop#1
protonspy merged 1 commit into
mainfrom
docs/project-wiki-plan

Conversation

@protonspy

@protonspy protonspy commented Jul 31, 2026

Copy link
Copy Markdown
Owner

O que muda

Registra o produto e as decisões que o definem. É tudo documentação — nenhuma linha de código.

O produto. Um aplicativo desktop (Windows, Apache-2.0) que centraliza as fontes de documentação de um projeto numa pasta local e serve essa pasta por MCP como uma wiki que o agente de IA lê e escreve.

A decisão que define o resto: o aplicativo não chama LLM. Ele recebe fontes — arquivo subido ou gravação de reunião —, reduz cada uma a text.md com âncoras de proveniência, guarda a wiki e serve um projeto por vez pelo servidor MCP. Quem lê o texto, aplica a metodologia LLM-Wiki e escreve as páginas é o agente do usuário, no harness que ele já tem aberto.

Como não há versionamento nem recompilação para onde recuar, a defesa fica na entrada: toda escrita — do editor ou do MCP — é validada contra o schema, os wikilinks e as citações antes de tocar o disco. O aplicativo não garante que a página seja boa; garante que seja bem formada.

Arquivos

Arquivo O que é
plans/project-wiki.md O plano: 10 grupos de tarefas, cada uma com (Unit) ou (TDD)
docs/adr/00010007 As sete decisões caras de desfazer
docs/glossary.md Termos canônicos e sinônimos a evitar
docs/stack.md Tecnologia adotada, com a razão de cada uma

As ADRs: sem backend (0001) · workspace como pasta local sem versionamento (0002) · MCP como única ponte com o LLM (0003) · edição de markdown sem blocos (0004) · captura WASAPI num sidecar mínimo (0005) · Opus como formato de proveniência (0006) · credenciais em texto claro no config (0007).

Como foi verificado

Não há suíte de testes nem lint para rodar — o repositório ainda não tem código, e montar o monorepo é a tarefa 1.1 do próprio plano.

scc validate não foi executado: o manifesto registra scc v0.0.1, mas o binário não está instalado na máquina. As verificações que o scc faria foram feitas à mão:

  • toda citação adr: resolve para um arquivo existente;
  • as ADRs são numeradas contiguamente de 0001 a 0007, todas accepted, todas alcançadas por pelo menos um arquivo;
  • nenhum sinônimo marcado como Avoid: no glossário aparece em docs/ ou plans/;
  • toda tarefa do plano carrega exatamente um (Unit) ou (TDD).

code-review e security-review não foram executados: esta sessão não despacha subagentes. Como o diff é só prosa, a revisão que importa é humana — e é o que este PR pede.

Fora deste PR

O .gitignore continua ignorando .claude/ e CLAUDE.md, então a metodologia não está versionada. Corrigir isso é a tarefa 1.4 do plano, e ficou de fora porque a modificação pendente no .gitignore não é deste trabalho.

🤖 Generated with Claude Code

https://claude.ai/code/session_0184CMSxPj8FbBMF1ExbZ4LU

Summary by CodeRabbit

  • Documentation
    • Added architectural decisions covering local workspaces, Markdown editing, audio capture, transcription formats, credentials, and MCP integration.
    • Documented the planned Windows desktop application, technology stack, processing workflow, and project milestones.
    • Added a glossary defining standard project terminology and concepts.

Registra o produto: um aplicativo desktop que centraliza as fontes de
documentação de um projeto numa pasta local e serve essa pasta por MCP
como uma wiki que o agente de IA lê e escreve.

A decisão que define o resto é que o aplicativo não chama LLM. Ele
recebe fontes (arquivo ou gravação), reduz cada uma a texto com âncoras
de proveniência, guarda a wiki e serve um projeto por vez pelo servidor
MCP. Quem lê o texto e escreve as páginas é o agente do usuário.

Como não há versionamento nem recompilação para onde recuar, a defesa
fica na entrada: toda escrita — do editor ou do MCP — é validada contra
o schema, os wikilinks e as citações antes de tocar o disco.

- plans/project-wiki.md — 10 grupos de tarefas, cada uma com Unit ou TDD
- docs/adr/0001-0007 — as sete decisões caras de desfazer
- docs/glossary.md — termos canônicos e sinônimos a evitar
- docs/stack.md — tecnologia adotada, com a razão de cada uma

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0184CMSxPj8FbBMF1ExbZ4LU
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A documentação registra decisões para um aplicativo Windows local com workspace Markdown, integração exclusiva por MCP, captura WASAPI em sidecar Rust, proveniência em Opus, credenciais locais, stack técnica e plano de implementação.

Changes

Arquitetura documentada

Layer / File(s) Summary
Workspace local e edição Markdown
docs/adr/0002-workspace-como-pasta-local-de-markdown.md, docs/adr/0004-edicao-de-markdown-sem-blocos.md, docs/glossary.md
Define o workspace local, a separação entre raw/ e wiki/, as escritas atômicas, o undo por operação e a edição Markdown com correção de wikilinks.
Fronteira MCP e credenciais
docs/adr/0001-sem-backend-byok.md, docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md, docs/adr/0007-credenciais-em-texto-claro-no-config.md
Define o fluxo BYOK, o MCP como única ponte com o LLM, a autenticação obrigatória, o isolamento por projeto e o armazenamento local de credenciais.
Captura e proveniência de áudio
docs/adr/0005-captura-wasapi-num-sidecar-minimo.md, docs/adr/0006-opus-como-formato-de-proveniencia.md
Define a captura WASAPI em sidecar Rust, o contrato JSON-RPC mínimo e o uso de Opus como formato permanente em raw/.
Stack e plano de implementação
docs/stack.md, plans/project-wiki.md
Consolida as tecnologias, os marcos de implementação, o escopo, os requisitos de integridade e os riscos arquiteturais documentados.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed O título resume com clareza o plano e as decisões documentadas para o Project Wiki desktop.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/project-wiki-plan

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/0001-sem-backend-byok.md`:
- Around line 27-31: Substitua o trecho sobre LGPD e a classificação jurídica
por uma descrição técnica do fluxo: o aplicativo envia áudio e documentos
diretamente ao provedor de transcrição, sem backend, armazenamento ou telemetria
próprios. Remova conclusões sobre os papéis de controlador ou operador e
registre que uma validação jurídica específica é necessária antes de publicar
qualquer conclusão sobre a LGPD.

In `@docs/adr/0002-workspace-como-pasta-local-de-markdown.md`:
- Around line 27-32: Atualize o ADR para definir uma operação durável que agrupe
snapshots, alterações de páginas, correções de wikilinks e logs em um journal
com estados de commit e recuperação após falhas. No fluxo de desfazer, restrinja
a operação ao topo da pilha (LIFO) ou exija precondições/versionamento por
página, mantendo a promessa documentada consistente com essa regra.

In `@docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md`:
- Line 39: Atualize o inventário de credenciais neste ADR para afirmar que a
credencial de transcrição é a única credencial de provedor e listar
separadamente o token local do MCP como segredo armazenado pelo aplicativo,
mantendo alinhamento com o ADR-0007.
- Around line 27-31: Atualize a decisão arquitetural para vincular cada sessão
MCP ao projeto ativo, impedindo que conexões antigas continuem válidas após a
troca de projeto. Defina o dreno ou cancelamento das requisições em andamento e
a rejeição de sessões antigas por época de projeto ou handshake;
alternativamente, documente a rotação do token na troca. Mantenha explícito que
o agente não escolhe o projeto.

In `@docs/adr/0004-edicao-de-markdown-sem-blocos.md`:
- Around line 25-27: Atualize o ADR para delimitar explicitamente a garantia de
validação às escritas realizadas pelo editor e pelo MCP, ou documente detecção,
quarentena e comportamento para arquivos externos inválidos. Ajuste as
declarações sobre o arquivo Markdown continuar editável externamente para não
sugerir que essas alterações são validadas silenciosamente.

In `@docs/adr/0006-opus-como-formato-de-proveniencia.md`:
- Around line 43-46: Atualize o ADR `0006-opus-como-formato-de-proveniencia`
para definir que retranscrições de uma `source` imutável sejam armazenadas como
versões ou artefatos de transcript separados, sem sobrescrever `text.md` em
`raw/`. Especifique também que as citações associadas às versões antigas
permaneçam resolvíveis, preservando o texto que fundamentou claims existentes.
- Around line 25-31: Atualize o ADR para separar o formato permanente `.opus` em
`raw/` do formato enviado ao provedor STT. Documente que cada adaptador de
`SttProvider` deve converter ou reempacotar os chunks antes do upload,
preservando o offset original; inclua cobertura para MIME type, nome do arquivo
e mapeamento correspondente em `timemap.json`.

In `@docs/adr/0007-credenciais-em-texto-claro-no-config.md`:
- Around line 26-31: Atualize o exemplo de configuração no ADR para não
apresentar mcp.token vazio como valor válido; use um placeholder explicitamente
não utilizável. No fluxo de inicialização do servidor MCP, gere um token não
vazio antes de iniciar e rejeite configurações com token ausente ou vazio.

In `@docs/glossary.md`:
- Line 20: Expand the “provenance link” glossary entry to define a consistent
citation syntax and resolution behavior for every supported source type: audio,
PDF, Markdown, plain text, and DOCX. Specify the required location anchor for
each type, including headings for Markdown and text offsets, so validators, UI,
and MCP tools share the same contract.
- Line 11: Atualize a definição de “recording” no glossário para separar o
identificador lógico do nome de diretório: mantenha `recording_id` em ISO-8601
no `manifest.json` e defina `recording_dir` com uma forma segura para
filesystem, ou estabeleça explicitamente a codificação com hífens como
identificador canônico. Aplique a mesma convenção em citações, buscas e
restauração.

In `@docs/stack.md`:
- Line 21: Atualize a entrada de benchmark do Groq para whisper-large-v3-turbo
em docs/stack.md, substituindo o valor de ~228x por uma medição datada ou pelo
valor atualmente documentado de aproximadamente 216x tempo real. Preserve as
demais informações da descrição.
- Around line 26-30: Documente, em docs/stack.md, o contrato de segurança do
renderer: trate Markdown via MCP e saídas de plugins markdown-it como não
confiáveis; desative HTML bruto, aplique sanitização e allowlist de esquemas de
URL, e defina CSP. Registre a configuração contextIsolation: true, sandbox: true
e nodeIntegration: false, além das APIs mínimas expostas por contextBridge e das
allowlists para navegação e abertura externa.
- Around line 19-20: Antes de publicar o instalador, documente a licença e a
configuração redistribuível do FFmpeg vendorizado na seção correspondente de
docs/stack.md, incluindo versão, flags de build, fonte correspondente, textos de
licença e notices. Esclareça separadamente que a licença Apache-2.0 cobre apenas
o aplicativo e registre o impacto de --enable-gpl e --enable-nonfree na
redistribuição.

In `@plans/project-wiki.md`:
- Around line 113-118: Atualize o fluxo de transcrição paralela descrito em 4.9
para definir timeout por chunk, número máximo de tentativas, backoff entre
tentativas e cancelamento quando o processamento for encerrado ou exceder o
limite. Adote um identificador estável para cada chunk e tentativa, garantindo
deduplicação e evitando resultados divergentes de reprocessamentos.
- Around line 63-74: Atualize a árvore de artefatos em plans/project-wiki.md
para incluir timemap.json entre os arquivos persistidos e imutáveis de cada
gravação, e documente explicitamente no contrato onde device_changes é
armazenado, preferencialmente no manifest.json se esse for o formato existente.
Mantenha a distinção entre artefatos raw imutáveis e conteúdo derivado da wiki.
- Around line 125-134: Modele a operação de escrita como uma transação composta,
gerando um único identificador e mantendo o conjunto completo de arquivos
afetados, incluindo a página, log.md e changelog.md. Atualize o item 5.5 para
exigir que esses registros compartilhem o mesmo id e origem, e defina uma
proteção explícita para que as escritas internas dos logs não disparem novo
logging recursivo nem duplicado.
- Around line 119-120: Atualize os itens 4.12 e 4.13 do plano para substituir os
rótulos `me` e `remote` por `mic` e `system`, deixando claro que representam
canais/faixas de origem e não identidades de locutores; preserve a ausência de
diarização por ML.
- Line 96: Estenda o item 2.6 para exigir confinamento baseado em handles e no
caminho final resolvido, cobrindo não apenas symlinks, mas também junctions e
volume mount points que escapem do projeto servido. Inclua testes para symlinks
relativos e absolutos, renomeação do diretório pai durante a operação e
diferenças de maiúsculas e minúsculas, sem depender somente de normalização
textual.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b20f073-e23e-4cf1-aa7f-4163074e7b07

📥 Commits

Reviewing files that changed from the base of the PR and between 5cbbac1 and 458a8c6.

📒 Files selected for processing (10)
  • docs/adr/0001-sem-backend-byok.md
  • docs/adr/0002-workspace-como-pasta-local-de-markdown.md
  • docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md
  • docs/adr/0004-edicao-de-markdown-sem-blocos.md
  • docs/adr/0005-captura-wasapi-num-sidecar-minimo.md
  • docs/adr/0006-opus-como-formato-de-proveniencia.md
  • docs/adr/0007-credenciais-em-texto-claro-no-config.md
  • docs/glossary.md
  • docs/stack.md
  • plans/project-wiki.md

Comment on lines +27 to +31
O áudio e os documentos nunca passam por servidor nosso, o que nos deixa na posição de
fornecedor de software e não de operador de dados. Isso simplifica bastante a posição em
relação à LGPD — e deixa de valer no instante em que qualquer componente hospedado for
adicionado. É por isso que isto é um ADR e não uma linha de README: o custo não é
adicionar o componente, é perder a posição.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu
file="$(fd -i -t f '0001-sem-backend-byok\.md$' . | head -n 1)"
printf '%s\n' "$file"
cat -n "$file" | sed -n '1,90p'
printf '%s\n' '--- LGPD/ANPD references in repository ---'
rg -n -i 'LGPD|ANPD|controlador|operador|dados pessoais|backend|servidor' --glob '!node_modules' --glob '!dist' --glob '!build' .

Repository: protonspy/open-wiki

Length of output: 6527


🌐 Web query:

site:gov.br/anpd Guia agentes de tratamento controlador operador ações função tratamento dados pessoais ausência backend fornecedor software LGPD

💡 Result:

De acordo com a Lei Geral de Proteção de Dados Pessoais (LGPD) e o Guia Orientativo da Autoridade Nacional de Proteção de Dados (ANPD), a distinção entre controlador e operador é baseada no poder de decisão sobre o tratamento dos dados [1][2]. O controlador é a pessoa natural ou jurídica a quem competem as decisões referentes ao tratamento de dados pessoais (finalidade, duração, natureza do dado) [2][3]. O operador, por sua vez, realiza o tratamento de dados pessoais em nome do controlador, seguindo estritamente as suas instruções e os limites das finalidades estabelecidas [2][3][4]. No contexto de uma relação entre uma empresa (cliente/usuário) e um fornecedor de software (que provê, por exemplo, o backend de uma aplicação), a definição de cada papel depende da análise concreta da autonomia de cada parte: 1. Fornecedor de Software (Operador): Geralmente atua como operador quando provê a infraestrutura (backend) e realiza o tratamento de dados (como armazenamento ou processamento) apenas em nome e conforme as instruções do cliente [3][4]. É legítimo que, nesta condição, o operador tenha autonomia técnica para decidir sobre elementos não essenciais, como a escolha de linguagens de programação, ferramentas de banco de dados ou medidas específicas de segurança para a execução do serviço, desde que respeite as diretrizes do controlador [4]. 2. Cliente/Usuário (Controlador): É o controlador quando detém a prerrogativa decisória sobre a finalidade, os tipos de dados coletados e a duração do tratamento [3][4]. Mesmo que o fornecedor de software gerencie a tecnologia, se o cliente é quem define o "porquê" e o "o quê" do tratamento, ele mantém a posição de controlador [3]. Responsabilidade: Embora as obrigações sejam distintas, a LGPD estabelece que ambos possuem responsabilidade em caso de danos causados pelo tratamento irregular, se violarem a legislação ou descumprirem instruções [2][5]. O operador deve atuar estritamente dentro do escopo definido pelo contrato ou ordens do controlador [3][4]. A responsabilidade solidária pode ser aplicada se o operador descumprir obrigações legais ou instruções legítimas do controlador [5]. Para consolidar essas posições, é recomendável documentar claramente os papéis em contrato, incluindo as instruções de tratamento e as salvaguardas de segurança, evitando que o fornecedor tome decisões sobre a finalidade ou o uso dos dados que excedam o seu papel de suporte técnico [3][4].

Citations:


Registre o fluxo de dados sem concluir o papel jurídico.

Substitua as linhas 27–31 por uma decisão técnica: o aplicativo envia os dados diretamente ao provedor de transcrição, sem backend, armazenamento ou telemetria nossos. A arquitetura, por si só, não define os papéis de controlador e operador. Registre validação jurídica específica antes de publicar qualquer conclusão sobre a LGPD.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0001-sem-backend-byok.md` around lines 27 - 31, Substitua o trecho
sobre LGPD e a classificação jurídica por uma descrição técnica do fluxo: o
aplicativo envia áudio e documentos diretamente ao provedor de transcrição, sem
backend, armazenamento ou telemetria próprios. Remova conclusões sobre os papéis
de controlador ou operador e registre que uma validação jurídica específica é
necessária antes de publicar qualquer conclusão sobre a LGPD.

Comment on lines +27 to +32
- **Toda escrita é atômica** — arquivo temporário e renomeação — para que um aplicativo
fechado no meio não deixe página pela metade.
- **Toda escrita tira snapshot antes** das páginas que vai tocar, numa pasta `.state/`
que não é conteúdo.
- **Toda escrita entra num log de operações** com origem e horário, e qualquer operação
pode ser desfeita pelo seu id.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Defina uma operação durável para escrita e desfazer.

arquivo temporário + renomeação protege um arquivo, não o conjunto formado por snapshots, páginas renomeadas, correções de wikilinks e logs. Uma falha entre essas etapas pode deixar .state/ divergente. Desfazer um id antigo também pode apagar alterações posteriores, embora o texto prometa desfazer qualquer operação e depois limite o retorno à última operação.

Defina um journal com estados de commit e recuperação. Restrinja o desfazer a operações LIFO ou use precondições/versionamento por página.

Also applies to: 49-50

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0002-workspace-como-pasta-local-de-markdown.md` around lines 27 -
32, Atualize o ADR para definir uma operação durável que agrupe snapshots,
alterações de páginas, correções de wikilinks e logs em um journal com estados
de commit e recuperação após falhas. No fluxo de desfazer, restrinja a operação
ao topo da pilha (LIFO) ou exija precondições/versionamento por página, mantendo
a promessa documentada consistente com essa regra.

Comment on lines +27 to +31
O servidor MCP expõe leitura, busca, ingestão e escrita. Ele roda por HTTP no loopback,
é ligado e desligado pelo aplicativo, e **serve exatamente um projeto por vez, escolhido
pelo aplicativo** — nenhuma ferramenta aceita parâmetro de projeto, e o endereço não muda
quando o projeto muda. Quem decide qual base o agente alcança é o aplicativo, nunca o
agente.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

rg -n -C 8 "serve exatamente um projeto|token|projeto ativo|credencial|workspace|MCP" docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md

Repository: protonspy/open-wiki

Length of output: 3814


🏁 Script executed:

fd -t f . | sort | sed -n '1,240p'
printf '\n--- references to MCP, loopback, token, project switching ---\n'
rg -n -i -C 3 "MCP|loopback|127\.0\.0\.1|localhost|token|bearer|workspace|projeto.*(troca|ativo)|troca.*projeto|credencial" --glob '!docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md' .

Repository: protonspy/open-wiki

Length of output: 32911


🏁 Script executed:

printf '%s\n' '--- ADR 0007 ---'
cat -n docs/adr/0007-credenciais-em-texto-claro-no-config.md
printf '%s\n' '--- plan section 9 and security consequences ---'
sed -n '165,190p;210,246p' plans/project-wiki.md
printf '%s\n' '--- ADR 0003 consequences ---'
sed -n '60,76p' docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md

Repository: protonspy/open-wiki

Length of output: 8259


🏁 Script executed:

python3 - <<'PY'
from dataclasses import dataclass

`@dataclass`
class Server:
    active_project: str
    token: str
    connections: dict
    requests: dict

    def switch_project(self, project):
        # This is the behavior specified by plan item 9.5:
        # close connections, but retain the workspace token.
        self.connections.clear()
        self.active_project = project

    def reconnect(self, client, token):
        if token == self.token:
            self.connections[client] = self.active_project
            return True
        return False

    def start_request(self, client):
        self.requests[client] = self.connections[client]

    def finish_request(self, client):
        return self.active_project, self.requests.pop(client)

server = Server("project-a", "workspace-token", {}, {})
server.reconnect("harness", "workspace-token")
server.start_request("harness")
server.switch_project("project-b")
reconnected = server.reconnect("harness", "workspace-token")
completed_against = server.finish_request("harness")

print({
    "persistent_token_reconnects": reconnected,
    "request_project_at_start": completed_against[1],
    "active_project_at_completion": completed_against[0],
    "cross_project_request_possible": completed_against[1] != completed_against[0],
})
PY

Repository: protonspy/open-wiki

Length of output: 321


🏁 Script executed:

python3 - <<'PY'
from dataclasses import dataclass

`@dataclass`
class Server:
    active_project: str
    token: str
    connections: dict
    requests: dict

    def switch_project(self, project):
        self.connections.clear()
        self.active_project = project

    def reconnect(self, client, token):
        if token == self.token:
            self.connections[client] = self.active_project
            return True
        return False

    def start_request(self, client):
        self.requests[client] = self.connections[client]

    def finish_request(self, client):
        return self.active_project, self.requests.pop(client)

server = Server("project-a", "workspace-token", {}, {})
server.reconnect("harness", "workspace-token")
server.start_request("harness")
server.switch_project("project-b")
reconnected = server.reconnect("harness", "workspace-token")
completed_against = server.finish_request("harness")

print({
    "persistent_token_reconnects": reconnected,
    "request_project_at_start": completed_against[1],
    "active_project_at_completion": completed_against[0],
    "cross_project_request_possible": completed_against[1] != completed_against[0],
})
PY

Repository: protonspy/open-wiki

Length of output: 321


Vincule cada sessão MCP ao projeto ativo.

Como o token é persistente e pertence ao workspace, derrubar conexões não impede que um harness se reconecte ao mesmo endereço após a troca. Drene ou cancele requisições em andamento e rejeite sessões antigas com uma época de projeto ou handshake. Como alternativa, faça rotação do token na troca.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md` around lines 27 - 31,
Atualize a decisão arquitetural para vincular cada sessão MCP ao projeto ativo,
impedindo que conexões antigas continuem válidas após a troca de projeto. Defina
o dreno ou cancelamento das requisições em andamento e a rejeição de sessões
antigas por época de projeto ou handshake; alternativamente, documente a rotação
do token na troca. Mantenha explícito que o agente não escolhe o projeto.

aplicativo não garante que a página seja boa; garante que seja bem formada, e devolve um
erro que o agente consiga ler para tentar de novo.

A única credencial que o aplicativo guarda é a de transcrição.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Corrija o inventário de credenciais.

Este ADR diz que o aplicativo guarda apenas a credencial de transcrição. docs/adr/0007-credenciais-em-texto-claro-no-config.md também armazena o token local do MCP.

Use “única credencial de provedor” e liste o token MCP como segredo local separado. Isso evita omissões em rotação, diagnóstico e exclusão de segredos.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md` at line 39, Atualize o
inventário de credenciais neste ADR para afirmar que a credencial de transcrição
é a única credencial de provedor e listar separadamente o token local do MCP
como segredo armazenado pelo aplicativo, mantendo alinhamento com o ADR-0007.

Comment on lines +25 to +27
Sem blocos arrastáveis, sem slash-commands, sem embeds, sem modelo de documento próprio.
O arquivo `.md` é a verdade, e continua editável por fora do aplicativo enquanto ele está
aberto.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Reconcilie edição externa com a garantia de validação.

Obsidian e VS Code podem gravar enquanto o aplicativo está aberto. O texto só define validação para escritas do editor e do MCP. Uma edição externa pode chegar ao disco antes da validação de schema, wikilinks e citações.

Restrinja a garantia às escritas pelo aplicativo e pelo MCP, ou defina detecção, quarentena e comportamento para arquivos externos inválidos. Não trate a edição externa como validada silenciosamente.

Also applies to: 41-44

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0004-edicao-de-markdown-sem-blocos.md` around lines 25 - 27,
Atualize o ADR para delimitar explicitamente a garantia de validação às escritas
realizadas pelo editor e pelo MCP, ou documente detecção, quarentena e
comportamento para arquivos externos inválidos. Ajuste as declarações sobre o
arquivo Markdown continuar editável externamente para não sugerir que essas
alterações são validadas silenciosamente.

Comment thread plans/project-wiki.md
Comment on lines +63 to +74
<workspace>/
fenix/ um projeto
raw/ fontes, imutáveis depois de escritas
2026-07-31T14-02-11Z/ uma gravação
manifest.json · mic.opus · system.opus · timeline.json · text.md
arquitetura-fenix.pdf/ um arquivo subido
source.pdf · text.md
wiki/ conteúdo primário, escrito pelo agente e pelo usuário
index.md · changelog.md · log.md
projects/*.md · people/*.md · topics/*.md
.state/ snapshots e log de operações; não é conteúdo
CLAUDE.md schema e metodologia, para o agente que opera a pasta

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Complete o contrato de artefatos de uma gravação.

As tarefas exigem timemap.json e registram device_changes, mas a árvore do workspace lista apenas manifest.json e timeline.json. Defina se device_changes fica no manifest e inclua timemap.json entre os artefatos persistidos e imutáveis. Sem isso, reinício e retranscrição podem perder a reconstrução de proveniência.

Also applies to: 108-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/project-wiki.md` around lines 63 - 74, Atualize a árvore de artefatos
em plans/project-wiki.md para incluir timemap.json entre os arquivos persistidos
e imutáveis de cada gravação, e documente explicitamente no contrato onde
device_changes é armazenado, preferencialmente no manifest.json se esse for o
formato existente. Mantenha a distinção entre artefatos raw imutáveis e conteúdo
derivado da wiki.

Comment thread plans/project-wiki.md
- [ ] 2.3 (TDD) Gravar página atomicamente — temporário mais renomeação — tirando snapshot em `.state/` das páginas tocadas antes de qualquer escrita
- [ ] 2.4 (TDD) Registrar toda operação de escrita num log em `.state/`, com origem (editor, MCP), páginas afetadas e horário
- [ ] 2.5 (TDD) Desfazer uma operação pelo seu id, restaurando o snapshot e removendo o que ela criou
- [ ] 2.6 (TDD) Recusar escrita que resolva para fora do projeto servido, inclusive por caminho relativo ou link simbólico

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

fd -i 'project-wiki.md' . && sed -n '80,110p' "$(fd -i -t f 'project-wiki.md' . | head -n 1)" && printf '\n--- related terms ---\n' && rg -n -i 'symlink|junction|reparse|mount point|canonical|MCP|escrita|write' . --glob '!node_modules' --glob '!dist' --glob '!build' | head -n 200

Repository: protonspy/open-wiki

Length of output: 11628


🏁 Script executed:

sed -n '1,90p' docs/adr/0002-workspace-como-pasta-local-de-markdown.md
printf '\n--- ADR 0003 ---\n'
sed -n '20,80p' docs/adr/0003-mcp-como-unica-ponte-com-o-llm.md
printf '\n--- repository implementation files ---\n'
git ls-files | rg -i '(^|/)(src|apps|packages|crates)/|package.json|Cargo.toml' | head -n 200

Repository: protonspy/open-wiki

Length of output: 5874


🌐 Web query:

Microsoft Windows reparse points name surrogate symbolic link junction mount point GetFinalPathNameByHandle documentation

💡 Result:

Reparse points are file system objects in Windows (specifically NTFS and ReFS) that contain user-defined data, allowing developers to extend file system behavior [1][2][3]. Each reparse point is associated with a unique reparse tag that identifies the owner of the data and dictates how the system processes the file [4][1]. Name Surrogate A reparse point is classified as a name surrogate if its reparse tag has the name surrogate bit set [4][5]. This indicates that the file or directory acts as a substitute for another named entity in the system, such as a volume mount point or a symbolic link [5]. Applications can use the IsReparseTagNameSurrogate macro to programmatically determine if a reparse point tag signifies such a surrogate [5]. Symbolic Links and Junctions/Mount Points Symbolic links and directory junctions (which use the mount point reparse tag) are both common examples of name surrogate reparse points [3]: - Symbolic Links (IO_REPARSE_TAG_SYMLINK): Introduced in Windows Vista, these are resolved on the client side and can point to files or directories, supporting both absolute and relative paths [3]. - Junctions/Mount Points (IO_REPARSE_TAG_MOUNT_POINT): These are used for volume mount points and directory junctions. They map a directory to a path on another volume or subdirectory [6][3]. Unlike symbolic links, they must point to directories [3]. Data Structures Microsoft uses the REPARSE_DATA_BUFFER structure (or REPARSE_GUID_DATA_BUFFER for third-party tags) to store the data within a reparse point [7]. This buffer contains the substitute name (the actual target path) and the print name (a user-friendly path for display) [8][6][7]. GetFinalPathNameByHandle The GetFinalPathNameByHandle function retrieves the fully resolved final path of a file [9][10]. When applied to a reparse point, it returns the path to the ultimate target rather than the reparse point itself [9][10]. To interact with the reparse point's internal data directly (e.g., to read the link target without resolving it), developers typically use DeviceIoControl with the FSCTL_GET_REPARSE_POINT control code while opening the file handle with the FILE_FLAG_OPEN_REPARSE_POINT flag [11][12][13].

Citations:


Estenda o confinamento aos reparse points que alteram a resolução.

Junctions e volume mount points, além de symlinks, podem resolver para fora do projeto servido. Valide a operação com handles e o caminho final resolvido, sem depender apenas de normalização textual. Cubra symlinks relativos e absolutos, junctions, volume mount points, renomeação do diretório pai durante a operação e diferenças de maiúsculas e minúsculas.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/project-wiki.md` at line 96, Estenda o item 2.6 para exigir
confinamento baseado em handles e no caminho final resolvido, cobrindo não
apenas symlinks, mas também junctions e volume mount points que escapem do
projeto servido. Inclua testes para symlinks relativos e absolutos, renomeação
do diretório pai durante a operação e diferenças de maiúsculas e minúsculas, sem
depender somente de normalização textual.

Comment thread plans/project-wiki.md
Comment on lines +113 to +118
- [ ] 4.6 (Unit) ffmpeg: downmix para 16 kHz mono, VAD cortando silêncio a partir de 800 ms, encode em Opus 24 kbps
- [ ] 4.7 (TDD) Emitir o mapa de tempo que converte instante comprimido em instante real, e as fronteiras de chunk em pontos de silêncio
- [ ] 4.8 (Unit) Interface `SttProvider` com os adaptadores `groq` e `whispercpp`, trocáveis por configuração
- [ ] 4.9 (Unit) Transcrever chunks em paralelo, isolando falha e refazendo só o chunk que falhou
- [ ] 4.10 (Unit) Preencher o vocabulário da transcrição com os nomes já presentes nas páginas do projeto — é o que impede o nome do projeto de sair errado
- [ ] 4.11 (TDD) Reconstruir os timestamps absolutos a partir do offset do chunk e do mapa de tempo

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Limite o fluxo de transcrição dos chunks.

A execução paralela com retry não define timeout, limite de tentativas, backoff, cancelamento ou deduplicação por chunk. Uma chamada presa pode bloquear a conclusão. Tentativas repetidas podem gerar resultados divergentes.

Defina uma política limitada e um identificador estável de chunk e tentativa.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/project-wiki.md` around lines 113 - 118, Atualize o fluxo de
transcrição paralela descrito em 4.9 para definir timeout por chunk, número
máximo de tentativas, backoff entre tentativas e cancelamento quando o
processamento for encerrado ou exceder o limite. Adote um identificador estável
para cada chunk e tentativa, garantindo deduplicação e evitando resultados
divergentes de reprocessamentos.

Comment thread plans/project-wiki.md
Comment on lines +119 to +120
- [ ] 4.12 (Unit) Fundir as duas faixas em `timeline.json` ordenada por tempo real, rotulando `me` e `remote` pela faixa de origem
- [ ] 4.13 (Unit) Renderizar o `text.md` da gravação a partir da timeline, com o instante de cada trecho como âncora de proveniência

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Não trate me e remote como atribuição de locutor.

O plano exclui diarização por ML, mas rotula a timeline como me e remote apenas pela faixa. A faixa system pode conter vários participantes remotos ou outros sons. Use mic e system, ou documente explicitamente que os rótulos representam canais, não identidades.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/project-wiki.md` around lines 119 - 120, Atualize os itens 4.12 e 4.13
do plano para substituir os rótulos `me` e `remote` por `mic` e `system`,
deixando claro que representam canais/faixas de origem e não identidades de
locutores; preserve a ausência de diarização por ML.

Comment thread plans/project-wiki.md
Comment on lines +125 to +134
O que substitui o código que escrevia as páginas: o app não garante que o conteúdo seja
bom, garante que ele seja **bem formado**. Toda escrita — do editor ou do MCP — passa por
aqui.

- [ ] 5.1 (TDD) Validar o frontmatter da página contra o schema (`id`, `type`, `title`, `status`, `aliases`, `updated`, `sources`) e recusar a escrita com o motivo, em vez de gravar torto
- [ ] 5.2 (TDD) Recusar escrita cujo wikilink não resolva para página existente, dizendo qual link quebrou
- [ ] 5.3 (TDD) Recusar escrita cuja citação de proveniência não aponte para fonte existente e, no caso de áudio, para instante dentro da gravação
- [ ] 5.4 (Unit) Preencher `updated` e acrescentar a fonte em `sources` automaticamente, para que isso não dependa de o agente lembrar
- [ ] 5.5 (Unit) Acrescentar uma linha em `log.md` e a entrada em `changelog.md` a cada operação de escrita, com a origem
- [ ] 5.6 (Unit) Manter o índice: registrar página nova em `index.md` e apontar página que ficou inalcançável

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Modele os logs como parte de uma operação composta.

log.md e changelog.md ficam em wiki/, mas a tarefa exige gravar neles a cada operação de escrita. Como toda escrita também deve ser registrada, uma implementação literal pode gerar recursão, duplicidade ou ids diferentes para uma única operação.

Defina um único id de operação, o conjunto completo de arquivos afetados e uma regra explícita para impedir logging recursivo.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plans/project-wiki.md` around lines 125 - 134, Modele a operação de escrita
como uma transação composta, gerando um único identificador e mantendo o
conjunto completo de arquivos afetados, incluindo a página, log.md e
changelog.md. Atualize o item 5.5 para exigir que esses registros compartilhem o
mesmo id e origem, e defina uma proteção explícita para que as escritas internas
dos logs não disparem novo logging recursivo nem duplicado.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant