opencode-config/docs/decisions/073-pr-175-overwrite-existing-local-readme.md
Sergey 4258621def
fix(repo-readme): create mode does not overwrite existing local README (#175)
* 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>
2026-07-31 21:10:29 +03:00

52 lines
No EOL
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 в переменных) — локальный режим тулзы нельзя
было протестировать.
## Решение
1. **Резолв пути относительно worktree**: `const absPath =
path.resolve(context.worktree, file_path)` — симметрично с `spawnSync`
в удалённом режиме. `writeFileSync(absPath, ...)` / `readFileSync(absPath,
...)` работают с абсолютным путём. Существующий файл гарантированно
перезаписывается.
2. **Расширение `_ts_loader.mjs`**: `stripTs` теперь обрабатывает `fs`
импорты, многострочные `type X = { ... }`, type annotations в
`const/let/var`, non-null assertions `x!`. `loadTool(spawnSyncImpl,
fsImpl)` передаёт `fs` модуль в sandbox. Это открывает возможность
тестировать любую тулзу, использующую `fs` в локальном режиме.
## Альтернативы
- **`process.chdir(context.worktree)` в начале `execute()`**: меняло бы CWD
процесса, но побочные эффекты на другие тулзы в том же процессе
неприемлемы (гонки, неявное состояние). Отвергнуто.
- **Передача `file_path` как абсолютного всегда (валидировать на входе)**:
ломало бы существующие вызовы с относительным `file_path` (default
`README.md`). `path.resolve(worktree, file_path)` прозрачно обрабатывает
оба случая (относительный → относительно worktree; абсолютный → как есть).
- **Не расширять лоадер, тестировать только через интеграцию**: медленнее,
хрупче, не ловит регрессии на уровне `execute()`. Расширение лоадера
позволяет точечные unit-тесты с реальным `fs` во временных директориях.