Doc touch
Skill pedroberaldo87/pedro-plugins/plugins/project-doc/skills/doc-touch
Atualização INCREMENTAL da documentação project-doc — mapeia o diff do trabalho recente pros docs afetados (via scope inverso) e re-projeta SÓ eles, sem re-mineração completa. Use quando o usuário diz "/doc-touch", "atualiza a doc do que eu mexi", "toca a doc", "atualiza a documentação disso que fizemos", ou após um ciclo de código quando a doc dos arquivos tocados precisa acompanhar. NÃO substitui o /project-doc FULL (mineração completa) — é o complemento frequente entre FULLs.From its SKILL.md
npx -y skills add pedroberaldo87/pedro-plugins --skill doc-touchAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
10.7 KB, ~3.1k tokens by cl100k_base, as published. Nobody here has run it
doc-touch — atualização incremental da doc
Irmã do /project-doc (mesmo plugin, mesma estrutura de doc, mesmos invariantes). O FULL minera tudo e re-projeta tudo; o touch atualiza só os docs cujo scope: intersecta o diff do trabalho recente. Mexeu → tocou a doc. O FULL vira evento raro.
Fluxo (5 passos)
1 · Grafo fresco + plano determinístico
graphify update "<root>" --force # AST, ZERO LLM, segundos, idempotente. Ausente → cria; fresco → no-op.
python3 plugins/project-doc/lib/pattern_check.py --project-root "<root>" --touch-plan --json
O touch documenta ⇒ é modo PESADO na regra do grafo (canônica: skills/project-doc/SKILL.md → Workflow Engine → Passo 0): doc nova nunca sai de grafo velho. Rode sem anunciar custo nem pedir confirmação — só informe o status. graphify não instalado ⇒ avise e siga (a re-projeção vem do diff, não do mapa; o touch não consome graph_map).
Devolve {changed, docs:{doc:{files, already_current}}, pending_docs, seam_review, unscoped_new, dead_scope, ledger_last_commit, last_full_age_days}. O changed = working tree ∪ staged ∪ ledger.last_commit..HEAD (mesma janela do backward-delta do journal, lida read-only). ⚠️ git diff não lista untracked — arquivo novo só entra no changed depois do git add.
Escalada touch → FULL: decida AQUI, antes de re-projetar nada. Quem chama o touch (o usuário, ou a /sovai) não tem como saber se o caso pede FULL — a informação nasce neste passo. Um sinal só, e ele é mecânico:
last_full_age_days > 30(ounull— ledger ausente/ilegível/SHA órfão, ou seja "não sei") ⇒ escale pro FULL. Em modo autônomo (/sovai, headless) escale e siga, sem perguntar: sugerir não serve pra quem não está lendo. Em modo interativo, diga o número e pergunte.- Caso contrário ⇒ touch, que é o caminho normal.
O campo existe porque o FULL é o único que avança ledger.last_commit (o touch é read-only nele), então a data desse commit é a data do último FULL.
⚠️ Não invente um segundo critério. unscoped_new e "arquivo fora do scope de todo doc" não servem de gatilho, e a tentação é real: o primeiro exige, por definição, que o arquivo esteja num diretório já coberto (então acusaria FULL a cada test_*.sh novo), e o segundo é alto num repo saudável (os scope: são seletivos de propósito — medido: 41 de 79 arquivos mudados neste repo, com o touch sendo claramente a escolha certa). Mecanizar "isso é estrutural?" produz heurística com cara de determinismo — o precedente do repo é o commits_after > 0 or edits_after >= 3, que era código e carimbava plano de 10 fases como executado.
Trabalhe sobre pending_docs, não sobre docs. docs lista tudo que o diff toca; pending_docs exclui os que já absorveram a mudança (doc mais novo que os arquivos). Sem isso o touch repetido vira no-op — enquanto o trabalho não é commitado, o git diff segue mostrando os mesmos arquivos. pending_docs vazio → reporte "nada a tocar" e pare.
2 · Re-projeção escopada, por doc
Para cada doc do plano (sequencial se ≤3; subagentes paralelos se mais): o agente recebe o doc atual + SÓ os arquivos mudados do scope + o diff deles (git diff <ledger_last_commit> -- <files> + working tree) e:
- Atualiza apenas as seções afetadas pelo diff; preserva o resto intocado (não reescreve, não "melhora").
- Obedece as Regras de escrita assertiva do SKILL grande (
skills/project-doc/SKILL.md→ Rules): nome/número/lista só por derivação mecânica no run; ponteiro = arquivo+símbolo; "ativa" exige evidência de wiring; costura citada existe nos dois lados. - Fato durável genuinamente NOVO que entrou na doc → anotar para o passo 4.
3 · Gate doc-lint (determinístico, antes do re-stamp)
python3 plugins/project-doc/lib/doc_lint.py --project-root "<root>" --docs <docs tocados> --json
FAIL → corrigir com a evidência que o próprio lint dá e re-rodar (máx 2 iterações; persiste → reportar FAIL, não silenciar). Falso-positivo legítimo (var dinâmica, config externa) → <!-- lint:ignore TOKEN --> ou .claude/.project-doc/lint-allow.txt, com justificativa no report.
4 · Journal
- Journal (disciplina do FULL, nunca relaxar):
journal.py adoptsó de fato durável genuinamente novo (nunca adopt do que já está vivo);journal.py invalidatesó contradição frontal com evidência arquivo:linha. - PROIBIDO rodar
journal.py update— avançarialedger.last_commite queimaria o backward-delta do próximo FULL. O ledger pertence ao FULL; o touch é read-only nele. - NÃO carimbe nada aqui. O carimbo é o passo 5, e ele vem depois do commit — pelo motivo do ovo-e-galinha abaixo.
5 · Report + o rito de DOIS commits (não é opcional)
Report curto primeiro: docs tocados (com o quê) · seam_review (costuras tocadas — verificar se o claim do OUTRO módulo mudou) · unscoped_new (arquivos novos em dirs cobertos — oferecer adicionar ao scope: do doc certo, ou ao verified-by: se for suíte de teste) · dead_scope (renames) · idade do último FULL (last_full_age_days, já decidida no passo 1 — aqui é só relatar o número).
Por que dois commits, e por que não dá pra ser um: o carimbo generated-commit: diz "esta doc vale pro estado do código no commit X". Quando código e doc entram no mesmo commit, X ainda não existe no momento de escrever o frontmatter — então o carimbo aponta pro commit anterior, a janela de staleness enxerga a mudança que a própria doc acabou de descrever, e o hook do SessionStart passa a gritar "⚠️ DEFASADA" sobre doc recém-nascida. Um doc não consegue citar o commit que o contém. Este repo pagou isso 3× (16211ae, b9028c3, 8d7a5a0) antes de virar comando.
PC="plugins/project-doc/lib/pattern_check.py"
# 1º commit — o CONTEÚDO (código, se houver, + os docs re-projetados + journal + grafo)
git add <arquivos tocados> .claude/docs/<tocados> .claude/.project-doc/findings.jsonl graphify-out/
git commit -m "..." # nunca `git add -A`
# 2º commit — o CARIMBO, apontando pro commit que acabou de nascer
python3 $PC --project-root . --restamp .claude/docs/<tocados>
git add .claude/docs/<tocados> && git commit -m "docs: re-stamp pro commit do conteúdo"
# confira: os dois medidores têm que concordar em `fresh`
python3 $PC --project-root . --project-staleness .
O --restamp faz o que antes era receita de sed pra lembrar: generated: = hoje, generated-commit: = HEAD, doc-sig: recomputada do corpo final e preservando a gen do doc-set (lida do marker do CLAUDE.md, não o CURRENT_GEN do código — o --sig cru bumpa a gen e viola o invariante "Gen NÃO bumpa"). Ele pula doc autoral (authored-by: human) e arquivo sem frontmatter, e falha sem escrever nada se não resolver o HEAD — carimbo pela metade é pior que carimbo velho. Passe só os docs que você re-projetou: carimbar doc que ninguém tocou escreveria generated: hoje sobre trabalho que não aconteceu.
Push seguro: git fetch antes, confirme fast-forward (git merge-base --is-ancestor origin/<branch> HEAD), nunca --force — o session-sync do bootstrap disputa esse push.
O que entra nos commits: só os artefatos de doc — docs tocados, findings.jsonl e graphify-out/ se existir (o .gitignore do projeto é quem exclui cache/ e os paths de máquina; o graph.json é versionado) — mais o código, se esta rodada mexeu em código. Nunca git add -A. O touch preserva o resto do doc, inclusive erro pré-existente: é complemento do FULL, não substituto.
Invariantes (não-negociáveis)
- Doc autoral é INTOCÁVEL. Arquivo com
authored-by: humanno frontmatter (quality-goals.md,constraints.md,context.md,solution-strategy.md,glossary.md,decisions/*.md— território do/start-doc) nunca é re-projetado, nunca ganhascope:, nunca é re-stampado. Se um aparecer no plano, pule e reporte. Hoje a proteção é indireta — oscope: []vazio o mantém fora dotouch-plan—, mas o passo 5 manda corrigirdead_scopee adotarunscoped_newnoscope:do doc certo: popular o scope de um autoral quebraria a trava para sempre e em silêncio. Antes de mexer noscope:de qualquer doc, cheque oauthored-by:. (Achado da revisão de 2026-07-26.) - Ativo novo exige linha de durabilidade (gen 3.8). Se
data-stores.mdestá entre os docs tocados, confira que todo depósito nele tem bloco correspondente emdurability.md— é a regra do check #24 do FULL, trazida pro touch porque senão um volume novo no compose entra no inventário e fica sem cobertura declarada até o próximo FULL (que pode demorar 30 dias). Sem bloco → escreva[TODO: sem cobertura declarada]e reporte. Silêncio sobre durabilidade é o que a gen 3.8 proíbe. - Gen NÃO bumpa. O touch não invalida docs antigas nem cria campo obrigatório (
generated-commit:é opcional — ausência não é violação). - Grafo em modo PESADO — o touch escreve doc, então garante o grafo fresco (
graphify update --force, passo 1), igual ao FULL. O que o touch NÃO faz é consumir o mapa: re-projeta do diff, semgraph_map.py/fan-out. Grafo e doc viajam juntos no commit. - Ledger read-only. Ver passo 4.
- Nunca re-projetar doc fora do plano. O touch-plan é o contrato; doc não mapeado não é tocado (nem "aproveitando que estou aqui").
- Secret: as mesmas regras do FULL (nomes SIM, valores NUNCA).
Output Protocol
**Touch 1/5:** grafo {criado | atualizado | já fresco | graphify ausente} · plano → {N} arquivos mudados → {M} doc(s) afetado(s) [+ costuras: {ids}] · último FULL há {D} dias → **{touch | ESCALEI PRO FULL}**
**Touch 2/5:** re-projeção → {doc}: {seções atualizadas}
**Touch 3/5:** doc-lint → {ok | X FAILs corrigidos | FAIL persistente: ...}
**Touch 4/5:** journal ({adopts} adoções, {invs} invalidações) · ledger intocado
**Touch 5/5:** conteúdo <hash1> + carimbo <hash2> ({M} doc(s) via --restamp) · staleness: por-doc {X} · agregado {Y} · último FULL há {N} dias{ — sugerir /project-doc se >30}
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.