Skip to content

fix(hooks): count HH:MM memory.md rows so the stop reminder can clear - #64

Open
meketreve wants to merge 1 commit into
cytostack:mainfrom
meketreve:fix/semantic-summary-detection
Open

fix(hooks): count HH:MM memory.md rows so the stop reminder can clear#64
meketreve wants to merge 1 commit into
cytostack:mainfrom
meketreve:fix/semantic-summary-detection

Conversation

@meketreve

Copy link
Copy Markdown
Contributor

The bug

The stop hook prints this on every stop, forever, no matter how many summaries have been written:

ACTION REQUIRED: N files were modified this session but no semantic summary was written to memory.md. Append a one-line summary: | HH:MM | description | file(s) | outcome | ~tokens |

countSemanticEntries counts only rows starting with | YYYY-MM-DD, and nothing in the codebase writes rows in that shape:

where format
src/templates/OPENWOLF.md:41 documents | HH:MM | description | file(s) | outcome | ~tokens |
src/hooks/stop.ts:297 the reminder text asks for | HH:MM | ... |
src/hooks/stop.ts:197 the hook's own rows: `| ${timeShort()} | Session end: ...`
src/hooks/session-start.ts:147 sessions are delimited by ## Session: YYYY-MM-DD HH:MM

So the count is always 0. Following the reminder's own instructions can never satisfy its check — the agent writes a summary, the reminder fires again, and the loop repeats until someone reads the source.

The fix

Decide "today" from the enclosing ## Session: header instead of from the row, then count non-mechanical | HH:MM | rows inside today's block.

Two properties kept deliberately:

  • rows with an explicit | YYYY-MM-DD | prefix still count — nothing that already worked regresses;
  • rows from an earlier session still don't count — a naive "accept any HH:MM row" would break the check the other way, and the reminder would never fire again once memory.md had a single entry.

The mechanical-row filter is unchanged, so the hook's own Created / Edited / Multi-edited / Session end: / designqc: rows are still excluded.

Tests

New tests/semantic-entries.test.ts, in the style of tests/token-measurement.test.ts. Two cases fail on the old implementation and pass on the new one; the other four pass on both and pin the surrounding behaviour so this can't silently loosen:

case old new
HH:MM row inside today's session block ✖ 0 ✔ 1
stacked sessions — only today's rows counted ✖ 1 ✔ 2
mechanical rows ignored ✔ 0 ✔ 0
rows from an earlier session ✔ 0 ✔ 0
explicit | YYYY-MM-DD | row ✔ 1 ✔ 1
missing memory.md ✔ 0 ✔ 0

Verification

Linux (WSL2), Node 24:

  • node --test tests/*.test.ts32/32 pass
  • tsc --noEmit -p tsconfig.hooks.json → clean

Behaviour change is confined to countSemanticEntries; its only caller is checkSemanticSummaries in src/hooks/stop.ts, which is unchanged.

`countSemanticEntries` only counted rows starting with `| YYYY-MM-DD`, but
nothing writes rows in that shape:

- `src/templates/OPENWOLF.md` documents `| HH:MM | description | file(s) |
  outcome | ~tokens |`
- the stop-hook reminder itself asks for `| HH:MM | ... |` (stop.ts)
- the hook writes its own rows that way too (`| ${timeShort()} | Session end:
  ... |`, stop.ts)
- sessions are delimited by `## Session: YYYY-MM-DD HH:MM` headers
  (session-start.ts)

So the count was always 0 and the stop hook emitted "ACTION REQUIRED: N files
were modified this session but no semantic summary was written to memory.md" on
every single stop, no matter how many summaries the agent had written. Following
the reminder's own instructions could never satisfy its check.

Decide "today" from the enclosing `## Session:` header instead of from the row,
and count non-mechanical `| HH:MM |` rows inside today's session block. Rows with
an explicit `| YYYY-MM-DD` prefix still count, so nothing that already worked
regresses, and rows from an earlier session still don't — otherwise the reminder
would go the other way and never fire again once memory.md had any entry.

Tests cover both directions: the two new cases fail on the old implementation
(HH:MM row today, and stacked sessions) and the other four pass on both, pinning
the mechanical-row filter, the earlier-session boundary, the explicit-date path
and the missing-file path.

Verified on Linux (WSL2), Node 24: `node --test tests/*.test.ts` 32/32 and
`tsc --noEmit -p tsconfig.hooks.json` clean.
meketreve added a commit to meketreve/logica-em-jogo that referenced this pull request Jul 27, 2026
O aviso "no semantic summary was written to memory.md" repetia a cada stop
porque `countSemanticEntries` só conta linha `| YYYY-MM-DD` e nada escreve
nesse formato — o template, o texto do aviso e as linhas do próprio hook usam
`| HH:MM |`. Corrigido no pacote global (o `pnpm update -g` sobrescreve) e
mandado upstream: cytostack/openwolf#64.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
meketreve added a commit to meketreve/logica-em-jogo that referenced this pull request Aug 3, 2026
STATUS com o diário da sessão e a próxima fase (craft por lista), mais a
ressalva de decidir com o usuário se o F6 (comida) vem antes, depois ou junto:
o F3 nasceu com a inanição limitada a 3 corações por não haver o que comer, e
agora que existe inventário o laço da fome dá pra fechar.

TODO ganhou a regra de vegetação que o usuário pediu para registrar — e, ao
registrar, apareceu o buraco de verdade: precisaApoio() JÁ lista grama alta,
mas GramaAlta/Seca/Fria (179-181) não estão no rulesMap, então o capim flutua
hoje. Fica anotado com o fix (um for de 3 ids apontando pro torchRule), não
implementado, porque o pedido era registrar.

Cinco bugs no buglog:

- 549: changedThisTick.size como detector de "o mundo mudou" (Set dedupe por
  coordenada ⇒ bloco infinito por quebrar e recolocar a mesma célula no mesmo
  tick).
- 550: grade de 9 colunas da mochila colapsada sem width: 100%.
- 551: o teste de esforço do F3 colocava um bloco e o F4 passou a exigir
  tê-lo — virou quebra, que cobra o mesmo.
- 552: o cenário de mochila cheia do smoke não enchia a mochila (cheia é por
  PILHA e por ID, não por slot).
- 553: o ?mochila= era apagado pelo `modo criativo` que todo join manda.

Cerebrum com seção nova de Ferramentas e ambiente, e o que ela guarda vale
além deste projeto: escrever arquivo vigiado por hook pela ferramenta
Write/Edit, nunca por heredoc no Bash (o stop.js olha session.files_written e
não enxerga escrita via shell); e o aviso "no semantic summary" é
insatisfazível — countSemanticEntries conta linhas que começam com
| YYYY-MM-DD, mas o formato que o próprio aviso pede é | HH:MM. É o que o PR
upstream cytostack/openwolf#64 corrige, e o TODO agora registra o mecanismo,
não só o sintoma.

Mais três aprendizados de arquitetura: o detector de edição é contador e não
tamanho de Set; um bloco tem BYTE e tem ITEM, e não são o mesmo número; e o
que o servidor NÃO manda também é informação (a ausência de `inventario` é o
que significa "paleta infinita", mesmo desenho do campo fome ausente no F3).

.wolf/backups/ foi pro .gitignore no commit anterior: são cópias por sessão do
que já é versionado, 3 MB por rodada.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
meketreve added a commit to meketreve/logica-em-jogo that referenced this pull request Aug 3, 2026
Os dois avisos de `stop` dispararam a cada turno da sessão 36 com o trabalho já
feito. Diagnosticados agora, nenhum corrigido — o usuário cuida disso na
próxima sessão, e o STATUS avisa para não obedecer cegamente (escrever de novo
só duplica diário e buglog).

Corrige de passagem o que eu tinha registrado errado mais cedo: o PR upstream
cytostack/openwolf#64 JÁ ENTROU e já está na 2.0.1 instalada — o comentário
dele está no countSemanticEntries do pacote. A nota antiga dizia que a função
só contava linhas `| YYYY-MM-DD`, o que valia para a versão anterior.

O que realmente acontece hoje:

1. "no semantic summary" fura na virada da MEIA-NOITE (UTC). O fix aceita
   linhas `| HH:MM |` dentro de um bloco `## Session: <hoje>`, mas o header é
   gravado quando a sessão COMEÇA. Sessão que vira o dia fica com a data de
   ontem, inTodaySession nunca é true, e o outro ramo (`| YYYY-MM-DD`) não casa
   porque o formato pedido é `| HH:MM`. Contagem 0 para sempre. Foi o nosso
   caso: `## Session: 2026-08-02 23:34` com o dia já em 08-03.

2. "buglog.json was not updated" é cego a escrita fora das ferramentas.
   checkForMissingBugLogs olha session.files_written, que só recebe Write/Edit;
   os 5 bugs desta sessão foram gravados por python3 no Bash.

STATUS ganhou a seção de alerta com o comando de confirmação em 10 s, o TODO
§🧭 guarda causa e conserto sugerido de cada um, e o cerebrum fica com o
contorno do lado de cá: gravar arquivo vigiado por hook pela FERRAMENTA, nunca
por heredoc.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant