fix(pipeline-status): match full receipt pattern in check_memory #21

Merged
slaid098 merged 3 commits from fix/check-memory-receipt-pattern into main 2026-08-07 14:01:57 +03:00
Owner

Что сделано

  • pipeline-status.py:check_memory (строки 702–723): заменён substring-поиск pattern in f.read_text() на regex full-match receipt-формата re.compile(rf"- \[\d{{4}}-\d{{2}}-\d{{2}}, PR#{pr_number}\]"). Теперь требуется полная квитанция - [YYYY-MM-DD, PR#N] — префикс - [date, и закрывающая ] после номера.
  • tests/test_pipeline_status.py: добавлены 3 regression-теста в секцию # ── check_memory ───:
    • test_check_memory_no_substring_collision — PR#180 в файле, check_memory(18) → NOT_DONE
    • test_check_memory_no_adr_ref_match — ADR-ref (PR#18) без receipt, check_memory(18) → NOT_DONE
    • test_check_memory_matches_real_receipt — реальный receipt - [2026-08-07, PR#18] — durable: ..., check_memory(18) → DONE
  • .opencode/agents/reviewer.md секция ## Known deterministic links: обновлены обе записи (строки 406–408 и 411–413) — «expects PR#N literal» → «expects - [YYYY-MM-DD, PR#N] receipt pattern (regex, full match)».

Почему

После миграции репо с GitHub (PR до ~#290) на Forgejo (нумерация с #1) детектор pattern in f.read_text() (бессодержательный substring-поиск) коллидировал: (a) PR#18 — подстрока PR#180/PR#181/... (22 вхождения в opencode-config.md), (b) PR#18 совпадает со старой GitHub ADR-ref (PR#18) (1 вхождение). В результате check_memory возвращал ложный DONE для всех Forgejo PR #1–#18, и run-pipeline пропускал фазу memory-syncer — durable-знания по этим PR не попадали в память. Regex требует полную квитанцию: ] после номера отсекает подстроки (PR#180 → после 18 идёт 0), префикс - [date, отсекает ADR-ref'ы ((PR#18) → нет префикса, после 18 идёт )).

Watch out

  • Writer memory-syncer.md НЕ менялся — он уже пишет корректный формат - [YYYY-MM-DD, PR#N] <content> (строки 69–83). Reader (pipeline-status.py) просто начал матчить то, что writer давно пишет.
  • get_memory_files() multi-file scan (PR#245 fix) НЕ менялся — regex применяется к тому же списку файлов.
  • Возвращаемые значения остались DONE/NOT_DONE (без AMBIGUOUS) — per PR#245 контракт.
  • Mypy сообщает 3 pre-existing ошибки [type-arg] на строках 92/133/191 (dict без type-args) — не связаны с этой правкой, присутствуют на origin/main (проверено через git stash).
  • Ретроспективный memory-sync для Forgejo PR #1–#17 вне scope (per issue #20: «только fix, без retro»).

Pending

  • MEMORY-фаза этого PR будет первым корректным receipt'ом под новым regex.

Closes #20

## Что сделано - `pipeline-status.py:check_memory` (строки 702–723): заменён substring-поиск `pattern in f.read_text()` на regex full-match receipt-формата `re.compile(rf"- \[\d{{4}}-\d{{2}}-\d{{2}}, PR#{pr_number}\]")`. Теперь требуется полная квитанция `- [YYYY-MM-DD, PR#N]` — префикс `- [date, ` и закрывающая `]` после номера. - `tests/test_pipeline_status.py`: добавлены 3 regression-теста в секцию `# ── check_memory ───`: - `test_check_memory_no_substring_collision` — `PR#180` в файле, `check_memory(18)` → NOT_DONE - `test_check_memory_no_adr_ref_match` — ADR-ref `(PR#18)` без receipt, `check_memory(18)` → NOT_DONE - `test_check_memory_matches_real_receipt` — реальный receipt `- [2026-08-07, PR#18] — durable: ...`, `check_memory(18)` → DONE - `.opencode/agents/reviewer.md` секция `## Known deterministic links`: обновлены обе записи (строки 406–408 и 411–413) — «expects `PR#N` literal» → «expects `- [YYYY-MM-DD, PR#N]` receipt pattern (regex, full match)». ## Почему После миграции репо с GitHub (PR до ~#290) на Forgejo (нумерация с #1) детектор `pattern in f.read_text()` (бессодержательный substring-поиск) коллидировал: (a) `PR#18` — подстрока `PR#180`/`PR#181`/... (22 вхождения в `opencode-config.md`), (b) `PR#18` совпадает со старой GitHub ADR-ref `(PR#18)` (1 вхождение). В результате `check_memory` возвращал ложный DONE для всех Forgejo PR #1–#18, и `run-pipeline` пропускал фазу memory-syncer — durable-знания по этим PR не попадали в память. Regex требует полную квитанцию: `]` после номера отсекает подстроки (`PR#180` → после `18` идёт `0`), префикс `- [date, ` отсекает ADR-ref'ы (`(PR#18)` → нет префикса, после `18` идёт `)`). ## Watch out - Writer `memory-syncer.md` НЕ менялся — он уже пишет корректный формат `- [YYYY-MM-DD, PR#N] <content>` (строки 69–83). Reader (pipeline-status.py) просто начал матчить то, что writer давно пишет. - `get_memory_files()` multi-file scan (PR#245 fix) НЕ менялся — regex применяется к тому же списку файлов. - Возвращаемые значения остались DONE/NOT_DONE (без AMBIGUOUS) — per PR#245 контракт. - Mypy сообщает 3 pre-existing ошибки `[type-arg]` на строках 92/133/191 (`dict` без type-args) — не связаны с этой правкой, присутствуют на `origin/main` (проверено через `git stash`). - Ретроспективный memory-sync для Forgejo PR #1–#17 вне scope (per issue #20: «только fix, без retro»). ## Pending - MEMORY-фаза этого PR будет первым корректным receipt'ом под новым regex. Closes #20
docs(reviewer): update known deterministic link for receipt pattern
All checks were successful
CI (always) / bootstrap (pull_request) Successful in 6s
CI / bootstrap (pull_request) Successful in 10s
Permission Security Check / check (pull_request) Successful in 12s
CI / complexity (pull_request) Successful in 30s
CI / lint (pull_request) Successful in 31s
CI / typecheck (pull_request) Successful in 33s
CI / test (3.13) (pull_request) Successful in 1m42s
8355c9e7d0
Author
Owner

Code Review Summary

Чистый fix: замена substring-поиска PR#N на regex full-match receipt-формата - [YYYY-MM-DD, PR#N] в check_memory. Корректно решает оба collision-кейса (substring PR#180 vs PR#18, ADR-ref (PR#18)). 3 regression-теста покрывают все сценарии, existing тесты не сломаны (11/11 passed).

Positives

  • Regex корректен: rf"- \[\d{{4}}-\d{{2}}-\d{{2}}, PR#{pr_number}\]" — в f-string {{→{, итоговый regex - \[\d{4}-\d{2}-\d{2}, PR#18\]. \] вне character class — просто literal ], валидно. Проверено вручную: 7 edge cases (substring, ADR-ref, real receipt, empty receipt, single-digit date, multi-digit PR) — все ожидаемые результаты.
  • 3 regression-теста покрывают все 3 collision типа: substring (PR#180), ADR-ref ((PR#18)), positive (real receipt). Моки get_memory_files через monkeypatch.setattr(ps, "get_memory_files", lambda: [memory_file]) — корректные, изолированные, tmp_path обеспечивает clean state.
  • Existing тесты не сломаны: test_check_memory_not_done_no_files (PR#46), test_check_memory_not_done_no_pattern, test_check_memory_not_done_remote_error — все pass.
  • Cross-file impact обработан: writer memory-syncer.md НЕ менялся (строки 69-83 уже пишут - [YYYY-MM-DD, PR#N] <суть>), reader обновлён. reviewer.md Known deterministic links (строки 406-408, 411-413) обновлены консистентно: «expects PR#N literal» → «expects - [YYYY-MM-DD, PR#N] receipt pattern (regex, full match)». Формат memory/SKILL.md:83 и run-pipeline/SKILL.md:124 совпадают с regex.
  • PR body качественный: ## Что сделано / ## Почему / ## Watch out / ## Pending — все заполнены осмысленно, Watch out содержит 5 конкретных пунктов (writer unchanged, multi-file scan unchanged, return values, pre-existing mypy errors, retro out of scope).
  • Error handling сохранён: try/except вокруг get_memory_files() не тронут, return values DONE/NOT_DONE без AMBIGUOUS (per PR#245 контракт).
  • Функция check_memory — 22 строки, well under 50-line limit. re уже импортирован (строка 29), новых импортов нет.

Suggestions (info, not blocking)

  • .opencode/skills/feature-spec/SKILL.md:125,132 [docs] Pre-existing: ссылается на get_memory_file_path() (старое имя функции, теперь get_memory_files()). Не в scope этого PR, но стоит обновить в отдельном PR — может запутать при feature-spec анализе.

Verdict: APPROVE

## Code Review Summary Чистый fix: замена substring-поиска `PR#N` на regex full-match receipt-формата `- [YYYY-MM-DD, PR#N]` в `check_memory`. Корректно решает оба collision-кейса (substring `PR#180` vs `PR#18`, ADR-ref `(PR#18)`). 3 regression-теста покрывают все сценарии, existing тесты не сломаны (11/11 passed). ### Positives - **Regex корректен**: `rf"- \[\d{{4}}-\d{{2}}-\d{{2}}, PR#{pr_number}\]"` — в f-string `{{`→`{`, итоговый regex `- \[\d{4}-\d{2}-\d{2}, PR#18\]`. `\]` вне character class — просто literal `]`, валидно. Проверено вручную: 7 edge cases (substring, ADR-ref, real receipt, empty receipt, single-digit date, multi-digit PR) — все ожидаемые результаты. - **3 regression-теста покрывают все 3 collision типа**: substring (`PR#180`), ADR-ref (`(PR#18)`), positive (real receipt). Моки `get_memory_files` через `monkeypatch.setattr(ps, "get_memory_files", lambda: [memory_file])` — корректные, изолированные, `tmp_path` обеспечивает clean state. - **Existing тесты не сломаны**: `test_check_memory_not_done_no_files` (PR#46), `test_check_memory_not_done_no_pattern`, `test_check_memory_not_done_remote_error` — все pass. - **Cross-file impact обработан**: writer `memory-syncer.md` НЕ менялся (строки 69-83 уже пишут `- [YYYY-MM-DD, PR#N] <суть>`), reader обновлён. `reviewer.md` Known deterministic links (строки 406-408, 411-413) обновлены консистентно: «expects `PR#N` literal» → «expects `- [YYYY-MM-DD, PR#N]` receipt pattern (regex, full match)». Формат `memory/SKILL.md:83` и `run-pipeline/SKILL.md:124` совпадают с regex. - **PR body качественный**: `## Что сделано` / `## Почему` / `## Watch out` / `## Pending` — все заполнены осмысленно, `Watch out` содержит 5 конкретных пунктов (writer unchanged, multi-file scan unchanged, return values, pre-existing mypy errors, retro out of scope). - **Error handling сохранён**: try/except вокруг `get_memory_files()` не тронут, return values DONE/NOT_DONE без AMBIGUOUS (per PR#245 контракт). - **Функция `check_memory` — 22 строки**, well under 50-line limit. `re` уже импортирован (строка 29), новых импортов нет. ### Suggestions (info, not blocking) - **.opencode/skills/feature-spec/SKILL.md:125,132** [docs] Pre-existing: ссылается на `get_memory_file_path()` (старое имя функции, теперь `get_memory_files()`). Не в scope этого PR, но стоит обновить в отдельном PR — может запутать при feature-spec анализе. ### Verdict: APPROVE
slaid098 deleted branch fix/check-memory-receipt-pattern 2026-08-07 14:01:58 +03:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/opencode-config!21
No description provided.