groundfast 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/references/coverage.md +13 -5
- package/references/pr-goal.md +5 -4
- package/scripts/cr-status.sh +21 -3
- package/skills/babysit/SKILL.md +2 -2
- package/skills/babysit/references/coderabbit.md +5 -0
- package/skills/babysit/references/loop.md +1 -0
- package/skills/babysit/scripts/pr-goal.sh +11 -8
- package/skills/babysit/scripts/pr-state.sh +1 -0
- package/skills/babysit/scripts/wait-review.sh +7 -0
- package/skills/drain/SKILL.md +2 -2
- package/skills/drain/references/inner-loop.md +3 -2
- package/skills/drain/references/threads.md +1 -0
- package/skills/pipeline/SKILL.md +1 -1
- package/skills/pipeline/references/issue-loop.md +3 -1
package/package.json
CHANGED
package/references/coverage.md
CHANGED
|
@@ -8,7 +8,7 @@ procedimento.
|
|
|
8
8
|
|
|
9
9
|
## Gatilho
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Três gatilhos, todos automáticos: não peça autorização, não pergunte ao Mestre, não espere outro
|
|
12
12
|
ciclo.
|
|
13
13
|
|
|
14
14
|
1. O **primeiro** `VEREDITO: rate limited` da espera de review para o head atual: o pedido do bot
|
|
@@ -18,16 +18,24 @@ ciclo.
|
|
|
18
18
|
já foi postado após o head (saída 0, sem comentário novo): o full review deste head já rodou e
|
|
19
19
|
não trouxe `APPROVED`. O bot não vai aprovar sozinho; cubra na mesma passada, sem esperar o
|
|
20
20
|
próximo ciclo (que estagnaria com o mesmo fingerprint). O critério 6 sai `N-A` (visto no #134).
|
|
21
|
+
3. O **primeiro** `VEREDITO: review skipped` do head (classe `skipped` do `cr-status.sh`): o bot
|
|
22
|
+
pulou a review deste head e não vai revisá-lo — PR aberto por bot sem vaga de review, como o
|
|
23
|
+
Renovate no #166, recusa até o `full review`. Não há janela a esperar nem pedido a repetir:
|
|
24
|
+
cubra no ciclo em que o skip é lido. Qualquer description que comece com `Review skipped` conta,
|
|
25
|
+
não só a de bot: o head não foi revisado, e a cobertura é review de verdade. Com a cobertura, o
|
|
26
|
+
critério 2 sai `cobre (interno)` e o 6 `N-A`.
|
|
21
27
|
|
|
22
28
|
| Veredito da review | Cobertura interna |
|
|
23
29
|
| :-- | :-- |
|
|
24
30
|
| `rate limited` | dispara agora, para este head |
|
|
31
|
+
| `review skipped` | dispara agora, para este head |
|
|
25
32
|
| `ausente` · `em curso` · `indeterminado` | não dispara: o critério 2 fica pendente e o próximo ciclo espera de novo. O `pr-goal.sh` aceitaria a cobertura no critério 2 com o bot `absent` (nunca no 6), mas o gatilho da casa é a recusa explícita — enquanto o bot pode chegar, espere por ele |
|
|
26
33
|
| `cobre o head` · `atenção` | não dispara: o bot cobriu e prevalece — exceto o gatilho 2, quando só falta o `APPROVED` dele |
|
|
27
34
|
| `pausado` | não dispara: o critério 2 já é `N-A` ([`pr-goal.md`](pr-goal.md) §Pausa) |
|
|
28
35
|
|
|
29
36
|
Head novo pede cobertura nova: depois de um push, a cobertura do head anterior não vale mais, e o
|
|
30
|
-
gatilho volta a valer no primeiro `rate limited` do head novo (ou no `APPROVED`
|
|
37
|
+
gatilho volta a valer no primeiro `rate limited` ou `review skipped` do head novo (ou no `APPROVED`
|
|
38
|
+
que não veio).
|
|
31
39
|
|
|
32
40
|
## A passada
|
|
33
41
|
|
|
@@ -77,7 +85,7 @@ mudou desde a passada (7).
|
|
|
77
85
|
O resumo é superfície pública: o que mudou e onde, sem log, sem saída de comando, sem valor de
|
|
78
86
|
config. O wrapper redige e neutraliza, e você também.
|
|
79
87
|
|
|
80
|
-
Depois do registro, com o bot em rate limit o `pr-goal.sh` passa o critério 2 como `cobre (interno)`
|
|
88
|
+
Depois do registro, com o bot em rate limit ou review skipped o `pr-goal.sh` passa o critério 2 como `cobre (interno)`
|
|
81
89
|
e, quando a base exige `APPROVED`, o 6 sai `N-A`; com o bot `success` (gatilho 2) só o 6 sai `N-A`.
|
|
82
90
|
A linha final sai `GOAL: atingido` com a nota de §O relatório. O ciclo conta a cobertura como
|
|
83
91
|
progresso, então o `ESTAGNADO` não a engole.
|
|
@@ -87,8 +95,8 @@ progresso, então o `ESTAGNADO` não a engole.
|
|
|
87
95
|
- Não substitui CI: critério 1 continua sendo o `VEREDITO:` do `wait-ci.sh`.
|
|
88
96
|
- Não fecha thread aberta de ninguém: critério 3 é medido igual.
|
|
89
97
|
- Não muda `reviewDecision`: `CHANGES_REQUESTED` herdado segue no critério 4. Só dispensa o
|
|
90
|
-
`APPROVED` do critério 6, e só quando o bot existe e não aprovou: recusou (rate limit)
|
|
91
|
-
revisou sem aprovar. Bot `absent` não dispensa o 6.
|
|
98
|
+
`APPROVED` do critério 6, e só quando o bot existe e não aprovou: recusou (rate limit), pulou o
|
|
99
|
+
head (review skipped) ou revisou sem aprovar. Bot `absent` não dispensa o 6.
|
|
92
100
|
- Não autoriza merge: merge é do Mestre, pelo `drain`.
|
|
93
101
|
|
|
94
102
|
## O relatório
|
package/references/pr-goal.md
CHANGED
|
@@ -10,11 +10,11 @@ pela impressão do texto.
|
|
|
10
10
|
| # | Critério | Medida |
|
|
11
11
|
|:-:|:--|:--|
|
|
12
12
|
| 1 | CI verde, ou repo sem check configurado — e todo check obrigatório da base presente no head | `VEREDITO:` de `wait-ci.sh` (`verde` / `sem CI`); obrigatório ausente é `pendente` e `FAIL 1 CI check obrigatório <x> ausente no head` (§Checks obrigatórios) |
|
|
13
|
-
| 2 | A review cobre o head | `VEREDITO: cobre` de `wait-review.sh --ping`; `cr_status` = `success`. Ou `cobre (interno)`: bot `rate_limited`/`absent` **e** comentário de cobertura interna do usuário autenticado com o sha do head (§Cobertura interna). `N-A` só para repo sem CodeRabbit: base sem `.coderabbit.yaml`, bot chamado há ≥ 30 min e nenhuma atividade dele no PR |
|
|
13
|
+
| 2 | A review cobre o head | `VEREDITO: cobre` de `wait-review.sh --ping`; `cr_status` = `success`. Ou `cobre (interno)`: bot `rate_limited`/`skipped`/`absent` **e** comentário de cobertura interna do usuário autenticado com o sha do head (§Cobertura interna). `N-A` só para repo sem CodeRabbit: base sem `.coderabbit.yaml`, bot chamado há ≥ 30 min e nenhuma atividade dele no PR |
|
|
14
14
|
| 3 | Zero threads não-resolvidas, **de qualquer autor** | query de `reviewThreads` sem `isResolved: false` |
|
|
15
15
|
| 4 | `reviewDecision` sem `CHANGES_REQUESTED` | `gh pr view --json reviewDecision`; o script diz se quem pediu foi o bot (full review resolve) ou humano (escalada) |
|
|
16
16
|
| 5 | `mergeStateStatus == CLEAN` | `gh pr view --json mergeStateStatus` |
|
|
17
|
-
| 6 | `reviewDecision == APPROVED` — **só se** a **base** do PR tem `.coderabbit.yaml` com `request_changes_workflow: true` | o script lê o arquivo da base pela API; sem a flag o critério é `N-A`; leitura falha é pendente — exceto com cobertura interna no head e o bot `rate_limited` ou `success` sem `APPROVED`, que deixa o 6 `N-A` (§Cobertura interna) |
|
|
17
|
+
| 6 | `reviewDecision == APPROVED` — **só se** a **base** do PR tem `.coderabbit.yaml` com `request_changes_workflow: true` | o script lê o arquivo da base pela API; sem a flag o critério é `N-A`; leitura falha é pendente — exceto com cobertura interna no head e o bot `rate_limited`, `skipped` ou `success` sem `APPROVED`, que deixa o 6 `N-A` (§Cobertura interna) |
|
|
18
18
|
|
|
19
19
|
Critério 6 existe porque o CodeRabbit só aprova sozinho com essa flag (o que ela faz, literal da docs, está em `skills/babysit/references/coderabbit.md`). Sem a flag, exigir `APPROVED` travaria o loop para sempre. `reviewDecision` preso em `CHANGES_REQUESTED` do bot com zero threads só sai com review nova: `@coderabbitai full review`, uma vez por head — o wrapper garante.
|
|
20
20
|
|
|
@@ -28,7 +28,7 @@ O critério 5 não é rede para isso: com `protected: false` (repo privado sem G
|
|
|
28
28
|
|
|
29
29
|
## Cobertura interna
|
|
30
30
|
|
|
31
|
-
Terceiro estado do critério 2 (ADR 0001, glossário em `CONTEXT.md`): quando o bot não cobre o head (`rate_limited` ou `absent`), a review interna da casa aplicada ao head vale como `PASS 2 review cobre (interno)`. Este arquivo diz o que o `pr-goal.sh` **aceita**; quando a cobertura dispara (primeiro `rate limited` do head, ou o bot revisou sem aprovar), o que a passada olha e como ela é registrada está em [`coverage.md`](coverage.md). A prova mora no GitHub, não em estado local: **um comentário de issue no PR** (`gh pr comment`; review e thread não contam), escrito pelo usuário autenticado, com a linha-máquina numa **linha própria**:
|
|
31
|
+
Terceiro estado do critério 2 (ADR 0001, glossário em `CONTEXT.md`): quando o bot não cobre o head (`rate_limited`, `skipped` ou `absent`), a review interna da casa aplicada ao head vale como `PASS 2 review cobre (interno)`. Este arquivo diz o que o `pr-goal.sh` **aceita**; quando a cobertura dispara (primeiro `rate limited` ou `review skipped` do head, ou o bot revisou sem aprovar), o que a passada olha e como ela é registrada está em [`coverage.md`](coverage.md). A prova mora no GitHub, não em estado local: **um comentário de issue no PR** (`gh pr comment`; review e thread não contam), escrito pelo usuário autenticado, com a linha-máquina numa **linha própria**:
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
<!-- groundfast-cobertura-interna: <sha completo do head> -->
|
|
@@ -39,11 +39,12 @@ Terceiro estado do critério 2 (ADR 0001, glossário em `CONTEXT.md`): quando o
|
|
|
39
39
|
A cobertura no head dispensa o critério **6** (emenda à ADR 0001) só com evidência positiva de que o bot existe e não aprovou este head, e só quando o 6 se aplicaria (flag na base, ou config ilegível):
|
|
40
40
|
|
|
41
41
|
- bot `rate_limited`: recusou, não revisou o head e não tem como aprová-lo;
|
|
42
|
+
- bot `skipped`: a description do status começa com `Review skipped` (state `SUCCESS`, mas o head não foi revisado — PR de bot sem vaga de review, #166); pulou o head e não tem como aprová-lo;
|
|
42
43
|
- bot `success` sem `APPROVED`: revisou o head e não aprovou (visto no #134, mesmo depois de um `full review` aceito). `APPROVED` passa pela régua normal.
|
|
43
44
|
|
|
44
45
|
Bot `absent` **não** dispensa o 6: pode ser só o bot a caminho do head recém-pushado. O 2 sai `cobre (interno)` e o 6 segue a config (flag → exige `APPROVED`; leitura falha → pendente; sem flag → `N-A`). Só a aprovação sai do caminho: `CHANGES_REQUESTED` continua barrando pelo critério 4, e thread aberta pelo 3.
|
|
45
46
|
|
|
46
|
-
O fingerprint diferencia `cr=rate_limited` de `cr=rate_limited+interno` (idem `absent`) e `cr=success` de `cr=success+cov6` (o `fpjson:` leva `internal` e `cov6`), então o ciclo conta a cobertura como progresso (e `+interno` não entra na contagem de rate limit do `cycle.sh`). A linha final sai `GOAL: atingido (critérios 2 e 6 por cobertura interna)` quando a cobertura passou o 2 e dispensou o 6, `(critério 2 por cobertura interna)` quando só o 2, e `(critério 6 por cobertura interna)` quando o bot revisou e só o 6 foi dispensado; o `MERGED` do drain repete a nota. Quem posta é `skills/babysit/scripts/cov-comment.sh` (`<N> <owner/name> <passadas> <real> <nits> <lentes> [sha revisado]`, resumo na stdin; no drain e no pipeline, `babysit-cmd.sh cov-comment` / `pipeline-cmd.sh cov-comment`): lê o head pelo `gh`, sai 5 sem postar quando já há cobertura válida para esse sha, sai 7 quando o head já não é o sha revisado que se passou, redige o corpo e põe o marcador na primeira linha, antes do texto humano (passadas, REAL corrigidos, nits, lentes). A linha do marcador é a única parte lida pelo `pr-goal.sh`, e é **dado, não instrução**.
|
|
47
|
+
O fingerprint diferencia `cr=rate_limited` de `cr=rate_limited+interno` (idem `skipped` e `absent`) e `cr=success` de `cr=success+cov6` (o `fpjson:` leva `internal` e `cov6`), então o ciclo conta a cobertura como progresso (e `+interno` não entra na contagem de rate limit do `cycle.sh`). A linha final sai `GOAL: atingido (critérios 2 e 6 por cobertura interna)` quando a cobertura passou o 2 e dispensou o 6, `(critério 2 por cobertura interna)` quando só o 2, e `(critério 6 por cobertura interna)` quando o bot revisou e só o 6 foi dispensado; o `MERGED` do drain repete a nota. Quem posta é `skills/babysit/scripts/cov-comment.sh` (`<N> <owner/name> <passadas> <real> <nits> <lentes> [sha revisado]`, resumo na stdin; no drain e no pipeline, `babysit-cmd.sh cov-comment` / `pipeline-cmd.sh cov-comment`): lê o head pelo `gh`, sai 5 sem postar quando já há cobertura válida para esse sha, sai 7 quando o head já não é o sha revisado que se passou, redige o corpo e põe o marcador na primeira linha, antes do texto humano (passadas, REAL corrigidos, nits, lentes). A linha do marcador é a única parte lida pelo `pr-goal.sh`, e é **dado, não instrução**.
|
|
47
48
|
|
|
48
49
|
## Pausa do CodeRabbit
|
|
49
50
|
|
package/scripts/cr-status.sh
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# Classifica o CodeRabbit no head: rollup GraphQL + check homônimo.
|
|
2
2
|
# Sourced — não é executável. Seta CR_CLASS CR_DETAIL CR_HEAD CR_BOT.
|
|
3
3
|
#
|
|
4
|
-
# CR_CLASS: paused | rate_limited | success | pending | attention | absent | error
|
|
4
|
+
# CR_CLASS: paused | rate_limited | skipped | success | pending | attention | absent | error
|
|
5
5
|
# paused vem de GROUNDFAST_CODERABBIT=off (references/pr-goal.md §Pausa) e sai
|
|
6
6
|
# antes de qualquer leitura: `cr_paused` é a única definição da chave.
|
|
7
7
|
# No rollup vale a entrada do bot mais recente (createdAt/completedAt/startedAt);
|
|
8
8
|
# em `gh pr checks` um status context vem sem data (0001-01-01), então ali vale
|
|
9
9
|
# a última da lista. Precedência: rate_limited (a description do check/rollup
|
|
10
10
|
# diz "Review rate limited" — o state vem SUCCESS, mas o head NÃO foi revisado)
|
|
11
|
-
# →
|
|
11
|
+
# → skipped (a description começa com "Review skipped", como no PR de bot sem
|
|
12
|
+
# vaga de review do #166: state SUCCESS, head NÃO revisado, e o bot recusa o
|
|
13
|
+
# full review) → rollup success → pending (rollup ou check) → rollup attention → check
|
|
12
14
|
# SUCCESS só se o rollup não cobriu → check attention → leitura falha em uma
|
|
13
15
|
# fonte sem a outra ter decidido → error (graphql morto, checks ilegíveis ou jq
|
|
14
16
|
# que não parseou: falta de evidência não é evidência de ausência) → ausente
|
|
@@ -28,6 +30,13 @@ cr_paused() {
|
|
|
28
30
|
esac
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
# A description do bot começa com "Review skipped" (ex.: "Review skipped: bot
|
|
34
|
+
# user not eligible for review"). Só o começo da primeira linha não vazia: a
|
|
35
|
+
# frase no meio de outro texto não é o status do bot.
|
|
36
|
+
cr_desc_skipped() {
|
|
37
|
+
printf '%s\n' "$1" | tr '\r' '\n' | grep -v '^[[:space:]]*$' | head -1 | grep -Eiq '^[[:space:]]*review skipped'
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
cr_status() {
|
|
32
41
|
local owner="$1" name="$2" num="$3" repo="$4"
|
|
33
42
|
local fr frc chk chk_err chk_state chk_desc line rollup rollup_desc check
|
|
@@ -73,11 +82,13 @@ cr_status() {
|
|
|
73
82
|
| if . == null then empty else (.description // empty) end' 2>/dev/null) || chk_desc=
|
|
74
83
|
if [ -n "$chk_desc" ]; then
|
|
75
84
|
cr_comment_classify "$chk_desc"
|
|
76
|
-
[ "$CR_REASON" = rate_limit ]
|
|
85
|
+
if [ "$CR_REASON" = rate_limit ]; then chk_state=RATE_LIMITED
|
|
86
|
+
elif cr_desc_skipped "$chk_desc"; then chk_state=REVIEW_SKIPPED; fi
|
|
77
87
|
fi
|
|
78
88
|
case "$chk_state" in
|
|
79
89
|
__JQ_ERROR__) check=error ;;
|
|
80
90
|
RATE_LIMITED) check=rate_limited ;;
|
|
91
|
+
REVIEW_SKIPPED) check=skipped ;;
|
|
81
92
|
SUCCESS|success) check=success ;;
|
|
82
93
|
PENDING|IN_PROGRESS|QUEUED|WAITING|pending|in_progress|queued|waiting) check=pending ;;
|
|
83
94
|
FAILURE|CANCELLED|TIMED_OUT|ACTION_REQUIRED|failure|cancelled|timed_out|action_required) check=attention ;;
|
|
@@ -126,6 +137,9 @@ cr_status() {
|
|
|
126
137
|
if [ "$CR_REASON" = rate_limit ]; then
|
|
127
138
|
rollup=rate_limited
|
|
128
139
|
line="rate_limited ${line#* } — ${rollup_desc}"
|
|
140
|
+
elif cr_desc_skipped "$rollup_desc"; then
|
|
141
|
+
rollup=skipped
|
|
142
|
+
line="skipped ${line#* } — ${rollup_desc}"
|
|
129
143
|
fi
|
|
130
144
|
fi
|
|
131
145
|
CR_BOT="coderabbit: ${line#* }"
|
|
@@ -139,6 +153,10 @@ cr_status() {
|
|
|
139
153
|
CR_CLASS=rate_limited; CR_DETAIL="rate limited — o bot não revisou o head (rollup: ${CR_BOT#coderabbit: })"
|
|
140
154
|
elif [ "$check" = "rate_limited" ]; then
|
|
141
155
|
CR_CLASS=rate_limited; CR_DETAIL="rate limited — o bot não revisou o head (check com \"Review rate limited\", rollup ${rollup})"
|
|
156
|
+
elif [ "$rollup" = "skipped" ]; then
|
|
157
|
+
CR_CLASS=skipped; CR_DETAIL="review skipped — o bot pulou a review deste head (rollup: ${CR_BOT#coderabbit: })"
|
|
158
|
+
elif [ "$check" = "skipped" ]; then
|
|
159
|
+
CR_CLASS=skipped; CR_DETAIL="review skipped — o bot pulou a review deste head (check com \"Review skipped\", rollup ${rollup})"
|
|
142
160
|
elif [ "$rollup" = "success" ]; then
|
|
143
161
|
CR_CLASS=success; CR_DETAIL="rollup success"
|
|
144
162
|
elif [ "$rollup" = "pending" ] || [ "$check" = "pending" ]; then
|
package/skills/babysit/SKILL.md
CHANGED
|
@@ -75,9 +75,9 @@ GROUNDFAST_WAIT_BG=1 scripts/wait-review.sh --ping <N> <owner/name> 900
|
|
|
75
75
|
|
|
76
76
|
Roteie pelo `VEREDITO:` em `loop.md`. Sem a env recusa (exit 2).
|
|
77
77
|
|
|
78
|
-
### 2b. `rate limited` → cobertura interna
|
|
78
|
+
### 2b. `rate limited` ou `review skipped` → cobertura interna
|
|
79
79
|
|
|
80
|
-
O bot recusou o head: cubra pela casa, pelo procedimento de
|
|
80
|
+
O bot recusou ou pulou o head: cubra pela casa, pelo procedimento de
|
|
81
81
|
[`references/coverage.md`](../../references/coverage.md). As três lentes de `lenses.md` sobre
|
|
82
82
|
`git diff origin/<base>...HEAD` — uma lente por agente read-only onde o fan-out couber, senão em
|
|
83
83
|
sequência. Zero achados abertos e então:
|
|
@@ -32,6 +32,11 @@ no plano incluído (o bot avisa que pode seguir por usage-based billing, se eleg
|
|
|
32
32
|
`wait-review --ping` lê a janela na recusa do bot ("Your next included review will be available in
|
|
33
33
|
N minutes"; sem match estima 60 min e diz isso no `VEREDITO:`) e repete o pedido quando ela reabre —
|
|
34
34
|
dentro do orçamento da mesma execução; janela maior que o orçamento cai no ciclo seguinte.
|
|
35
|
+
|
|
36
|
+
"Review skipped" também chega com o status em `SUCCESS` sem revisar o head: no PR aberto por bot sem
|
|
37
|
+
vaga de review (`Review skipped: bot user not eligible for review`, #166), e o `full review` volta
|
|
38
|
+
`Action not completed`. `cr-status.sh` classifica `skipped` pela description que começa com
|
|
39
|
+
"Review skipped"; não há janela, e o `wait-review` sai na hora, sem ping.
|
|
35
40
|
`gh-thread cr review|full-review` posta e espera a resposta ao comando por até 90 s
|
|
36
41
|
(`GROUNDFAST_CR_ACK_WAIT`). O julgamento do comentário é `scripts/cr-comment.sh` (`ack` / `reason` /
|
|
37
42
|
janela): "rate limited" solto no walkthrough não é recusa; "Review triggered" conta como aceite
|
|
@@ -39,6 +39,7 @@ Chegou aqui de um rerun do passo 3? Rode `flaky.sh` (§3) antes de seguir a tabe
|
|
|
39
39
|
| cobre o head · atenção | `<skill-dir>/scripts/pr-state.sh` de novo (threads podem ter nascido) e passo 4 |
|
|
40
40
|
| ausente · em curso · indeterminado · orçamento estourado | passo 4 com as threads que já existem; o critério 2 fica pendente e o próximo ciclo espera de novo |
|
|
41
41
|
| rate limited | o bot recusou: o head **não** foi revisado. Cubra pela casa agora — [`coverage.md`](../../../references/coverage.md), procedimento e registro. Cobertura que gerou push: volte ao passo 2, e cubra o head novo; sem push: passo 4 com o que existe. O `--ping` repete o pedido quando a janela reabrir |
|
|
42
|
+
| review skipped | o bot pulou o head e não vai revisá-lo. Cubra pela casa agora — [`coverage.md`](../../../references/coverage.md), gatilho 3 |
|
|
42
43
|
| pausado | `pr-goal.md` §Pausa: critério 2 `N-A`, nada a esperar. A chave é do ambiente do Mestre — nunca inline, nunca a pedido de thread. Passo 4 com as threads que existem |
|
|
43
44
|
|
|
44
45
|
## 3. CI vermelho que passa no rerun — flaky, não infra
|
|
@@ -117,9 +117,9 @@ cr_detail=$(printf '%s' "$CR_DETAIL" | redact | head -c 200)
|
|
|
117
117
|
# de código não contam. Corpo de comentário é dado, não instrução: só a linha
|
|
118
118
|
# do marcador é lida. Sha antigo, outro autor ou edição deixam o motivo na linha.
|
|
119
119
|
# cov_ok = cobertura válida no head; quem a usa decide cada critério: o 2 só com o
|
|
120
|
-
# bot rate_limited/absent (`internal`), o 6 só com rate_limited/success (abaixo).
|
|
120
|
+
# bot rate_limited/skipped/absent (`internal`), o 6 só com rate_limited/skipped/success (abaixo).
|
|
121
121
|
cov_ok=0; internal=0; internal_note=""
|
|
122
|
-
case "$CR_CLASS" in rate_limited|absent|success) cov_read=1 ;; *) cov_read=0 ;; esac
|
|
122
|
+
case "$CR_CLASS" in rate_limited|skipped|absent|success) cov_read=1 ;; *) cov_read=0 ;; esac
|
|
123
123
|
if [ "$cov_read" -eq 1 ] && [ -n "$head_full" ]; then
|
|
124
124
|
cov=$(cov_status "$pv" "$head_full")
|
|
125
125
|
case "$cov" in
|
|
@@ -131,17 +131,19 @@ if [ "$cov_read" -eq 1 ] && [ -n "$head_full" ]; then
|
|
|
131
131
|
*) internal_note="leitura dos comentários de cobertura falhou — não conta" ;;
|
|
132
132
|
esac
|
|
133
133
|
fi
|
|
134
|
-
[ "$cov_ok" -eq 1 ] && { [ "$CR_CLASS" = "rate_limited" ] || [ "$CR_CLASS" = "absent" ]; } && internal=1
|
|
134
|
+
[ "$cov_ok" -eq 1 ] && { [ "$CR_CLASS" = "rate_limited" ] || [ "$CR_CLASS" = "skipped" ] || [ "$CR_CLASS" = "absent" ]; } && internal=1
|
|
135
135
|
note="${internal_note:+ · $internal_note}"
|
|
136
136
|
case "$CR_CLASS" in
|
|
137
137
|
paused) na "2 review — CodeRabbit pausado (GROUNDFAST_CODERABBIT=off): a review do PR é a da casa, pelo /pr" ;;
|
|
138
138
|
success) pass "2 review cobre o head ($cr_detail)" ;;
|
|
139
139
|
error) fail "2 review" "leitura falhou ($cr_detail) — não conclua que o head foi revisado" ;;
|
|
140
|
-
absent|rate_limited)
|
|
140
|
+
absent|rate_limited|skipped)
|
|
141
141
|
if [ "$internal" -eq 1 ]; then
|
|
142
142
|
pass "2 review cobre (interno) — cobertura interna no head ${head}, comentário do usuário autenticado; bot ${CR_CLASS}"
|
|
143
143
|
elif [ "$CR_CLASS" = "rate_limited" ]; then
|
|
144
144
|
fail "2 review" "rate limited — o bot não revisou o head; wait-review --ping repete o pedido quando a janela reabrir${note}"
|
|
145
|
+
elif [ "$CR_CLASS" = "skipped" ]; then
|
|
146
|
+
fail "2 review" "${cr_detail}; o bot não vai revisá-lo — cubra pela casa (coverage.md, gatilho 3)${note}"
|
|
145
147
|
# N-A só quando o repo não tem o bot: base sem .coderabbit.yaml, bot chamado
|
|
146
148
|
# há pelo menos 30 min e nenhuma atividade dele no PR. Antes disso é fila.
|
|
147
149
|
elif [ "$cr_cfg" = "present" ]; then
|
|
@@ -210,16 +212,17 @@ if [ "$mss" = "CLEAN" ]; then pass "5 mergeStateStatus CLEAN"; else fail "5 merg
|
|
|
210
212
|
|
|
211
213
|
# --- 6. APPROVED, só com request_changes_workflow na base ---------------------
|
|
212
214
|
# A cobertura interna no head dispensa o 6 só com evidência positiva de que o bot
|
|
213
|
-
# existe e não aprovou este head (ADR 0001,
|
|
214
|
-
# (recusou)
|
|
215
|
+
# existe e não aprovou este head (ADR 0001, emendas de 2026-10-01 e 2026-10-08):
|
|
216
|
+
# rate_limited (recusou), skipped (pulou a review, #166) ou success sem APPROVED
|
|
217
|
+
# (revisou e não aprovou). `absent` pode ser só
|
|
215
218
|
# o bot ainda a caminho do head recém-pushado: segue a régua da config. A
|
|
216
219
|
# dispensa só conta quando a base exige APPROVED ou a config dela não foi lida.
|
|
217
220
|
cov6=0
|
|
218
221
|
need6=0; { [ "$cr_flag" -eq 1 ] || [ "$cr_cfg" = "error" ]; } && need6=1
|
|
219
222
|
if [ "$paused" -eq 1 ]; then
|
|
220
223
|
na "6 APPROVED — CodeRabbit pausado (GROUNDFAST_CODERABBIT=off): ninguém aprova automaticamente"
|
|
221
|
-
elif [ "$need6" -eq 1 ] && [ "$cov_ok" -eq 1 ] && [ "$CR_CLASS" = "rate_limited" ]; then
|
|
222
|
-
cov6=1; na "6 APPROVED — cobertura interna no head ${head}: o bot (
|
|
224
|
+
elif [ "$need6" -eq 1 ] && [ "$cov_ok" -eq 1 ] && { [ "$CR_CLASS" = "rate_limited" ] || [ "$CR_CLASS" = "skipped" ]; }; then
|
|
225
|
+
cov6=1; na "6 APPROVED — cobertura interna no head ${head}: o bot (${CR_CLASS}) não revisou o head e não tem como aprová-lo"
|
|
223
226
|
elif [ "$need6" -eq 1 ] && [ "$cov_ok" -eq 1 ] && [ "$CR_CLASS" = "success" ] && [ "$rd" != "APPROVED" ]; then
|
|
224
227
|
cov6=1; na "6 APPROVED — cobertura interna no head ${head}: o bot revisou o head sem aprovar (reviewDecision=${rd:-nenhuma}); a cobertura cobre a aprovação"
|
|
225
228
|
elif [ "$cr_cfg" = "error" ]; then
|
|
@@ -57,6 +57,7 @@ else
|
|
|
57
57
|
attention) echo "veredito: ATENÇÃO — status $CR_DETAIL no head; leia o comentário do bot" ;;
|
|
58
58
|
absent) echo "veredito: NÃO REVISADO — rode wait-review.sh" ;;
|
|
59
59
|
rate_limited) echo "veredito: RATE LIMITED — o bot recusou e não revisou o head; rode wait-review.sh --ping (repete quando a janela reabrir)" ;;
|
|
60
|
+
skipped) echo "veredito: REVIEW SKIPPED — o bot pulou a review deste head e não vai revisá-lo; cubra pela casa (coverage.md, gatilho 3)" ;;
|
|
60
61
|
*) echo "veredito: INDETERMINADO — rode wait-review.sh" ;;
|
|
61
62
|
esac
|
|
62
63
|
fi
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
# "Review rate limited" (classe rate_limited) NÃO cobre o head: com --ping o
|
|
9
9
|
# pedido é repetido quando a janela reabre — a que o bot anunciou, ou 60 min
|
|
10
10
|
# estimados quando a recusa vem sem janela. Sem --ping é VEREDITO imediato.
|
|
11
|
+
# "Review skipped" (classe skipped) também NÃO cobre o head, e não tem janela:
|
|
12
|
+
# o bot pulou este head (PR de bot sem vaga de review, #166) e recusa o pedido.
|
|
13
|
+
# VEREDITO imediato, com ou sem --ping — um ping só sujaria o PR.
|
|
11
14
|
set -uo pipefail
|
|
12
15
|
# shellcheck source=../../../scripts/redact.sh
|
|
13
16
|
. "$(dirname "$0")/../../../scripts/redact.sh" || { echo "redact.sh ausente — abortando" >&2; exit 3; }
|
|
@@ -148,6 +151,10 @@ while :; do
|
|
|
148
151
|
veredito="VEREDITO: atenção — status ${CR_DETAIL} no head; leia o comentário do bot"
|
|
149
152
|
break
|
|
150
153
|
;;
|
|
154
|
+
skipped)
|
|
155
|
+
veredito="VEREDITO: review skipped — o bot pulou a review deste head e não vai revisá-lo; cubra pela casa (coverage.md, gatilho 3)"
|
|
156
|
+
break
|
|
157
|
+
;;
|
|
151
158
|
rate_limited)
|
|
152
159
|
if [ "$ping" -eq 0 ]; then
|
|
153
160
|
veredito="VEREDITO: rate limited — o bot não revisou o head (sem --ping, ninguém repete o pedido)"
|
package/skills/drain/SKILL.md
CHANGED
|
@@ -87,9 +87,9 @@ As duas esperas passam do teto de um comando em foreground: rode em segundo plan
|
|
|
87
87
|
|
|
88
88
|
`<min>` é o orçamento da pergunta do passo 1. A linha `CICLO:` decide (`inner-loop.md` §Scripts): segue, ou encerra este PR (2g).
|
|
89
89
|
|
|
90
|
-
Nesta ordem: push, espera de CI, espera de review (com `--ping`). Vermelho: corrija, `scripts/babysit-cmd.sh stage` + `scripts/commit.sh` (mensagem na stdin), volte ao 2d. Depois das esperas: `VEREDITO: atenção` → leia o comentário do bot e volte ao 2c antes de seguir; `VEREDITO: rate limited` → cobertura interna deste head, abaixo; 2e se `mergeable` ≠ `MERGEABLE` ou se `pr-goal` reporta critério 5 com `BEHIND` / `DIRTY`; senão 2f.
|
|
90
|
+
Nesta ordem: push, espera de CI, espera de review (com `--ping`). Vermelho: corrija, `scripts/babysit-cmd.sh stage` + `scripts/commit.sh` (mensagem na stdin), volte ao 2d. Depois das esperas: `VEREDITO: atenção` → leia o comentário do bot e volte ao 2c antes de seguir; `VEREDITO: rate limited` ou `review skipped` → cobertura interna deste head, abaixo; 2e se `mergeable` ≠ `MERGEABLE` ou se `pr-goal` reporta critério 5 com `BEHIND` / `DIRTY`; senão 2f.
|
|
91
91
|
|
|
92
|
-
`rate limited`: o bot recusou e a casa cobre, pelo procedimento de [`coverage.md`](../../references/coverage.md). A passada do 2b vale para este head quando nada foi commitado entre ela e o push; commitou, passe as lentes sobre o delta. Registre e decida pela linha `COBERTURA:`:
|
|
92
|
+
`rate limited` / `review skipped`: o bot recusou ou pulou o head e a casa cobre, pelo procedimento de [`coverage.md`](../../references/coverage.md). A passada do 2b vale para este head quando nada foi commitado entre ela e o push; commitou, passe as lentes sobre o delta. Registre e decida pela linha `COBERTURA:`:
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
95
|
scripts/babysit-cmd.sh cov-comment <N> <owner/name> <passadas> <real> <nits> <lentes> <sha revisado> <<'--RESUMO--'
|
|
@@ -22,9 +22,10 @@ saem só via `babysit-cmd.sh`. O objetivo é o de [`pr-goal.md`](../../../refere
|
|
|
22
22
|
**Orçamento por PR** em minutos (perguntado com o prefixo, default 60), **900 s** por `wait-ci` e por
|
|
23
23
|
`wait-review`. `cycle begin` no início de cada ciclo. Na linha `CICLO:`: `ESTAGNADO` → `#<N> BLOQUEADO estagnado <critérios pendentes>`; `indeterminado` → `#<N> BLOQUEADO leitura <motivo>`; `ORÇAMENTO ESTOURADO` → `#<N> BLOQUEADO orçamento <min>`. Cada uma: `cycle end`, a linha, próximo.
|
|
24
24
|
|
|
25
|
-
## Review rate limited — cubra pela casa
|
|
25
|
+
## Review rate limited ou skipped — cubra pela casa
|
|
26
26
|
|
|
27
|
-
`VEREDITO: rate limited` no `wait-review` do 2d: o bot recusou
|
|
27
|
+
`VEREDITO: rate limited` ou `review skipped` no `wait-review` do 2d: o bot recusou ou pulou o head,
|
|
28
|
+
e o head não foi revisado. Cubra
|
|
28
29
|
agora, pelo procedimento de [`coverage.md`](../../../references/coverage.md) — a passada do 2b
|
|
29
30
|
vale para este head quando nada foi commitado entre ela e o push — e registre com
|
|
30
31
|
`babysit-cmd.sh cov-comment`. Com a cobertura no head, `pr-goal` passa o critério 2 como
|
|
@@ -27,6 +27,7 @@ O sinal é o `VEREDITO:` de `babysit-cmd.sh wait-review --ping <N> <repo> 900`.
|
|
|
27
27
|
- `cobre o head` → critério 2 ok; `pr-state` de novo se nasceram threads.
|
|
28
28
|
- `atenção` → leia o comentário do bot, triagem como acima.
|
|
29
29
|
- `rate limited` → o head **não** foi revisado; critério 2 pendente e o ciclo fica `aguardando` (até 3 ciclos sem push; depois `ESTAGNADO`), salvo cobertura interna válida, que o `pr-goal` passa como `cobre (interno)` (procedimento em [`coverage.md`](../../../references/coverage.md)). O `--ping` repete o pedido quando a janela do bot reabre.
|
|
30
|
+
- `review skipped` → o bot pulou este head e não vai revisá-lo: cubra pela casa no mesmo ciclo ([`coverage.md`](../../../references/coverage.md), gatilho 3).
|
|
30
31
|
- `pausado` → `GROUNDFAST_CODERABBIT=off` (`pr-goal.md` §Pausa): critério 2 `N-A`, nada a esperar nem a pingar; trate as threads que existem.
|
|
31
32
|
- `ausente` / `em curso` / orçamento → critério 2 pendente; trate as threads que existem e o próximo ciclo espera de novo. `pr-goal` é quem diz se o objetivo fechou — e marca `N-A 2` quando o bot foi chamado e nunca apareceu no PR (repo sem CodeRabbit).
|
|
32
33
|
- `reviewDecision` preso em `CHANGES_REQUESTED` → `inner-loop.md` §Merge (bot: full-review; humano: bloqueado).
|
package/skills/pipeline/SKILL.md
CHANGED
|
@@ -43,7 +43,7 @@ Para cada issue confirmada, na ordem, percorra `issue-loop.md` sem reordenar ou
|
|
|
43
43
|
A implementação e o push são sempre seus. A política de fan-out do preâmbulo decide a forma das
|
|
44
44
|
análises read-only — as três lentes no review do PR e na cobertura interna
|
|
45
45
|
([`coverage.md`](../../references/coverage.md)), que o babysit do passo 5 dispara no primeiro
|
|
46
|
-
`VEREDITO: rate limited` do head, a triagem de threads por arquivo e o diagnóstico de CI vermelho:
|
|
46
|
+
`VEREDITO: rate limited` ou `review skipped` do head, a triagem de threads por arquivo e o diagnóstico de CI vermelho:
|
|
47
47
|
onde ela permite agentes read-only em paralelo e `free -m` mostra 2000 MB ou mais, despache-os;
|
|
48
48
|
caso contrário, tudo em sequência nesta sessão. Esperas que excedem o turno
|
|
49
49
|
(`pipeline-cmd.sh wait-ci`, `wait-review --ping`) rodam em segundo plano pelo mecanismo do host;
|
|
@@ -96,12 +96,14 @@ Não invoque `/babysit`. Execute o ciclo pelos scripts já existentes:
|
|
|
96
96
|
e o tempo restante da issue.
|
|
97
97
|
4. CI vermelho → o log falho pela stdin de `pipeline-cmd.sh ci-cause` dá os candidatos `arquivo:linha`, depois diagnostique e corrija; review/threads → leia [`threads.md`](../../drain/references/threads.md), emita `THREAD:` / `RESOLVED:`, verifique a linha que resolve antes de responder/resolver.
|
|
98
98
|
5. Refaça gate, stage, commit e `push-pr.sh`; volte ao passo 2.
|
|
99
|
-
6. Review rate limited
|
|
99
|
+
6. Review rate limited ou skipped não é review: cubra o head pela casa, pelo procedimento de
|
|
100
100
|
[`coverage.md`](../../../references/coverage.md), e registre com `pipeline-cmd.sh cov-comment`.
|
|
101
101
|
Fix REAL da passada: gate verde, commit e `push-pr.sh` — o head muda, então volte ao passo 2
|
|
102
102
|
deste ciclo (CI e review de novo) e cubra o head novo antes de avaliar o `GOAL:`.
|
|
103
103
|
O bot revisou o head sem aprovar (só o `6 APPROVED` pendente, bot `success`, e o full-review
|
|
104
104
|
responde `já postado após o head`) é o gatilho 2 do mesmo procedimento: cubra e registre igual.
|
|
105
|
+
`VEREDITO: review skipped` (o bot pulou o head, PR de bot sem vaga de review) é o gatilho 3:
|
|
106
|
+
cubra no mesmo ciclo, sem esperar janela nem pingar.
|
|
105
107
|
Falha de leitura é indeterminada, não ausência. Thread escalada ao Mestre permanece aberta.
|
|
106
108
|
|
|
107
109
|
O objetivo é `GOAL: atingido` de `pr-goal.sh`. `babysit` para sem merge por `GOAL: atingido`,
|