enhance(#2554): resolve code review depth from path-scoped override rules (#3695)

* test(#2554): failing-first suite for path-scoped code review depth overrides

Binds the not-yet-built code-review-depth module: segment-aware path-prefix
matching of a changed-file set against ordered {paths,depth} rules, resolution
order flag > strongest matching rule > global > standard, typed validation
errors, and the large-scope downgrade boundary. Also proves behaviorally that
workflow.code_review_depth_overrides is not yet a registered config key.

Refs #2554

* feat(#2554): resolve code review depth from path-scoped override rules

Adds workflow.code_review_depth_overrides — an ordered array of {paths, depth}
rules matched against a review's changed-file set by segment-aware path-prefix
comparison. Resolution order is --depth= flag, then the strongest matching rule,
then workflow.code_review_depth, then standard; a matching rule replaces the
global rather than being max'd with it, so quick and standard rules stay
meaningful. Glob metacharacters are a hard configuration error rather than sugar
for a prefix, and malformed rules halt the review instead of degrading to
standard. The resolver is pure and reports its own provenance, so the workflow
can print the resolved depth and the rule that matched. The pre-existing
>50-file deep-to-standard downgrade moves into the module and now names the rule
it overrode.

The key is registered centrally rather than as a capability config slice: the
federated slice channel admits only boolean/string/number/enum, so an array
slice would be dropped as malformed.

Closes #2554

* test(#2554): correct depth-provenance assertions and pin out-of-repo paths

Two corrections to the failing-first suite. The source assertion for a
non-matching rule with no global configured expected 'config'; with no global
set the depth comes from the default, and a companion assertion tolerated
either value, so both passed against an implementation that derived provenance
from whether any rules existed rather than from where the depth came from.

The out-of-repo absolute-path case used a home-directory path that matched
neither implementation, so it never exercised the defect it named. It now pins
the discriminating cases: an absolute path outside the repo root must not match
a repo-relative rule, and one under the root must.

* docs(#2554): document path-scoped code review depth overrides

Reference rows for workflow.code_review_depth_overrides in the configuration,
features and commands references plus the locale copies that carry those tables,
and in the planning-config reference. Explanation of why escalation is
whole-review rather than per-file and why v1 is prefix-only. New how-to for
scoping review depth by path, carrying the configuration-error reason table and
the distinction between nothing to report and could not look. CONTEXT.md
glossary entry and the INVENTORY row for the new CLI module.

ja-JP and ko-KR CONFIGURATION.md carry no code_review keys at all, and ko-KR and
pt-BR FEATURES.md carry no code-review config table, so those files are
deliberately untouched.

* fix(#2554): make the depth-misconfiguration halt executable and reject control chars

Three review findings, all in this change.

The misconfiguration halt was prose rather than shell: the error-printing fence
was followed by an unconditional extraction fence, so an ok:false result threw
and left the depth empty instead of stopping the review. Prose is not a guard —
the two fences are now one block with a real conditional, and anything that is
not the literal string true fails closed.

An interior control character in a rule path survived validation and reached the
provenance string and the summary box; rule paths now reject control characters
via a new PATH_CONTROL_CHAR reason, after the glob check so precedence is
unchanged. That in turn makes the field record safe to delimit, so the seven
node invocations that each re-parsed the same result to read one field collapse
to one.

Also corrects the glossary entry's illustrative paths, which the glossary-ref
check read as real repository references.

* fix(#2554): use the fast-check v4 string API and acknowledge workflow growth

Two failures from the remote matrix on d3111f45, both this branch's.

The property block built its segment arbitrary with fc.stringOf, removed in
fast-check v4. Because the arbitrary is constructed in the describe body, the
throw took out all four property tests rather than one — they had never
executed. Rewritten to fc.string({unit, ...}), the form this repo already uses
in emitted-attribution.test.cjs. Every other fast-check helper in the file was
audited against the installed module.

The emitted-attribution growth arm needed an acknowledgment for code-review.md,
which grew 5376 bytes. The pre-existing 3503 fragment keying the same file is
spent — its ripple was absorbed when #3503 merged, and the base file is exactly
the 34435-byte baseline this growth is measured against — so it cannot clear
anything, while the ack lint hard-fails on a duplicate key across two sources.
Removed it in favor of the new fragment, which is exactly how #3503 itself
replaced the spent 3191 fragment.

* docs(#2554): backfill changeset PR number

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-19 22:45:35 -04:00
committed by GitHub
parent 71e00d426e
commit 2fca0e17e4
27 changed files with 1629 additions and 46 deletions

View File

@@ -1166,7 +1166,7 @@ Revisa arquivos de código-fonte alterados durante uma fase em busca de bugs, vu
| Argumento | Obrigatório | Descrição |
|-----------|-------------|-----------|
| `N` | **Sim** | Número da fase cujas mudanças revisar (por exemplo, `2` ou `02`) |
| `--depth=quick\|standard\|deep` | Não | Nível de profundidade da revisão (substitui a configuração `workflow.code_review_depth`). `quick`: somente correspondência de padrões (~2 min). `standard`: análise por arquivo com verificações específicas de linguagem (~5–15 min, padrão). `deep`: análise entre arquivos incluindo grafos de importação e cadeias de chamadas (~15–30 min) |
| `--depth=quick\|standard\|deep` | Não | Nível de profundidade da revisão. Substitui tanto `workflow.code_review_depth` quanto qualquer regra de caminho correspondente em `workflow.code_review_depth_overrides` — a flag sempre prevalece. `quick`: somente correspondência de padrões (~2 min). `standard`: análise por arquivo com verificações específicas de linguagem (~5–15 min, padrão). `deep`: análise entre arquivos incluindo grafos de importação e cadeias de chamadas (~15–30 min) |
| `--files file1,file2,...` | Não | Lista explícita de arquivos separados por vírgula; ignora completamente o escopo SUMMARY/git |
| `--fix` | Não | Corrige automaticamente problemas após a revisão — lê REVIEW.md, cria agente corretor, faz commit de cada correção atomicamente |
| `--fix --all` | Não | Inclui descobertas Info no escopo de correção (padrão: somente Critical + Warning) |

View File

@@ -47,6 +47,7 @@ O GSD armazena as configurações do projeto em `.planning/config.json`. Criado
"use_worktrees": true,
"code_review": true,
"code_review_depth": "standard",
"code_review_depth_overrides": [],
"plan_bounce": false,
"plan_bounce_script": null,
"plan_bounce_passes": 2,
@@ -248,6 +249,7 @@ Todos os controles de fluxo de trabalho seguem o padrão **ausente = habilitado*
| `workflow.worktree_skip_hooks` | boolean | `false` | Quando `true`, os agentes executores no modo worktree passam `--no-verify` (ignorando hooks de pré-commit) e a validação de hook pós-onda é executada contra o resultado mesclado. Válvula de escape opt-in para projetos cujos hooks não podem ser executados em worktrees de agente. Padrão `false` executa hooks em cada commit (#2924). |
| `workflow.code_review` | boolean | `true` | Habilita os comandos `/gsd-code-review` e `/gsd-code-review --fix`. Quando `false`, os comandos saem com uma mensagem de gate de configuração. Adicionado na v1.34 |
| `workflow.code_review_depth` | string | `standard` | Profundidade de revisão padrão para `/gsd-code-review`: `quick` (somente correspondência de padrão), `standard` (análise por arquivo) ou `deep` (entre arquivos com grafos de importação). Pode ser substituído por execução com `--depth=`. Adicionado na v1.34 |
| `workflow.code_review_depth_overrides` | array | `[]` | Lista ordenada de regras `{ paths: string[], depth }` que aumentam a profundidade de `/gsd-code-review` para diretórios específicos, ex.: `[{ "paths": ["src/auth"], "depth": "deep" }]`. Cada `paths` da regra é comparado com o conjunto de arquivos alterados da revisão por prefixo de diretório com segmentos completos (`src/auth` corresponde a `src/auth/token.ts`, nunca a `src/authfoo/x.ts` ou `docs/src/auth/x.ts`); a comparação diferencia maiúsculas/minúsculas, como o git. Sintaxe glob (`*`, `?`) é um erro de configuração, não um atalho para prefixo. Um único arquivo correspondido eleva a profundidade de toda a revisão — a profundidade não é aplicada por arquivo. Ordem de resolução: flag `--depth=` → regra correspondente mais forte → `workflow.code_review_depth` → `standard`; uma regra correspondente prevalece mesmo quando seu nível é mais fraco que o padrão global. Uma regra malformada (`depth` inválido, sintaxe glob, caminho absoluto, segmento `..`, caminho vazio, `overrides` que não é array, regra que não é objeto, `paths` malformado) é um erro de configuração e a revisão é interrompida em vez de usar um valor padrão silenciosamente. A profundidade resolvida e a regra correspondente são exibidas na saída da revisão. Adicionado em #2554 |
| `workflow.plan_bounce` | boolean | `false` | Executa script de validação externo nos planos gerados. Quando habilitado, o orquestrador de fase de planejamento encaminha cada PLAN.md pelo script especificado por `plan_bounce_script` e bloqueia em saída diferente de zero. Adicionado na v1.36 |
| `workflow.plan_bounce_script` | string | (nenhum) | Caminho para o script externo invocado na validação de bounce de plano. Recebe o caminho do PLAN.md como primeiro argumento. Obrigatório quando `plan_bounce` é `true`. Adicionado na v1.36 |
| `workflow.plan_bounce_passes` | number | `2` | Número de passagens sequenciais de bounce a executar. Cada passagem alimenta a saída da passagem anterior de volta no validador. Valores maiores aumentam o rigor ao custo de latência. Adicionado na v1.36 |