feat(memory-save): self-healing Forgejo auth bridge + non-silent hook #32
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/memory-save-auth-bridge"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что сделано
Реализован self-healing git auth bridge для Forgejo (issue #31):
memory-save.ts):ensureForgejoBridge()— автоматически создаётinsteadOf-правило изFORGEJO_TOKEN/FORGEJO_URLпри каждомmemory-save. Идемпотентно (не переписывает корректное правило), пропускается без env, токен маскируется как***в steps.memory-save.ts): post-commit hook теперь non-silent —2>/dev/nullубран, ошибки push выводятся в stderr как[memory] push failed (non-fatal). Старый hook мигрируется при следующемmemory-save.memory-doctor.ts):checkForgejoBridge()отображает ✓/✗ статус insteadOf-моста рядом сOPENCODE_MEMORY_REMOTE.test_memory_save_tool.py(11 тестов — bridge create/idempotent/skip/mask/trailing-slash/rotation + hook non-silent/migration),test_memory_doctor_tool.py(6 тестов — bridge present/missing/stale-token/skipped/trailing-slash).tests/_ts_loader.mjs: добавлена поддержкаos/fs/spawn/node:moduleмодулей иimport.meta.url/arrow-function type annotations/export interface— нужно для загрузки memory-tools через loader.Почему
При миграции с GitHub на Forgejo (ADR-093) вместоOf-правило для GitHub удалили, но для Forgejo не создали.
git pushпадал с 401, а post-commit hook тихо глотал ошибки (2>/dev/null || true) — 29 коммитов накопилось локально за сутки. Bridge делает авторизацию self-healing: переживает стирание~/.gitconfig, работает для всех репо глобально. Non-silent hook делает сбой sync видимым сразу.Watch out
_ts_loader.mjsизменён — добавлены strip-правила дляimport os,import fs(default),import { spawn, spawnSync },node:module,import.meta.url,export interface, arrow-function type annotations. Все существующие 821 тестов проходят (регрессии нет).ensureForgejoBridgeиспользует--add(не--replace-all) — при ротации токена старое правило остаётся в gitconfig (git суммирует вместоOf-правила, но doctor пометит мост как ✗ если не найдёт точный match). Это сознательное решение:--addбезопаснее, не затирает чужие правила.encodeURIComponent— спецсимволы (/,+) в токене обрабатываются.Pending
— Обновление AGENTS.md (раздел
## Git Host) — указать что insteadOf-мост создаётся автоматически. Вне scope этой задачи (issue #31 не упоминает AGENTS.md как обязательное).— Обновление
.env.exampleкомментария дляOPENCODE_MEMORY_REMOTE— вне scope.Closes #31
Code Review Summary
PR #32 (feat: self-healing Forgejo auth bridge + non-silent hook) — reviewed.
Что проверено
Security (критично)
stepsarraymemory-save— маскируется как***(verified вensureForgejoBridge())memory-doctorаналогично маскирует токен в выводеencodeURIComponent— корректно для спецсимволовИдемпотентность + Guard
FORGEJO_TOKEN/FORGEJO_URLне заданы → мост пропускается, не падает, не warnsHook migration
2>/dev/null || true) перезаписывается новым при следующемmemory-save[memory] push failed (non-fatal), commit не фейлитсяmemory-doctor
checkForgejoBridge()показывает ✓/✗ для insteadOf-моста рядом сOPENCODE_MEMORY_REMOTEcheckТесты (17 новых)
test_memory_save_tool.py+ 6 вtest_memory_doctor_tool.pyCross-file impact
pipeline-status.py,spec-status.py,project-status.py—parse_remote_urlregex(?:[^/@]*@)?уже обрабатывает insteadOf-rewritten URLs. No breakage.Warnings (non-blocking)
tests/_ts_loader.mjs:94— regexspawn(?:Sync)?конвертируетimport { spawn, spawnSync }вconst { spawnSync, spawnSync }(spawn потерян). Latent: RAG reindex disabled в тестах (OPENAI_BASE_URL=""), spawn не вызывается. Фикс: handle both orders.memory-save.ts:41—git config --addreturn status не проверяется. Minor:memory-doctorдетектит missing bridge позже.Info (suggestions)
memory-save.ts:30/memory-doctor.ts:117— hardcodedslaid098username. Could beFORGEJO_USERenv var (but consistent with repo owner now).Verdict: APPROVE — PR well-implemented, security handled, tests comprehensive. Warnings non-blocking.
Verdict: APPROVE