Help us improve
Share bugs, ideas, or general feedback.
From first-plan
Builds co-change graph from git history to identify files that typically change together, preventing incomplete PRs. Use in Discovery or /first-plan:cochange. Rust engine accelerates 10-100x.
npx claudepluginhub vynazevedo/first-plan --plugin first-planHow this skill is triggered — by the user, by Claude, or both
Slash command
/first-plan:co-change-analysisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Mapeia dependências de mudança baseadas em git history. Resolve o problema "esqueci de atualizar o consumer" - causa #1 de PRs incompletos em projetos grandes.
Identifies structural hotspots via co-change patterns and churn analysis using git history or Harness knowledge graph. Run before refactoring, for weekly risk tracking, or break investigations.
Analyzes git history to find code hotspots, temporal coupling between files, contributor knowledge distribution, and bus factor risks. Useful for queries on code ownership, frequent changes, or evolution.
Identifies and explains churn hotspots and unstable code clusters in git repos. Groups by directory, filename stems (e.g. foo.go + foo_test.go), and co-changes; classifies as unstable, buggy, tightly-coupled, etc.
Share bugs, ideas, or general feedback.
Mapeia dependências de mudança baseadas em git history. Resolve o problema "esqueci de atualizar o consumer" - causa #1 de PRs incompletos em projetos grandes.
Se o binário nativo first-plan-engine está disponível (ver skill first-plan-engine-bootstrap), invocar direto e parsear o JSON. 10-100x mais rápido vs git log via shell + agregação em Claude.
# Detectar engine
ENGINE=""
for c in "${CLAUDE_PLUGIN_ROOT}/engine/bin/first-plan-engine" "${HOME}/.local/bin/first-plan-engine" "$(command -v first-plan-engine 2>/dev/null)"; do
[ -x "$c" ] && ENGINE="$c" && break
done
if [ -n "$ENGINE" ]; then
# Engine path - rapido e exato
"$ENGINE" cochange \
--repo "$PWD" \
--since 180 \
--min-occurrences 5 \
--min-ratio 0.5 \
--output-json /tmp/cochange-${SESSION_ID}.json
# Parsear /tmp/cochange-*.json (schema first-plan-cochange-v1)
# Renderizar como markdown padrão em .first-plan/02-conventions/co-change.md
else
# Fallback markdown (algoritmo abaixo)
fi
JSON output schema (first-plan-cochange-v1):
pairs[].file_a, file_b, co_change_ratio, shared_commits, total_a, total_b, strengthclusters[].id, files, internal_cohesionengine_version, generated_at, repo_root, window_days, total_commits_analyzed, total_files_analyzed, elapsed_msSe engine ausente, oferecer instalação via skill first-plan-engine-bootstrap antes de cair no fallback.
Para cada par de arquivos (A, B), calcular:
co_change_ratio(A, B) = commits_modificando_ambos / commits_modificando_A
Se co_change_ratio(A, B) >= 0.7, B é um co-changer forte de A. Mexer em A sem tocar em B é red flag.
git log --since="180 days ago" --name-only --pretty=format:"COMMIT:%H" --no-merges
Output: lista de commits e arquivos modificados em cada.
Para cada commit, listar conjunto de arquivos S_i = {f1, f2, ...} modificados.
Para cada par (A, B) que aparece em algum S_i:
co_changes(A, B) = quantos S_i contêm ambostotal_changes(A) = quantos S_i contêm Aratio(A, B) = co_changes(A, B) / total_changes(A)Filtrar:
total_changes(A) >= 5 (sinal estatístico mínimo)co_change_ratio >= 0.5 (significativo)| Ratio | Força | Significado |
|---|---|---|
| >= 0.9 | strong | Quase sempre mudam juntos |
| 0.7-0.9 | moderate | Frequentemente juntos |
| 0.5-0.7 | weak | Mudam juntos com frequência notável |
| < 0.5 | none | Não considerar co-changer |
Aplicar clustering simples (Union-Find) sobre pares com ratio >= 0.7:
.first-plan/02-conventions/co-change.md---
section: conventions/co-change
generated_at: <ISO>
window_days: 180
total_files_analyzed: 245
strong_pairs: 23
moderate_pairs: 67
clusters_detected: 8
---
# Co-change Graph
Pares de arquivos que tendem a mudar juntos, baseado em 180 dias de git history.
## Pares fortes (>= 0.9)
| Arquivo A | Arquivo B | Co-change ratio | Commits compartilhados |
|-----------|-----------|-----------------|------------------------|
| internal/payment/charge.go | internal/payment/invoice.go | 0.94 | 17/18 |
| internal/auth/jwt.go | internal/middleware/auth.go | 0.92 | 11/12 |
| ... |
## Pares moderados (0.7-0.9)
(tabela similar)
## Clusters detectados
### Cluster 1 - Payment subsystem
Arquivos:
- internal/payment/charge.go
- internal/payment/invoice.go
- internal/payment/refund.go
- internal/handler/payment.go
Indicação: módulo coeso real, mudanças tipicamente afetam todos.
### Cluster 2 - ...
## Implicações pra Claude
- Antes de mexer em arquivo X, verificar `/first-plan:cochange X`
- Se algum co-changer não estiver no plano, alertar antes de execute
- Clusters detectados podem indicar boundaries de módulo - útil pra refator
08-meta/co-change.json (machine-readable){
"$schema": "first-plan-co-change-v1",
"generated_at": "<ISO>",
"window_days": 180,
"pairs": [
{
"file_a": "internal/payment/charge.go",
"file_b": "internal/payment/invoice.go",
"co_change_ratio": 0.94,
"shared_commits": 17,
"total_a": 18,
"total_b": 19,
"strength": "strong"
}
],
"clusters": [
{
"id": "cluster-1",
"name": "payment-subsystem",
"files": [
"internal/payment/charge.go",
"internal/payment/invoice.go",
"internal/payment/refund.go",
"internal/handler/payment.go"
],
"internal_cohesion": 0.87
}
]
}
Em monorepos com 50k+ commits, o git log pode ser lento. Otimizações:
--since="180 days ago" (já default)--max-count=5000 (commits mais recentes apenas)08-meta/co-change.json com TTL 7 diasEm projetos < 1000 commits, full scan é trivialmente rápido (<10s).
package-lock.json muda toda vez que package.json muda - filtrar lockfiles*.gen.go, *.pb.go - filtrar via gitignore patternsmigrations/ ou similarFiltros padrão excluem:
*.lock, *.lockb, package-lock.json, yarn.lock, Cargo.lock, go.sum, composer.lock*.min.js, *.bundle.jsvendor/, node_modules/, target/.gen., .pb., _pb2.pyQuando usuário roda /first-plan:plan <feature>:
ratio >= 0.7 não está no plano, listar como "potential missing co-change":## Riscos e ambiguidades
### Co-change alerts
- Vai modificar `internal/payment/charge.go` mas plano não menciona:
- `internal/payment/invoice.go` (co-change 0.94 - strong)
- `internal/handler/payment.go` (co-change 0.81 - moderate)
Considerar adicionar ao plano. Se intencional não tocar, justificar.
Co-change findings sempre têm:
confidence.initial: baseado em total_changes(A) (mais commits = mais confiável)signals_used: ratio + sample size + windowttl.days: 14 (refresh frequente porque git history muda)finding_id: F-cochange-payment-001
type: pattern
source:
type: git
location: git log --since="180 days ago"
commit_sha: <HEAD>
extracted_from:
- "17 commits affecting both files"
extracted_at: <ISO>
extracted_by: discovery-analyst
confidence:
initial: 0.88
signals_used:
- "ratio: 0.94"
- "shared_commits: 17"
- "total_a: 18 (sufficient sample)"
ttl:
days: 14
lifecycle:
status: active
data:
file_a: internal/payment/charge.go
file_b: internal/payment/invoice.go
co_change_ratio: 0.94
strength: strong