@gian-tiaga/eda 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/install.js +24 -2
- package/package.json +1 -1
- package/skills/eda-send-review.md +59 -33
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ eda update-all ~/Code
|
|
|
47
47
|
| `eda-fix-by-review` | Применяет замечания из ревью. Обязательные — все сразу. Optional-пункты в обычном режиме спрашивает, а в `apply-optional` сам решает: применяет полезные, отклонённые обосновывает в отчёте. В конце ссылается на отчёт прямо в файле ревью | `docs/review-fixes/` |
|
|
48
48
|
| `eda-manual-test` | Делает ручную smoke/acceptance-проверку после изменений: API прогоняет через `curl`/HTTP-запросы, фронт — через Playwright или доступную browser automation. Сам строит чеклист из входа, плана или diff, запускает очевидные dev/API-серверы и сохраняет QA-отчёт. Не правит код, не пишет автотесты и не коммитит | `docs/manual-tests/` |
|
|
49
49
|
| `eda-polish` | Оркестрирует доводку изменений: запускает `eda-review draft`, затем `eda-review-check`, затем `eda-fix-by-review apply-optional` и повторяет цикл до оценки 95/100 или лимита 5 итераций. Обязательные замечания чинятся все, optional-пункты fix-агент применяет или отклоняет сам с обоснованием. Каждый шаг идёт в изолированном субагенте или отдельном CLI-процессе. Не коммитит | `docs/reviews/`, `docs/review-fixes/` |
|
|
50
|
-
| `eda-send-review` | Отправляет ревью на GitHub PR через `gh`
|
|
50
|
+
| `eda-send-review` | Отправляет ревью на GitHub PR через `gh` всегда в едином формате: общий комментарий-сводка плюс комментарии к строкам кода. Тип (`comment`/`approve`/`request-changes`) задаёт только статус review; `approve` и `request-changes` подтверждаются. По умолчанию шлёт все пункты. Сам определяет PR по текущей ветке | (комментарий в PR) |
|
|
51
51
|
| `eda-commit` | Делает один аккуратный коммит в стиле проекта. В конце спрашивает: push, merge в main + удалить ветку, или ничего | (git) |
|
|
52
52
|
| `eda-worktree` | Создаёт git worktree рядом с основным проектом в папке `{name}-work-{n}` и одноимённую ветку. Базу берёт из аргумента или спрашивает | соседняя папка `{name}-work-{n}` |
|
|
53
53
|
| `eda-merge-worktree` | Мержит ветку из соседнего worktree в текущую ветку. Принимает номер `1`, короткое имя `work-1` или полное имя `{name}-work-1`. Worktree и ветку после merge не удаляет | (git) |
|
package/lib/install.js
CHANGED
|
@@ -165,7 +165,7 @@ export async function updateAll({
|
|
|
165
165
|
output.write(`\n=== ${projectLabel} ===\n`);
|
|
166
166
|
|
|
167
167
|
try {
|
|
168
|
-
const targets = await
|
|
168
|
+
const targets = await detectInstalledTargets(projectDir);
|
|
169
169
|
if (targets.length === 0) {
|
|
170
170
|
output.write('Пропускаю: установленные среды исчезли во время обхода.\n');
|
|
171
171
|
skippedProjects.push(projectDir);
|
|
@@ -295,6 +295,28 @@ async function detectTargets(cwd) {
|
|
|
295
295
|
return targets;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
// Среда считается установленной, только если в её папке скилов лежит хотя бы один eda-скил.
|
|
299
|
+
// Используется при массовом обходе (update-all), чтобы не засыпать скилами проекты,
|
|
300
|
+
// где папка .claude/skills или .codex/skills есть, но eda-скилов в ней нет.
|
|
301
|
+
async function detectInstalledTargets(cwd) {
|
|
302
|
+
const targets = [];
|
|
303
|
+
if (await hasInstalledSkill(path.join(cwd, '.claude/skills'))) targets.push('claude');
|
|
304
|
+
if (await hasInstalledSkill(path.join(cwd, '.codex/skills'))) targets.push('codex');
|
|
305
|
+
return targets;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function hasInstalledSkill(skillsDir) {
|
|
309
|
+
let entries;
|
|
310
|
+
try {
|
|
311
|
+
entries = await fs.readdir(skillsDir, { withFileTypes: true });
|
|
312
|
+
} catch (err) {
|
|
313
|
+
if (['ENOENT', 'ENOTDIR', 'EACCES', 'EPERM'].includes(err?.code)) return false;
|
|
314
|
+
throw err;
|
|
315
|
+
}
|
|
316
|
+
// eda-скилы лежат как папка eda-* (новый layout) или файл eda-*.md (старый Codex layout).
|
|
317
|
+
return entries.some(entry => entry.name.startsWith('eda-'));
|
|
318
|
+
}
|
|
319
|
+
|
|
298
320
|
async function syncSkills(cwd, targets, output = process.stdout, { action = 'update', writeDone = true } = {}) {
|
|
299
321
|
const skills = await listSkills();
|
|
300
322
|
if (skills.length === 0) {
|
|
@@ -326,7 +348,7 @@ async function findInstalledProjects(rootDir, maxDepth) {
|
|
|
326
348
|
const projects = [];
|
|
327
349
|
|
|
328
350
|
async function walk(dir, depth) {
|
|
329
|
-
const targets = await
|
|
351
|
+
const targets = await detectInstalledTargets(dir);
|
|
330
352
|
if (targets.length > 0) projects.push(dir);
|
|
331
353
|
if (depth >= maxDepth) return;
|
|
332
354
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gian-tiaga/eda",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Набор скилов eda-* для Claude Code и Codex CLI: start, roadmap, explore, plan, plan-polish, execute, fix, review, review-check, fix-by-review, manual-test, polish, send-review, commit, worktree, merge-worktree, docs, automate",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eda-send-review
|
|
3
|
-
description: 'Отправляет ревью из `docs/reviews/...`, выбранное по тексту рядом с вызовом, на GitHub PR через `gh` —
|
|
3
|
+
description: 'Отправляет ревью из `docs/reviews/...`, выбранное по тексту рядом с вызовом, на GitHub PR через `gh` — всегда в едином формате: общий комментарий-сводка плюс комментарии к строкам кода (inline). Тип отправки (`comment`/`approve`/`request-changes`) задаёт только статус review, но не структуру вывода. По умолчанию отправляет все пункты; если в тексте указано подмножество — только его. Перед отправкой читает `docs/rules.md` и `docs/arch.md` и строго следует им. Целевой PR определяется из текста или по текущей ветке; если PR нет — предлагает создать. После отправки в конец файла ревью дописывает ссылку. Не правит код, не делает само ревью. Вопросы задаёт только когда без ответа нельзя безопасно продолжать.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Скил: Отправитель ревью (eda-send-review)
|
|
7
7
|
|
|
8
|
-
Берёшь готовое ревью из `docs/reviews/`, отправляешь его на GitHub PR через `gh`. В конец файла ревью дописываешь, куда отправил.
|
|
8
|
+
Берёшь готовое ревью из `docs/reviews/`, отправляешь его на GitHub PR через `gh`. Отправляешь **всегда в одном формате**: общий комментарий-сводка плюс комментарии к строкам кода. В конец файла ревью дописываешь, куда отправил.
|
|
9
9
|
|
|
10
10
|
## Вход из сообщения пользователя
|
|
11
11
|
|
|
12
|
-
Текст рядом с вызовом скилла в текущем сообщении пользователя — главный вход. Сначала разбери именно его: тему, задачу, путь к файлу, режим,
|
|
12
|
+
Текст рядом с вызовом скилла в текущем сообщении пользователя — главный вход. Сначала разбери именно его: тему, задачу, путь к файлу, режим, ограничения, какие пункты отправлять и прямые указания.
|
|
13
13
|
|
|
14
14
|
Если этого входа достаточно, продолжай без вопроса. `AskUserQuestion` задавай только если входа нет, он противоречивый, найдено несколько равных вариантов или есть риск выполнить не ту задачу. Старое обсуждение в истории не считай входом, если пользователь не связал его с текущим вызовом явно.
|
|
15
15
|
|
|
16
16
|
## Главные правила
|
|
17
17
|
|
|
18
|
-
1.
|
|
19
|
-
2.
|
|
20
|
-
3.
|
|
21
|
-
4.
|
|
22
|
-
5.
|
|
18
|
+
1. **Единый формат всегда.** Отправляешь как GitHub review: тело — общий комментарий-сводка, а каждое замечание с привязкой к строке — отдельным комментарием к строке кода (inline). Тип отправки меняет только статус review (`event`), но не структуру вывода.
|
|
19
|
+
2. **По умолчанию — все пункты.** Если пользователь не указал, что отправлять, отправляешь все замечания ревью. Если указал подмножество — только его.
|
|
20
|
+
3. **Интерактивные вопросы** — по разделу ниже.
|
|
21
|
+
4. **Прочитай `docs/rules.md` и `docs/arch.md`**, если есть, и строго следуй им при выборе способа отправки и финальной отметке.
|
|
22
|
+
5. **Не правишь код, не делаешь само ревью.** Только переупаковка и отправка.
|
|
23
|
+
6. **Никаких самостоятельных оценок.** Статус review определяется по оценке ревью и тексту пользователя. `approve` и `request-changes` всегда подтверждаются пользователем.
|
|
24
|
+
7. **Простой язык.** В сообщениях пользователю и комментариях PR без лишних терминов.
|
|
23
25
|
|
|
24
26
|
## Интерактивные вопросы
|
|
25
27
|
|
|
@@ -28,61 +30,82 @@ description: 'Отправляет ревью из `docs/reviews/...`, выбр
|
|
|
28
30
|
- Codex interactive: если доступен `request_user_input`, используй его. Если tool недоступен, задай один короткий вопрос в чат, дай варианты 1–3, напиши «Ответь номером или своим вариантом. Я продолжу только после ответа.» и остановись.
|
|
29
31
|
- Codex exec / неинтерактивный запуск: не задавай вопросы и не пытайся читать stdin. Если без ответа нельзя безопасно продолжать, заверши работу со статусом `blocked: нужен ответ пользователя`, перечисли вопросы и варианты, не выполняй рискованные действия.
|
|
30
32
|
- Не запускай команды, которые ждут интерактивного ввода в терминале; перед такими командами спроси в хост-интерфейсе или остановись с `blocked`.
|
|
31
|
-
- Для отправки ревью это правило важнее продолжения: не создавай PR, не отправляй approve/request-changes и не меняй
|
|
33
|
+
- Для отправки ревью это правило важнее продолжения: не создавай PR, не отправляй approve/request-changes и не меняй статус отправки вместо ответа пользователя.
|
|
32
34
|
|
|
33
35
|
## Этапы
|
|
34
36
|
|
|
35
37
|
### 1. Проверить инструменты
|
|
36
38
|
`gh --version` + `gh auth status`. Если `gh` отсутствует или не авторизован — остановись, сообщи и выйди (это пользователю нужно решить).
|
|
37
39
|
|
|
38
|
-
### 2. Выбрать ревью
|
|
39
|
-
Сначала разбери текст рядом с вызовом: путь к ревью, название или часть названия, «последнее ревью», PR (`PR 12`, `#12`) и
|
|
40
|
+
### 2. Выбрать ревью и что отправлять
|
|
41
|
+
Сначала разбери текст рядом с вызовом: путь к ревью, название или часть названия, «последнее ревью», PR (`PR 12`, `#12`) и статус отправки (`comment`, `review-comment`, `approve`, `request-changes`).
|
|
40
42
|
|
|
41
43
|
Если найдено ровно одно ревью — продолжай без вопроса. Если найдено несколько одинаково подходящих ревью — `AskUserQuestion` со списком вариантов. Если входа нет — `AskUserQuestion` со списком последних файлов из `docs/reviews/`. Если `docs/reviews/` отсутствует или пуста — остановись с понятным вопросом или статусом `blocked: нужно ревью`. Прочитай файл целиком: оценку, замечания, рекомендации.
|
|
42
44
|
|
|
45
|
+
**Что отправлять.** По умолчанию — все замечания. Если в тексте указано подмножество, отправь только его. Синтаксис свободный, распознавай по смыслу: по номерам («пункты 1, 3, 5»), по обязательности («только обязательные» → раздел «Править обязательно»), по типу («только security» → замечания с этим `Тип`). Выбор влияет и на сводку, и на комментарии к строкам.
|
|
46
|
+
|
|
43
47
|
### 3. Найти целевой PR
|
|
44
48
|
Если номер PR указан в тексте пользователя — используй его. Иначе попробуй `gh pr view --json number,url,headRefName` — если у текущей ветки уже есть PR, возьми его номер.
|
|
45
49
|
|
|
46
50
|
Если PR нет — `AskUserQuestion`: «PR ещё нет: создать PR из текущей ветки / указать номер существующего PR / прервать». При создании используй `gh pr create` (заголовок и тело — по последним коммитам ветки).
|
|
47
51
|
|
|
48
|
-
### 4. Выбрать
|
|
49
|
-
|
|
52
|
+
### 4. Выбрать статус review
|
|
53
|
+
Review отправляется всегда; здесь выбирается только его статус (`event`).
|
|
54
|
+
|
|
55
|
+
| Условие | event | Подтверждение |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| score ≥ 80 (или в тексте `approve`) | `APPROVE` | всегда `AskUserQuestion` |
|
|
58
|
+
| score < 50 (или в тексте `request-changes`) | `REQUEST_CHANGES` | всегда `AskUserQuestion` |
|
|
59
|
+
| иначе (или в тексте `comment` / `review-comment`) | `COMMENT` | без подтверждения |
|
|
60
|
+
|
|
61
|
+
`comment` и `review-comment` означают review без статуса (`event=COMMENT`) — обычный комментарий-ревью, который тоже несёт сводку и комментарии к строкам. `approve` и `request-changes` подтверждай через `AskUserQuestion` всегда, даже если указаны в тексте. Если предложенный статус противоречит ревью — `AskUserQuestion`: подтвердить / выбрать другой.
|
|
50
62
|
|
|
51
|
-
|
|
63
|
+
### 5. Собрать сводку и комментарии к строкам
|
|
64
|
+
Из выбранных пунктов собери две части.
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
Структура комментария:
|
|
66
|
+
**Сводка** — тело review:
|
|
55
67
|
|
|
56
68
|
```markdown
|
|
57
69
|
## Ревью: <заголовок>
|
|
58
70
|
|
|
59
71
|
**Оценка:** N/100. <одно-два предложения почему>
|
|
60
72
|
|
|
61
|
-
|
|
62
|
-
1. **[тип]** `path/file.py:42` — <что не так>. → <что предлагаешь>
|
|
63
|
-
2. ...
|
|
73
|
+
<короткое резюме: что отправлено и общий вывод>
|
|
64
74
|
|
|
65
75
|
### Рекомендации
|
|
66
76
|
- **Править обязательно:** 1, 3, 5
|
|
67
77
|
- **На усмотрение автора:** 2, 4
|
|
68
|
-
|
|
78
|
+
|
|
79
|
+
### Замечания вне diff
|
|
80
|
+
1. **[тип]** `path/file.py:42` — <что не так>. → <что предлагаешь>
|
|
69
81
|
|
|
70
82
|
_Сгенерировано из `<путь к docs/reviews/...>`_
|
|
71
83
|
```
|
|
72
84
|
|
|
85
|
+
Раздел «Замечания вне diff» добавляй только если такие пункты есть (см. ниже); иначе опусти его.
|
|
86
|
+
|
|
87
|
+
**Комментарии к строкам** — по одному на каждое отправляемое замечание, чьё `Где: path:line` входит в diff PR. Для каждого: `{ "path": "<path>", "line": <line>, "side": "RIGHT", "body": "<суть простым языком + рекомендация + как исправить>" }`. Для замечания об удалённой строке используй `"side": "LEFT"`.
|
|
88
|
+
|
|
89
|
+
Какие строки входят в diff — определи по `gh pr diff <num>`. Замечания, чьи строки в diff не попали (или без `path:line`), в комментарии к строкам **не** клади — перенеси их в раздел «Замечания вне diff» сводки, чтобы ничего не потерялось.
|
|
90
|
+
|
|
73
91
|
### 6. Отправить
|
|
74
|
-
|
|
92
|
+
Тело сводки и комментарии собери в один JSON через `mktemp`:
|
|
75
93
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
| request-changes | `gh pr review <num> --request-changes --body-file <tmpfile>` |
|
|
94
|
+
```json
|
|
95
|
+
{ "body": "<сводка>", "event": "COMMENT|APPROVE|REQUEST_CHANGES", "comments": [ { "path": "...", "line": 42, "side": "RIGHT", "body": "..." } ] }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Отправь одним вызовом Reviews API:
|
|
82
99
|
|
|
83
|
-
|
|
100
|
+
```bash
|
|
101
|
+
OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
102
|
+
gh api "repos/$OWNER_REPO/pulls/<num>/reviews" --method POST --input <payload.json>
|
|
103
|
+
```
|
|
84
104
|
|
|
85
|
-
|
|
105
|
+
Fallback'ы:
|
|
106
|
+
- API упал с `422` из-за конкретных строк — перенеси эти пункты в раздел «Замечания вне diff» сводки и переотправь без них.
|
|
107
|
+
- У цели нет diff/строк PR вовсе (нечего привязывать) — отправь только сводку обычным комментарием: `gh pr comment <num> --body-file <tmpfile>`.
|
|
108
|
+
- Другая ошибка — покажи вывод пользователю и спроси через `AskUserQuestion` (повторить / другой статус / прервать).
|
|
86
109
|
|
|
87
110
|
### 7. Дописать ссылку в файл ревью
|
|
88
111
|
В конец `$REVIEW_FILE` добавь:
|
|
@@ -90,16 +113,19 @@ _Сгенерировано из `<путь к docs/reviews/...>`_
|
|
|
90
113
|
```markdown
|
|
91
114
|
## Отправлено
|
|
92
115
|
- PR: <URL из ответа gh>
|
|
93
|
-
-
|
|
116
|
+
- Статус: <comment | approve | request-changes>
|
|
117
|
+
- Отправлено пунктов: <сколько / inline + сколько в сводке>
|
|
94
118
|
- Дата: <YYYY-MM-DD HH:MM>
|
|
95
119
|
```
|
|
96
120
|
|
|
97
121
|
### 8. Финал
|
|
98
|
-
Короткое сообщение: PR-номер и URL,
|
|
122
|
+
Короткое сообщение: PR-номер и URL, статус отправки, сколько пунктов ушло комментариями к строкам и сколько в сводку, путь к файлу ревью.
|
|
99
123
|
|
|
100
124
|
## Чего НЕ делать
|
|
101
125
|
- Делать само ревью или править замечания — это `eda-review` / `eda-fix-by-review`.
|
|
102
|
-
- Отправлять
|
|
103
|
-
-
|
|
126
|
+
- Отправлять всё одним обычным комментарием PR, когда строки можно привязать к diff — обычный комментарий только fallback при отсутствии diff.
|
|
127
|
+
- Терять замечания вне diff — они идут в сводку отдельным разделом.
|
|
128
|
+
- Отправлять `approve` или `request-changes` без явного подтверждения через `AskUserQuestion`, даже если оценка ≥ 80.
|
|
129
|
+
- Передавать тело через `-b "..."` со спецсимволами — только `--input` (Reviews API) или `--body-file` (fallback).
|
|
104
130
|
- Создавать PR молча, если его нет — только через `AskUserQuestion`.
|
|
105
131
|
- Сохранять копии отправленного в отдельные файлы — связь через ссылку в файле ревью.
|