E10 · The batch in the rehearsal
10 minRun both rehearsal blocks.
Done when: the first shows approval_due=true and requested=true; the second ends with check: 0, check: 1 (after changing serve.sh) and check: 0.
Lesson 4 · 20 min
The other side of the loop that learns is not a number: it is the lesson the agent draws from a mistake. Written straight into CLAUDE.md, it only grows, and nobody decides on it or reviews it. In this lesson you use SIL Loop R: occurrence, proposal, batch approval with an explicit decision, and automatic review when the rule's file changes.
Start the lesson
Goal: record an occurrence and a proposal in SIL Loop R, approve in batch with an explicit decision, and reopen the rule when the watched file changes.
sil.py 1.1.0, local SQLite in the project's .sil folder. No command sends a message or calls a model. Click each block.
Source: sil-loop-r/skills/sil-loop-r/SKILL.md and sil.py --help (v1.1.0, commit 63746bd, 10/05/2026).
Rehearsal project in /tmp. The j only prints the JSON fields that sil.py returns.
SIL=~/projetos/sil-loop-r/sil.py # git clone https://github.com/inematds/sil-loop-r ~/projetos/sil-loop-r
E=${TMPDIR:-/tmp}/ensaio-aprende/a4; rm -rf $E; mkdir -p $E/p; cd $E/p && git init -q
echo 'python3 -m http.server 8000' > serve.sh
s() { python3 $SIL --project $E/p "$@"; }
j() { python3 -c 'import json,sys; d=json.load(sys.stdin); print(*[k+"="+json.dumps(d.get(k),ensure_ascii=False) for k in sys.argv[1:]])' "$@"; }
s init | j version; s config --approval-batch 2 | j approval_batch
s occurrence --title "porta ocupada" --evidence "teste HTTP falhou: address already in use" \
--cause "servidor de outra sessão na mesma porta" --correction "checar a porta antes" | j id
s lesson --occurrence O0001 --proposal "checar a porta antes de subir servidor" --scope "testes HTTP" --watch serve.sh | j id status
s occurrence --title "push no remoto errado" --evidence "git push foi para origin, não para o remoto da conta" | j id
s lesson --occurrence O0002 --proposal "conferir git remote -v antes do push" --scope "publicação" | j id status
echo "## fim da tarefa: chegou a hora do lote?"; s status | j approval_due approval_reasons
s request | j requestedversion="1.1.0" approval_batch=2 id="O0001" id="L0001" status="proposed" id="O0002" id="L0002" status="proposed" ## fim da tarefa: chegou a hora do lote? approval_due=true approval_reasons=["lote de novas propostas"] requested=true
With the batch set to 2, the second proposal turns on approval_due. From here on, the agent shows the person the ID, proposal, evidence, scope and suggested decision, and waits.
Continues the previous block. One proposal adopted, another on trial for 14 days; then the watched file changes.
SIL=~/projetos/sil-loop-r/sil.py
E=${TMPDIR:-/tmp}/ensaio-aprende/a4; cd $E/p # continua o bloco anterior
s() { python3 $SIL --project $E/p "$@"; }
j() { python3 -c 'import json,sys; d=json.load(sys.stdin); print(*[k+"="+json.dumps(d.get(k),ensure_ascii=False) for k in sys.argv[1:]])' "$@"; }
ATE=$(python3 -c 'import datetime; print(datetime.date.today() + datetime.timedelta(days=14))')
s decide L0001 adopt --approved-by "Seu Nome" --reason "falhou duas vezes; correção comprovada" | j status rule
s decide L0002 trial --until $ATE --criterion "nenhum push no remoto errado em 14 dias" \
--approved-by "Seu Nome" --reason "uma ocorrência só" | j status
s check > /dev/null; echo "check: $?"
echo "## o arquivo vigiado mudou"; echo 'python3 -m http.server 8080' > serve.sh
s check | j reviews; s check > /dev/null; echo "check: $?"
s review R0001 keep --approved-by "Seu Nome" --reason "a porta mudou; a regra continua valendo" | j status
s check > /dev/null; echo "check: $?"status="adopted" rule="R0001"
status="trial"
check: 0
## o arquivo vigiado mudou
reviews=[{"id": "R0001", "reasons": ["arquivo alterado: serve.sh"]}]
check: 1
status="active"
check: 0check exits 0 with nothing pending, 1 with something pending (here, the review) and 2 on error. Exit 0 does not prove the rules are true; only that nothing is overdue.
Trial with a past date: decide L0002 trial --until 2026-10-01 answers {"error": "Teste e adiamento exigem data futura."} (captured on 10/19/2026). That is why the block calculates the date with Python.
INEMA uses LESSONS.md, FALHAS.md and LIMITES.md in the wifi project (the monitoring hub). Counts only; no line from the files appears here.
The sil-melhoramento/ANALISE.md analysis counted 37 lessons in wifi's CLAUDE.md, 101 lines in FALHAS.md and 255 in LIMITES.md, 49 still "aberto".
Its conclusion: 100% "prose" rung, no triage, no ID, no citation and no pruning. The lesson about a busy port had been written three times on different dates.
contar-licoes.py, run in the wifi folder: 164 lessons in LESSONS.md (9 marked as repeated, none with an ID), 167 failures and 424 limits, 115 still "aberto".
In 14 days the open ones more than doubled. That is what happens when a lesson comes in without a decision and without a review date.
Of the analysis recommendations, only the SIL promotion was done (v1.1.0, 10/05). The others (ports hook, clock in LIMITES, IDs on lessons, post-translation probe) remain proposals.
SIL has not been started in wifi yet: the case serves as a diagnosis, not a showcase.
Run it in your project folder. The script only counts lines and marks; it does not print content.
K=~/projetos/loop-r-eng-aprende-v72/kit cd ~/projetos/<your-project> # the folder where your CLAUDE.md/AGENTS.md and your lessons live python3 $K/contar-licoes.py .
CLAUDE.md: 82 linhas, 19 lições na seção Lessons AGENTS.md: 10 linhas, 0 lições na seção Lessons LESSONS.md: 164 lições · 9 marcadas como repetidas · 0 com ID FALHAS.md: 167 falhas · 90 prompt · 85 infra (as duas contam quando a linha diz as duas) LIMITES.md: 424 limites · 115 ainda 'aberto' SIL Loop R: não iniciado nesta pasta degrau: prosa — sem decisão registrada, sem data de revisão, sem citação
The prompt and infra columns add up to more than the total because 8 lines say both.
Rehearsal first, then your project.
Run both rehearsal blocks.
Done when: the first shows approval_due=true and requested=true; the second ends with check: 0, check: 1 (after changing serve.sh) and check: 0.
Run contar-licoes.py in your project and note how many lessons exist, how many are repeated, and whether any has an ID or review date.
Done when: python3 $K/contar-licoes.py . prints the SIL Loop R: line and at least one count line.
Start the SIL in your project, take the three lessons that repeat the most, and record each one as occurrence + proposal, with --watch on the file the rule protects. When the batch kicks in, decide yourself, with a reason.
Done when: python3 $SIL --project . export | python3 -c 'import json,sys; print(len(json.load(sys.stdin)["rules"]))' → at least 1, and python3 $SIL --project . check; echo $? → 0.
Question 1 of 5
The approval batch arrived and the person did not respond. What does the agent do?skill
Question 2 of 5
Which of these sends an active rule back to review in the SIL?skill
Question 3 of 5
What does a trial require that adoption does not?
Question 4 of 5
The check exited with 0. What does that guarantee?
Question 5 of 5
In the wifi case, what shows that a lesson in prose alone does not close the loop?
Choose an answer. The explanation appears after you try.