restore: run-test-json конфиг от корня репо через resolveVitestConfig plus тест buildVitestJsonArgs plus GUIDE Уроки 9 формат плана
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -351,3 +351,27 @@ Verify-шаги под стеной сдвигают указатель, но GR
|
|||||||
|
|
||||||
**Мета-урок.** «SyntaxError без позиции» + «статика чистая, vitest красный» = почти всегда
|
**Мета-урок.** «SyntaxError без позиции» + «статика чистая, vitest красный» = почти всегда
|
||||||
CRLF/кодировка, а не логика. Проверь байты и переносы ПЕРВЫМ делом, а не последним.
|
CRLF/кодировка, а не логика. Проверь байты и переносы ПЕРВЫМ делом, а не последним.
|
||||||
|
|
||||||
|
## Уроки сессии №9 (2026-06-17) — формат ПЛАНА: verified-context-json + ref=якорь (не проза)
|
||||||
|
|
||||||
|
**Симптом (частая ошибка новой сессии).** Спека опечатана, план содержательно отличный, но печать
|
||||||
|
не встаёт — наставник/судья вроде не против, а seal не приходит.
|
||||||
|
|
||||||
|
**Причина — нарушен ФОРМАТ плана, не суть:**
|
||||||
|
|
||||||
|
1. в плане НЕТ блока ` ```verified-context-json``` ` — а он обязателен и для ПЛАНА (≥1 `EXTRACTED` с
|
||||||
|
реальным якорём-подстрокой), иначе печать не встаёт;
|
||||||
|
2. в `steps-json` поле `ref` несёт ПРОЗУ-описание («Task1 RED: …») вместо якоря спеки. `ref` обязан
|
||||||
|
быть НЕПУСТЫМ якорем секции спеки (`{#u3}` → `ref:"u3"`; `D1..Dn`/`u1..un`).
|
||||||
|
3. навык в `skills-json` — БЕЗ плагин-префикса (`test-driven-development`, не
|
||||||
|
`superpowers:test-driven-development`).
|
||||||
|
|
||||||
|
**Лечение:** добавить в план блок `verified-context-json` (готовый рабочий якорь: ref
|
||||||
|
`tools/cost-pricing.mjs`, anchor `export const PRICING = Object.freeze(`) + заменить все `ref` на
|
||||||
|
якоря секций спеки.
|
||||||
|
|
||||||
|
**Прецедент (параллель-сессия трек 2c, 2026-06-17).** План r1 не имел `verified-context-json` и нёс
|
||||||
|
прозу в `ref` → печать не вставала; контроллер переписал план трижды (r1→r2→r3), на r3 добавил
|
||||||
|
`verified-context-json` EXTRACTED + якорные `ref` → наставник GO, судья GO, церемония пройдена. Суть
|
||||||
|
фичи была верной с r1 — итерации терялись ТОЛЬКО на ритуальном формате. **Вывод:** сверь план с
|
||||||
|
«Рецептом церемонии» (выше, п.2) ДО первой записи — экономит 2-3 круга наставника/судьи.
|
||||||
|
|||||||
+11
-5
@@ -6,7 +6,7 @@
|
|||||||
* mutate-runner трактует как inconclusive (не «убит»). Чистый parseVitestJson + I/O runVitestJson.
|
* mutate-runner трактует как inconclusive (не «убит»). Чистый parseVitestJson + I/O runVitestJson.
|
||||||
*/
|
*/
|
||||||
import { execFileSync } from 'node:child_process';
|
import { execFileSync } from 'node:child_process';
|
||||||
import { join } from 'node:path';
|
import { resolveVitestConfig } from './produce-verify-receipt.mjs';
|
||||||
|
|
||||||
/** Разобрать stdout vitest --reporter json. Битый/пустой → loadError. */
|
/** Разобрать stdout vitest --reporter json. Битый/пустой → loadError. */
|
||||||
export function parseVitestJson(jsonText) {
|
export function parseVitestJson(jsonText) {
|
||||||
@@ -23,14 +23,20 @@ export function parseVitestJson(jsonText) {
|
|||||||
return { allGreen, numTests, numPassed, numFailed, loadError: false };
|
return { allGreen, numTests, numPassed, numFailed, loadError: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Аргументы `npx` для прогона одного тест-файла. Корень и конфиг сюиты — ОТ КОРНЯ репозитория
|
||||||
|
* через общий resolveVitestConfig (есть app/ → app-режим, иначе корень); без хардкода app/.
|
||||||
|
* `exists` инъектируется (для теста); по умолчанию resolveVitestConfig берёт existsSync. */
|
||||||
|
export function buildVitestJsonArgs(testFile, gitCwd, exists) {
|
||||||
|
const { root, config } = resolveVitestConfig(gitCwd, exists);
|
||||||
|
return ['vitest', 'run', testFile, '--root', root, '--config', config, '--reporter', 'json'];
|
||||||
|
}
|
||||||
|
|
||||||
/** I/O: прогнать testFile через vitest json. exit≠0 (упавшие тесты) — это нормально, парсим stdout. */
|
/** I/O: прогнать testFile через vitest json. exit≠0 (упавшие тесты) — это нормально, парсим stdout. */
|
||||||
export function runVitestJson(testFile, gitCwd) {
|
export function runVitestJson(testFile, gitCwd) {
|
||||||
let stdout = '';
|
let stdout = '';
|
||||||
try {
|
try {
|
||||||
stdout = execFileSync('npx', ['vitest', 'run', testFile,
|
stdout = execFileSync('npx', buildVitestJsonArgs(testFile, gitCwd),
|
||||||
'--root', join(gitCwd, 'app'),
|
{ encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
||||||
'--config', join(gitCwd, 'app', 'vitest.config.tools.mjs'),
|
|
||||||
'--reporter', 'json'], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Упавшие тесты → execFileSync бросает с ненулевым кодом; stdout всё равно несёт json.
|
// Упавшие тесты → execFileSync бросает с ненулевым кодом; stdout всё равно несёт json.
|
||||||
stdout = (e && e.stdout) ? String(e.stdout) : '';
|
stdout = (e && e.stdout) ? String(e.stdout) : '';
|
||||||
|
|||||||
@@ -22,3 +22,21 @@ describe('parseVitestJson (анти-вакуум SE-LB-1/11)', () => {
|
|||||||
expect(parseVitestJson('')).toEqual({ allGreen: false, numTests: 0, numPassed: 0, numFailed: 0, loadError: true });
|
expect(parseVitestJson('')).toEqual({ allGreen: false, numTests: 0, numPassed: 0, numFailed: 0, loadError: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import { buildVitestJsonArgs } from './run-test-json.mjs';
|
||||||
|
|
||||||
|
describe('buildVitestJsonArgs (конфиг от корня репо, без хардкода app/)', () => {
|
||||||
|
const norm = (s) => String(s).replace(/\\/g, '/');
|
||||||
|
it('есть app/vitest.config.tools.mjs → root=app', () => {
|
||||||
|
const a = buildVitestJsonArgs('t.mjs', '/repo', (p) => norm(p).endsWith('app/vitest.config.tools.mjs'));
|
||||||
|
expect(norm(a[a.indexOf('--root') + 1])).toBe('/repo/app');
|
||||||
|
expect(norm(a[a.indexOf('--config') + 1])).toBe('/repo/app/vitest.config.tools.mjs');
|
||||||
|
});
|
||||||
|
it('нет app/-конфига → root=корень репо + базовая форма аргументов', () => {
|
||||||
|
const a = buildVitestJsonArgs('t.mjs', '/repo', () => false);
|
||||||
|
expect(a[a.indexOf('--root') + 1]).toBe('/repo');
|
||||||
|
expect(a[0]).toBe('vitest');
|
||||||
|
expect(a).toContain('t.mjs');
|
||||||
|
expect(a).toContain('json');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user