* fix(create-readme): resolve file_path against context.worktree * test(loader): support fs imports and extended TS stripping * test(create-readme): add regression tests for local overwrite * docs(repo-readme): note file_path resolves against worktree * docs(handoff): set PR number --------- Co-authored-by: opencode-agent <agent@opencode.local>
3.6 KiB
ADR-073: create-readme local-mode path resolution via context.worktree
Статус
Accepted (2026-07-31)
Контекст
Тулза create-readme (.opencode/tools/create-readme.ts) работает в двух
режимах: локальном (file_path, без repo) и удалённом (repo: owner/name
через gh api). В удалённом режиме spawnSync вызовы корректно передавали
cwd: context.worktree — рабочую директорию сессии пользователя. В локальном
режиме writeFileSync(file_path, ...) / readFileSync(file_path, ...)
вызывались с относительным file_path (default README.md), который
резолвился относительно CWD процесса плагина Bun, а не относительно
context.worktree. В продакшене CWD плагина ≠ рабочая директория
пользователя — файл писался/читался не туда, отчёт README.md created at README.md был ложным success (issue #148).
Асимметрия: spawnSync получал cwd, а fs.*Sync — нет. Тестовый лоадер
tests/_ts_loader.mjs не поддерживал import { readFileSync, writeFileSync } from "fs" и расширенный TS-синтаксис (многострочные type-алиасы, non-null
assertions, type annotations в переменных) — локальный режим тулзы нельзя
было протестировать.
Решение
-
Резолв пути относительно worktree:
const absPath = path.resolve(context.worktree, file_path)— симметрично сspawnSyncв удалённом режиме.writeFileSync(absPath, ...)/readFileSync(absPath, ...)работают с абсолютным путём. Существующий файл гарантированно перезаписывается. -
Расширение
_ts_loader.mjs:stripTsтеперь обрабатываетfsимпорты, многострочныеtype X = { ... }, type annotations вconst/let/var, non-null assertionsx!.loadTool(spawnSyncImpl, fsImpl)передаётfsмодуль в sandbox. Это открывает возможность тестировать любую тулзу, использующуюfsв локальном режиме.
Альтернативы
-
process.chdir(context.worktree)в началеexecute(): меняло бы CWD процесса, но побочные эффекты на другие тулзы в том же процессе неприемлемы (гонки, неявное состояние). Отвергнуто. -
Передача
file_pathкак абсолютного всегда (валидировать на входе): ломало бы существующие вызовы с относительнымfile_path(defaultREADME.md).path.resolve(worktree, file_path)прозрачно обрабатывает оба случая (относительный → относительно worktree; абсолютный → как есть). -
Не расширять лоадер, тестировать только через интеграцию: медленнее, хрупче, не ловит регрессии на уровне
execute(). Расширение лоадера позволяет точечные unit-тесты с реальнымfsво временных директориях.