@gian-tiaga/eda 2.0.0 → 3.1.0
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/MIGRATION.md +68 -67
- package/README.md +44 -86
- package/agents/eda-aim-planner/prompt.md +1 -1
- package/agents/eda-review-api/prompt.md +5 -3
- package/agents/eda-review-architecture/prompt.md +6 -4
- package/agents/eda-review-business/prompt.md +5 -3
- package/agents/eda-review-code-quality/prompt.md +7 -5
- package/agents/eda-review-correctness/prompt.md +5 -3
- package/agents/eda-review-database/prompt.md +5 -3
- package/agents/eda-review-documentation/prompt.md +5 -3
- package/agents/eda-review-frontend/prompt.md +5 -3
- package/agents/eda-review-performance/prompt.md +7 -5
- package/agents/eda-review-plan-alignment/prompt.md +5 -3
- package/agents/eda-review-previous-reviews/prompt.md +6 -4
- package/agents/eda-review-references/prompt.md +5 -3
- package/agents/eda-review-rules/prompt.md +5 -3
- package/agents/eda-review-security/prompt.md +5 -3
- package/agents/eda-review-tests/prompt.md +5 -3
- package/bin/cli.js +2 -2
- package/lib/install.js +124 -160
- package/package.json +1 -1
- package/skills/eda-aim/SKILL.md +2 -2
- package/skills/eda-business/SKILL.md +47 -32
- package/skills/eda-discover-automations/SKILL.md +9 -9
- package/skills/eda-explore/SKILL.md +3 -3
- package/skills/eda-fix/SKILL.md +6 -6
- package/skills/eda-fix-by-review/SKILL.md +47 -58
- package/skills/eda-manual-test/SKILL.md +5 -5
- package/skills/eda-new-project/SKILL.md +3 -3
- package/skills/eda-orhestra/SKILL.md +2 -2
- package/skills/eda-plan/SKILL.md +92 -111
- package/skills/eda-plan-execute/SKILL.md +43 -68
- package/skills/eda-plan-polish/SKILL.md +51 -42
- package/skills/eda-plan-review/SKILL.md +89 -135
- package/skills/eda-plan-review-fix/SKILL.md +38 -63
- package/skills/eda-polish/SKILL.md +25 -35
- package/skills/eda-prepare-ai/SKILL.md +1 -1
- package/skills/eda-review/SKILL.md +18 -17
- package/skills/eda-roadmap/SKILL.md +5 -5
- package/skills/eda-send-review/SKILL.md +11 -11
- package/agents/eda-plan-review-api/agent.json +0 -9
- package/agents/eda-plan-review-api/prompt.md +0 -34
- package/agents/eda-plan-review-architecture/agent.json +0 -9
- package/agents/eda-plan-review-architecture/prompt.md +0 -34
- package/agents/eda-plan-review-database/agent.json +0 -9
- package/agents/eda-plan-review-database/prompt.md +0 -34
- package/agents/eda-plan-review-execution/agent.json +0 -9
- package/agents/eda-plan-review-execution/prompt.md +0 -34
- package/agents/eda-plan-review-feasibility/agent.json +0 -9
- package/agents/eda-plan-review-feasibility/prompt.md +0 -34
- package/agents/eda-plan-review-frontend/agent.json +0 -9
- package/agents/eda-plan-review-frontend/prompt.md +0 -34
- package/agents/eda-plan-review-performance/agent.json +0 -9
- package/agents/eda-plan-review-performance/prompt.md +0 -34
- package/agents/eda-plan-review-previous/agent.json +0 -9
- package/agents/eda-plan-review-previous/prompt.md +0 -28
- package/agents/eda-plan-review-requirements/agent.json +0 -9
- package/agents/eda-plan-review-requirements/prompt.md +0 -34
- package/agents/eda-plan-review-rules/agent.json +0 -9
- package/agents/eda-plan-review-rules/prompt.md +0 -34
- package/agents/eda-plan-review-security/agent.json +0 -9
- package/agents/eda-plan-review-security/prompt.md +0 -34
- package/agents/eda-plan-review-verification/agent.json +0 -9
- package/agents/eda-plan-review-verification/prompt.md +0 -34
package/lib/install.js
CHANGED
|
@@ -19,6 +19,22 @@ const SKILLS_SRC = path.join(PACKAGE_ROOT, 'skills');
|
|
|
19
19
|
const AGENTS_SRC = path.join(PACKAGE_ROOT, 'agents');
|
|
20
20
|
const PACKAGE_JSON_PATH = path.join(PACKAGE_ROOT, 'package.json');
|
|
21
21
|
const SETTINGS_RELATIVE_PATH = 'docs/settings.yaml';
|
|
22
|
+
const ARTIFACTS_RELATIVE_PATH = 'docs/artifacts';
|
|
23
|
+
const ARTIFACT_DIRECTORY_NAMES = [
|
|
24
|
+
'aims',
|
|
25
|
+
'automations',
|
|
26
|
+
'executions',
|
|
27
|
+
'fixes',
|
|
28
|
+
'manual-tests',
|
|
29
|
+
'plan-review-fixes',
|
|
30
|
+
'plan-reviews',
|
|
31
|
+
'plans',
|
|
32
|
+
'project-starts',
|
|
33
|
+
'researches',
|
|
34
|
+
'review-fixes',
|
|
35
|
+
'reviews',
|
|
36
|
+
'roadmaps'
|
|
37
|
+
];
|
|
22
38
|
const TARGET_CHOICES = [
|
|
23
39
|
{ value: 'claude', label: 'Claude Code', dir: '.claude/skills/' },
|
|
24
40
|
{ value: 'codex', label: 'Codex CLI', dir: '.codex/skills/' }
|
|
@@ -34,7 +50,19 @@ const RETIRED_SKILLS = [
|
|
|
34
50
|
'eda-start'
|
|
35
51
|
];
|
|
36
52
|
const RETIRED_AGENTS = [
|
|
37
|
-
'eda-commit-context'
|
|
53
|
+
'eda-commit-context',
|
|
54
|
+
'eda-plan-review-requirements',
|
|
55
|
+
'eda-plan-review-rules',
|
|
56
|
+
'eda-plan-review-architecture',
|
|
57
|
+
'eda-plan-review-feasibility',
|
|
58
|
+
'eda-plan-review-execution',
|
|
59
|
+
'eda-plan-review-verification',
|
|
60
|
+
'eda-plan-review-api',
|
|
61
|
+
'eda-plan-review-database',
|
|
62
|
+
'eda-plan-review-security',
|
|
63
|
+
'eda-plan-review-frontend',
|
|
64
|
+
'eda-plan-review-performance',
|
|
65
|
+
'eda-plan-review-previous'
|
|
38
66
|
];
|
|
39
67
|
const MANIFEST_FILE = 'eda-manifest.json';
|
|
40
68
|
const SETTINGS_VERSION = 3;
|
|
@@ -170,114 +198,6 @@ const DEFAULT_REVIEW_AGENTS = Object.fromEntries(REVIEW_AGENT_DEFINITIONS.map(ag
|
|
|
170
198
|
}
|
|
171
199
|
}
|
|
172
200
|
]));
|
|
173
|
-
const PLAN_REVIEW_AGENT_DEFINITIONS = [
|
|
174
|
-
{
|
|
175
|
-
key: 'requirements',
|
|
176
|
-
description: 'Проверяет соответствие плана задаче, scope, критериям готовности и применимым business-требованиям.',
|
|
177
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
178
|
-
mode: 'always',
|
|
179
|
-
claude: 'sonnet',
|
|
180
|
-
codex: 'gpt-5.6-terra'
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
key: 'rules',
|
|
184
|
-
description: 'Проверяет соблюдение AGENTS.md, CLAUDE.md и docs/rules.md.',
|
|
185
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
186
|
-
mode: 'always',
|
|
187
|
-
claude: 'haiku',
|
|
188
|
-
codex: 'gpt-5.6-luna'
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
key: 'architecture',
|
|
192
|
-
description: 'Проверяет архитектурные границы, зависимости и соответствие docs/arch.md.',
|
|
193
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
194
|
-
mode: 'always',
|
|
195
|
-
claude: 'opus',
|
|
196
|
-
codex: 'gpt-5.6-sol'
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
key: 'feasibility',
|
|
200
|
-
description: 'Проверяет реализуемость плана относительно фактического кода и отсутствие скрытого исследования.',
|
|
201
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
202
|
-
mode: 'always',
|
|
203
|
-
claude: 'opus',
|
|
204
|
-
codex: 'gpt-5.6-sol'
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
key: 'execution',
|
|
208
|
-
description: 'Проверяет связность фаз, ID задач, зависимости и размер работы для одного исполнителя.',
|
|
209
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
210
|
-
mode: 'always',
|
|
211
|
-
claude: 'sonnet',
|
|
212
|
-
codex: 'gpt-5.6-terra'
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
key: 'verification',
|
|
216
|
-
description: 'Проверяет тесты, команды проверок, ошибки, логирование, документацию и эксплуатационную готовность.',
|
|
217
|
-
auto: 'Эта базовая проверка по умолчанию запускается всегда.',
|
|
218
|
-
mode: 'always',
|
|
219
|
-
claude: 'sonnet',
|
|
220
|
-
codex: 'gpt-5.6-terra'
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
key: 'api',
|
|
224
|
-
description: 'Проверяет API, DTO, события, очереди, внешние интеграции и совместимость контрактов.',
|
|
225
|
-
auto: 'В auto запускается при изменении API, событий, очередей или внешних интеграций.',
|
|
226
|
-
mode: 'auto',
|
|
227
|
-
claude: 'sonnet',
|
|
228
|
-
codex: 'gpt-5.6-terra'
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
key: 'database',
|
|
232
|
-
description: 'Проверяет схему данных, миграции, backfill, индексы, транзакции и rollback.',
|
|
233
|
-
auto: 'В auto запускается при изменении хранения, моделей, SQL, схем или миграций.',
|
|
234
|
-
mode: 'auto',
|
|
235
|
-
claude: 'opus',
|
|
236
|
-
codex: 'gpt-5.6-sol'
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
key: 'security',
|
|
240
|
-
description: 'Проверяет auth, permissions, внешний ввод, секреты, персональные данные и опасные операции.',
|
|
241
|
-
auto: 'В auto запускается для auth, permissions, внешнего ввода, секретов и чувствительных данных.',
|
|
242
|
-
mode: 'auto',
|
|
243
|
-
claude: 'opus',
|
|
244
|
-
codex: 'gpt-5.6-sol'
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
key: 'frontend',
|
|
248
|
-
description: 'Проверяет пользовательский сценарий, состояния UI, ошибки, accessibility и адаптивность.',
|
|
249
|
-
auto: 'В auto запускается для компонентов, стилей, клиентских маршрутов и состояния UI.',
|
|
250
|
-
mode: 'auto',
|
|
251
|
-
claude: 'sonnet',
|
|
252
|
-
codex: 'gpt-5.6-terra'
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
key: 'performance',
|
|
256
|
-
description: 'Проверяет нагрузку, запросы, конкурентность, кеши и горячие пути.',
|
|
257
|
-
auto: 'В auto запускается для запросов, пакетной обработки, кешей, конкурентности и горячих путей.',
|
|
258
|
-
mode: 'auto',
|
|
259
|
-
claude: 'opus',
|
|
260
|
-
codex: 'gpt-5.6-sol'
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
key: 'previous',
|
|
264
|
-
description: 'Проверяет закрытие findings предыдущей связанной итерации plan-review.',
|
|
265
|
-
auto: 'В auto запускается только при наличии связанной цепочки review/fix для текущего SHA-256 плана.',
|
|
266
|
-
mode: 'auto',
|
|
267
|
-
claude: 'haiku',
|
|
268
|
-
codex: 'gpt-5.6-luna'
|
|
269
|
-
}
|
|
270
|
-
];
|
|
271
|
-
const DEFAULT_PLAN_REVIEW_AGENTS = Object.fromEntries(PLAN_REVIEW_AGENT_DEFINITIONS.map(agent => [
|
|
272
|
-
agent.key,
|
|
273
|
-
{
|
|
274
|
-
mode: agent.mode,
|
|
275
|
-
model: {
|
|
276
|
-
claude: agent.claude,
|
|
277
|
-
codex: agent.codex
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
]));
|
|
281
201
|
const ORHESTRA_STEP_DEFINITIONS = [
|
|
282
202
|
{
|
|
283
203
|
id: 'plan',
|
|
@@ -343,11 +263,10 @@ const DEFAULT_SETTINGS = {
|
|
|
343
263
|
loggingStrategy: 'ask_each_time'
|
|
344
264
|
},
|
|
345
265
|
planReview: {
|
|
346
|
-
threshold:
|
|
347
|
-
agents: DEFAULT_PLAN_REVIEW_AGENTS
|
|
266
|
+
threshold: 100
|
|
348
267
|
},
|
|
349
268
|
planPolish: {
|
|
350
|
-
limit:
|
|
269
|
+
limit: 2
|
|
351
270
|
},
|
|
352
271
|
review: {
|
|
353
272
|
agents: DEFAULT_REVIEW_AGENTS
|
|
@@ -431,11 +350,11 @@ const ORHESTRA_POLISH_LIMIT_CHOICES = [1, 2, 3, 5, 10].map(value => ({
|
|
|
431
350
|
value,
|
|
432
351
|
name: `${value} ${value === 1 ? 'итерация' : value < 5 ? 'итерации' : 'итераций'}`
|
|
433
352
|
}));
|
|
434
|
-
const PLAN_REVIEW_THRESHOLD_CHOICES = [
|
|
353
|
+
const PLAN_REVIEW_THRESHOLD_CHOICES = [80, 90, 100].map(value => ({
|
|
435
354
|
value,
|
|
436
355
|
name: `${value}/100`
|
|
437
356
|
}));
|
|
438
|
-
const PLAN_POLISH_LIMIT_CHOICES = [1, 2, 3
|
|
357
|
+
const PLAN_POLISH_LIMIT_CHOICES = [1, 2, 3].map(value => ({
|
|
439
358
|
value,
|
|
440
359
|
name: `${value} ${value === 1 ? 'итерация' : value < 5 ? 'итерации' : 'итераций'}`
|
|
441
360
|
}));
|
|
@@ -542,6 +461,7 @@ export async function update({ cwd, input = process.stdin, output = process.stdo
|
|
|
542
461
|
return;
|
|
543
462
|
}
|
|
544
463
|
output.write(`Найдены установленные среды: ${targets.join(', ')}\n`);
|
|
464
|
+
await migrateArtifactDirectories(cwd, output);
|
|
545
465
|
await configureSettings(cwd, { input, output });
|
|
546
466
|
await syncPackage(cwd, targets, output, { action: 'update' });
|
|
547
467
|
}
|
|
@@ -611,6 +531,7 @@ export async function updateAll({
|
|
|
611
531
|
}
|
|
612
532
|
|
|
613
533
|
output.write(`Найдены установленные среды: ${targets.join(', ')}\n`);
|
|
534
|
+
await migrateArtifactDirectories(projectDir, output);
|
|
614
535
|
const projectSettingsPath = path.join(projectDir, SETTINGS_RELATIVE_PATH);
|
|
615
536
|
if (resolvedSettingsMode === 'skip' && await fileExists(projectSettingsPath)) {
|
|
616
537
|
const existingContent = await fs.readFile(projectSettingsPath, 'utf8');
|
|
@@ -793,15 +714,6 @@ export async function askSettings({
|
|
|
793
714
|
target[property] = await selectPrompt({ message, choices, default: target[property] }, { input, output });
|
|
794
715
|
}
|
|
795
716
|
|
|
796
|
-
if (requestedSections.has('plan-review')) {
|
|
797
|
-
settings.planReview.agents = await askPlanReviewAgentSettings({
|
|
798
|
-
input,
|
|
799
|
-
output,
|
|
800
|
-
selectPrompt,
|
|
801
|
-
seedAgents: settings.planReview.agents,
|
|
802
|
-
missingKeys
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
717
|
if (requestedSections.has('review')) {
|
|
806
718
|
settings.review.agents = await askReviewAgentSettings({
|
|
807
719
|
input,
|
|
@@ -833,25 +745,6 @@ export async function askReviewAgentSettings({
|
|
|
833
745
|
});
|
|
834
746
|
}
|
|
835
747
|
|
|
836
|
-
export async function askPlanReviewAgentSettings({
|
|
837
|
-
input = process.stdin,
|
|
838
|
-
output = process.stdout,
|
|
839
|
-
selectPrompt = select,
|
|
840
|
-
seedAgents = DEFAULT_PLAN_REVIEW_AGENTS,
|
|
841
|
-
missingKeys = null
|
|
842
|
-
} = {}) {
|
|
843
|
-
return askAgentSettings({
|
|
844
|
-
input,
|
|
845
|
-
output,
|
|
846
|
-
selectPrompt,
|
|
847
|
-
definitions: PLAN_REVIEW_AGENT_DEFINITIONS,
|
|
848
|
-
seedAgents,
|
|
849
|
-
missingKeys,
|
|
850
|
-
keyPrefix: 'planReview.agents',
|
|
851
|
-
label: 'plan-review'
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
|
|
855
748
|
async function askAgentSettings({ input, output, selectPrompt, definitions, seedAgents, missingKeys, keyPrefix, label }) {
|
|
856
749
|
const configuredAgents = structuredClone(seedAgents);
|
|
857
750
|
const shouldAsk = key => missingKeys === null || missingKeys.has(key);
|
|
@@ -1010,6 +903,92 @@ async function findInstalledProjects(rootDir, maxDepth) {
|
|
|
1010
903
|
return projects;
|
|
1011
904
|
}
|
|
1012
905
|
|
|
906
|
+
async function migrateArtifactDirectories(cwd, output = process.stdout) {
|
|
907
|
+
const docsDir = path.join(cwd, 'docs');
|
|
908
|
+
const artifactsDir = path.join(cwd, ARTIFACTS_RELATIVE_PATH);
|
|
909
|
+
const legacyDirectories = [];
|
|
910
|
+
|
|
911
|
+
for (const directoryName of ARTIFACT_DIRECTORY_NAMES) {
|
|
912
|
+
const legacyPath = path.join(docsDir, directoryName);
|
|
913
|
+
const legacyStat = await lstatIfExists(legacyPath);
|
|
914
|
+
if (!legacyStat) continue;
|
|
915
|
+
if (!legacyStat.isDirectory() || legacyStat.isSymbolicLink()) {
|
|
916
|
+
throw new Error(`Ожидался каталог артефактов: ${legacyPath}`);
|
|
917
|
+
}
|
|
918
|
+
legacyDirectories.push({ directoryName, legacyPath });
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if (legacyDirectories.length === 0) {
|
|
922
|
+
return { migratedDirectories: 0, movedFiles: 0, discardedFiles: 0 };
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
const artifactsStat = await lstatIfExists(artifactsDir);
|
|
926
|
+
if (artifactsStat && (!artifactsStat.isDirectory() || artifactsStat.isSymbolicLink())) {
|
|
927
|
+
throw new Error(`Ожидался каталог артефактов: ${artifactsDir}`);
|
|
928
|
+
}
|
|
929
|
+
await fs.mkdir(artifactsDir, { recursive: true });
|
|
930
|
+
|
|
931
|
+
const result = {
|
|
932
|
+
migratedDirectories: legacyDirectories.length,
|
|
933
|
+
movedFiles: 0,
|
|
934
|
+
discardedFiles: 0
|
|
935
|
+
};
|
|
936
|
+
for (const { directoryName, legacyPath } of legacyDirectories) {
|
|
937
|
+
await mergeArtifactEntry(legacyPath, path.join(artifactsDir, directoryName), result);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
output.write(
|
|
941
|
+
`Артефакты перенесены в ${ARTIFACTS_RELATIVE_PATH}/: каталогов ${result.migratedDirectories}, `
|
|
942
|
+
+ `файлов перемещено ${result.movedFiles}, конфликтующих старых файлов удалено ${result.discardedFiles}.\n`
|
|
943
|
+
);
|
|
944
|
+
return result;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
async function mergeArtifactEntry(sourcePath, destinationPath, result) {
|
|
948
|
+
const sourceStat = await fs.lstat(sourcePath);
|
|
949
|
+
const destinationStat = await lstatIfExists(destinationPath);
|
|
950
|
+
|
|
951
|
+
if (!destinationStat) {
|
|
952
|
+
result.movedFiles += await countArtifactFiles(sourcePath, sourceStat);
|
|
953
|
+
await fs.mkdir(path.dirname(destinationPath), { recursive: true });
|
|
954
|
+
await fs.rename(sourcePath, destinationPath);
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const mergeDirectories = sourceStat.isDirectory()
|
|
959
|
+
&& !sourceStat.isSymbolicLink()
|
|
960
|
+
&& destinationStat.isDirectory()
|
|
961
|
+
&& !destinationStat.isSymbolicLink();
|
|
962
|
+
if (!mergeDirectories) {
|
|
963
|
+
result.discardedFiles += await countArtifactFiles(sourcePath, sourceStat);
|
|
964
|
+
await fs.rm(sourcePath, { recursive: true, force: true });
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
const entries = await fs.readdir(sourcePath, { withFileTypes: true });
|
|
969
|
+
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
970
|
+
for (const entry of entries) {
|
|
971
|
+
await mergeArtifactEntry(
|
|
972
|
+
path.join(sourcePath, entry.name),
|
|
973
|
+
path.join(destinationPath, entry.name),
|
|
974
|
+
result
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
await fs.rmdir(sourcePath);
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
async function countArtifactFiles(entryPath, entryStat = null) {
|
|
981
|
+
const stat = entryStat ?? await fs.lstat(entryPath);
|
|
982
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) return 1;
|
|
983
|
+
|
|
984
|
+
let count = 0;
|
|
985
|
+
const entries = await fs.readdir(entryPath, { withFileTypes: true });
|
|
986
|
+
for (const entry of entries) {
|
|
987
|
+
count += await countArtifactFiles(path.join(entryPath, entry.name));
|
|
988
|
+
}
|
|
989
|
+
return count;
|
|
990
|
+
}
|
|
991
|
+
|
|
1013
992
|
async function ensureSettings(cwd, { input = process.stdin, output = process.stdout } = {}) {
|
|
1014
993
|
const settingsPath = path.join(cwd, SETTINGS_RELATIVE_PATH);
|
|
1015
994
|
const existingContent = await readFileIfExists(settingsPath);
|
|
@@ -1144,13 +1123,6 @@ function migrateSettingsContent(content) {
|
|
|
1144
1123
|
|
|
1145
1124
|
const planReview = objectValue(raw['plan-review']);
|
|
1146
1125
|
transfer('planReview.threshold', planReview.threshold, score, value => { settings.planReview.threshold = value; });
|
|
1147
|
-
transferAgentSettings({
|
|
1148
|
-
rawAgents: objectValue(planReview.agents),
|
|
1149
|
-
settingsAgents: settings.planReview.agents,
|
|
1150
|
-
definitions: PLAN_REVIEW_AGENT_DEFINITIONS,
|
|
1151
|
-
prefix: 'planReview.agents',
|
|
1152
|
-
missingKeys
|
|
1153
|
-
});
|
|
1154
1126
|
|
|
1155
1127
|
const planPolish = objectValue(raw['plan-polish']);
|
|
1156
1128
|
transfer('planPolish.limit', planPolish.limit, positiveInt, value => { settings.planPolish.limit = value; });
|
|
@@ -1295,11 +1267,6 @@ ${onFailureThen}
|
|
|
1295
1267
|
# Модель для Codex.
|
|
1296
1268
|
codex: ${configured.model.codex}`;
|
|
1297
1269
|
}).join('\n\n');
|
|
1298
|
-
const planReviewAgents = formatAgents(
|
|
1299
|
-
PLAN_REVIEW_AGENT_DEFINITIONS,
|
|
1300
|
-
settings.planReview.agents,
|
|
1301
|
-
DEFAULT_PLAN_REVIEW_AGENTS
|
|
1302
|
-
);
|
|
1303
1270
|
const reviewAgents = formatAgents(REVIEW_AGENT_DEFINITIONS, settings.review.agents, DEFAULT_REVIEW_AGENTS);
|
|
1304
1271
|
|
|
1305
1272
|
return `version: ${SETTINGS_VERSION}
|
|
@@ -1329,7 +1296,7 @@ plan:
|
|
|
1329
1296
|
# Включает кросс-CLI ревью в eda-plan.
|
|
1330
1297
|
# true | false
|
|
1331
1298
|
strict: ${settings.plan.strict ? 'true' : 'false'}
|
|
1332
|
-
# Запускает
|
|
1299
|
+
# Запускает изолированный цикл eda-plan-polish.
|
|
1333
1300
|
# true | false
|
|
1334
1301
|
review: ${settings.plan.review !== false ? 'true' : 'false'}
|
|
1335
1302
|
# Задаёт размер плана.
|
|
@@ -1346,12 +1313,9 @@ plan:
|
|
|
1346
1313
|
logging_strategy: ${settings.plan.loggingStrategy}
|
|
1347
1314
|
|
|
1348
1315
|
plan-review:
|
|
1349
|
-
#
|
|
1316
|
+
# Доля закрытых пунктов чек-листа, при которой план считается готовым.
|
|
1350
1317
|
# 1..100
|
|
1351
1318
|
threshold: ${settings.planReview.threshold}
|
|
1352
|
-
# Каждая проверка имеет собственный режим запуска и модели для обеих сред.
|
|
1353
|
-
agents:
|
|
1354
|
-
${planReviewAgents}
|
|
1355
1319
|
|
|
1356
1320
|
plan-polish:
|
|
1357
1321
|
# Максимальное число подтверждающих review-итераций.
|
|
@@ -1369,7 +1333,7 @@ send-review:
|
|
|
1369
1333
|
close_previous_reviews: ${settings.sendReview.closePreviousReviews ? 'true' : 'false'}
|
|
1370
1334
|
|
|
1371
1335
|
discover-automations:
|
|
1372
|
-
# Добавляет docs/plans/ в обычный запуск eda-discover-automations.
|
|
1336
|
+
# Добавляет docs/artifacts/plans/ в обычный запуск eda-discover-automations.
|
|
1373
1337
|
# true | false
|
|
1374
1338
|
include_plans: ${settings.discoverAutomations.includePlans ? 'true' : 'false'}
|
|
1375
1339
|
`;
|
package/package.json
CHANGED
package/skills/eda-aim/SKILL.md
CHANGED
|
@@ -28,7 +28,7 @@ aim:
|
|
|
28
28
|
|
|
29
29
|
В автоматическом режиме основной агент сам выбирает ответ на рабочие вопросы по рекомендации субагента и фактам проекта. Это не отменяет одно обязательное подтверждение человеком точного списка целей до создания нового файла.
|
|
30
30
|
|
|
31
|
-
Если пользователь передал существующий файл из `docs/aims/`, продолжай его с текущего статуса. Не создавай второй файл для той же цели.
|
|
31
|
+
Если пользователь передал существующий файл из `docs/artifacts/aims/`, продолжай его с текущего статуса. Не создавай второй файл для той же цели.
|
|
32
32
|
|
|
33
33
|
## Пакетные агенты
|
|
34
34
|
|
|
@@ -59,7 +59,7 @@ aim:
|
|
|
59
59
|
|
|
60
60
|
## Файл цели
|
|
61
61
|
|
|
62
|
-
После подтверждения `eda-aim-planner` создаёт `docs/aims/{YYYY-MM-DD}_{HH-MM}_{slug}.md`. Файл должен оставаться коротким и содержать только цель и фактический журнал:
|
|
62
|
+
После подтверждения `eda-aim-planner` создаёт `docs/artifacts/aims/{YYYY-MM-DD}_{HH-MM}_{slug}.md`. Файл должен оставаться коротким и содержать только цель и фактический журнал:
|
|
63
63
|
|
|
64
64
|
```markdown
|
|
65
65
|
# <Короткое название>
|
|
@@ -5,7 +5,7 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
5
5
|
|
|
6
6
|
# Скил: Бизнес-логика (eda-business)
|
|
7
7
|
|
|
8
|
-
Создаёшь и поддерживаешь согласованную бизнес-документацию проекта: короткое оглавление `docs/business.md` и самостоятельные тематические карточки в `docs/business/`.
|
|
8
|
+
Создаёшь и поддерживаешь согласованную бизнес-документацию проекта: короткое оглавление `docs/business.md` и самостоятельные тематические карточки в `docs/business/`. Каждая карточка подробно фиксирует значимые решения своей темы, но не засоряется сведениями соседних тем и деталями конкретной реализации.
|
|
9
9
|
|
|
10
10
|
## Вход из сообщения пользователя
|
|
11
11
|
|
|
@@ -22,11 +22,16 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
22
22
|
1. **Только business-документация.** Меняй лишь `docs/business.md` и Markdown-файлы непосредственно в `docs/business/`. Не правь код, настройки, правила, архитектуру, планы, тесты или другие документы.
|
|
23
23
|
2. **Целевое поведение.** Карточки фиксируют согласованные требования и бизнес-логику, даже если код пока им не соответствует. Фактические отличия вынеси в последний раздел `Расхождения с реализацией`.
|
|
24
24
|
3. **Никаких догадок как фактов.** Код помогает найти существующие сценарии и вопросы, но не подтверждает продуктовые решения сам по себе.
|
|
25
|
-
4. **Одна тема за раз.** После согласования общего списка
|
|
25
|
+
4. **Одна тема за раз.** После согласования общего списка полно опиши и подтверди значимые решения текущей темы до записи, затем переходи к следующей.
|
|
26
26
|
5. **В индекс — только готовое.** Не записывай предложенные, незавершённые или спорные темы в `docs/business.md` и не создавай для них черновые карточки.
|
|
27
27
|
6. **Самодостаточные карточки.** Основной текст не должен требовать чтения исходного кода, плана или внешнего материала, чтобы понять бизнес-правило.
|
|
28
|
-
7. **Не проектируй реализацию.** Не назначай
|
|
28
|
+
7. **Не проектируй конкретную реализацию.** Не назначай язык, фреймворк, библиотеку, конкретную СУБД, схему данных, классы, функции, внутренние модули или порядок технических изменений.
|
|
29
29
|
8. **Сохраняй подтверждённое.** При обновлении не удаляй и не ослабляй существующее правило, не переименовывай и не удаляй карточку без явного решения пользователя.
|
|
30
|
+
9. **Полнота без шума.** Зафиксируй все подтверждённые детали, которые меняют целевое поведение темы: правила, выбранные алгоритмы, состояния, переходы, ограничения, исключения и наблюдаемые результаты. Не сокращай сложную тему ради краткости; убирай повторы, общие рассуждения и факты, не влияющие на правило.
|
|
31
|
+
10. **Строгая граница темы.** Карточка описывает только названную тему. Сведения о соседнем домене, внутреннем модуле или другой карточке опускай; если у них есть самостоятельное бизнес-значение, предложи отдельную тему, но не включай её в текущую.
|
|
32
|
+
11. **`about` — только обзор.** Это не сводная бизнес-спецификация и не каталог остальных карточек. Кратко опиши сам проект и перечисли его основные пользовательские возможности; не раскладывай их по модулям и не детализируй правила, сценарии и исключения других тем.
|
|
33
|
+
12. **Карточка не привязана к коду.** Код, тесты и конфиги используй для поиска вопросов и проверки текущего поведения, но пиши карточку устойчивым предметным языком. Не включай пути и строки исходников, имена классов, функций, файлов и внутренних модулей — в том числе в `about` и `Расхождения с реализацией`.
|
|
34
|
+
13. **Алгоритм допустим, стек — нет.** Фиксируй выбранный функциональный или security-механизм, если он определяет поведение продукта: например, JWT либо непрозрачные токены с хранением в базе данных, правила выпуска, срока действия, обновления и отзыва. Не регламентируй язык, framework, библиотеку, конкретную СУБД, таблицы и способ программной сборки механизма, если это не отдельное подтверждённое ограничение продукта.
|
|
30
35
|
|
|
31
36
|
## Интерактивные вопросы
|
|
32
37
|
|
|
@@ -43,7 +48,7 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
43
48
|
|
|
44
49
|
### 1. Прочитать существующий контекст
|
|
45
50
|
|
|
46
|
-
Прочитай `docs/business.md` и только карточки, которые относятся к текущей теме. Затем изучи
|
|
51
|
+
Прочитай `docs/business.md` и только карточки, которые относятся к текущей теме. Затем изучи минимальный набор релевантных источников, достаточный для понимания именно этой темы. Для `about` обычно достаточно основного README, метаданных проекта и пользовательских точек входа; не обходи каждый внутренний модуль, route, модель или тест.
|
|
47
52
|
|
|
48
53
|
Не загружай все карточки и весь код без необходимости. Разделяй:
|
|
49
54
|
|
|
@@ -54,60 +59,61 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
54
59
|
|
|
55
60
|
### 2. Выбрать темы при пустом вызове
|
|
56
61
|
|
|
57
|
-
Если тема не задана, составь короткий список только из реально применимых тем. Для каждой укажи, что именно будет
|
|
62
|
+
Если тема не задана, составь короткий список только из реально применимых и непересекающихся тем. Для каждой одной фразой укажи, что именно будет описано. Не используй обязательный универсальный набор и не создавай тему для каждого технического модуля: `auth`, `posts`, `payments` и другие названия допустимы только при наличии самостоятельных правил продукта.
|
|
58
63
|
|
|
59
64
|
Покажи список через `AskUserQuestion` и попроси подтвердить его или изменить. До подтверждения ничего не записывай. После ответа прорабатывай темы последовательно. Если работа прервана, следующий пустой вызов заново анализирует индекс и предлагает только отсутствующие или требующие актуализации темы.
|
|
60
65
|
|
|
61
66
|
### 3. Согласовать текущую тему
|
|
62
67
|
|
|
63
|
-
|
|
68
|
+
Сначала сформулируй суть темы в одном-двух предложениях. Затем собери все конкретные решения, необходимые для полного описания целевого поведения этой темы. Требования, термины, сценарии, состояния, ограничения, исключения и критерии приёмки добавляй по смыслу, а не ради заполнения универсального чеклиста. Не пропускай значимую конкретику только потому, что карточка получится длинной.
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
- участники, роли и значимые термины;
|
|
67
|
-
- требования, правила и инварианты;
|
|
68
|
-
- основные сценарии и порядок бизнес-действий;
|
|
69
|
-
- состояния, переходы, ограничения и исключения;
|
|
70
|
-
- ошибки и пограничные случаи, видимые пользователю или внешнему потребителю;
|
|
71
|
-
- проверяемые критерии приёмки.
|
|
70
|
+
Например, карточка аутентификации может подробно фиксировать выбранный вид токенов, их выпуск, срок действия, обновление, отзыв, завершение сессий и значимые ошибки. В ней допустимо выбрать JWT или токены, хранящиеся в базе данных, но не следует назначать язык, framework, библиотеку, конкретную СУБД, таблицы, классы и файлы.
|
|
72
71
|
|
|
73
|
-
Для `about`
|
|
72
|
+
Для `about` подготовь короткое описание проекта и компактный список его основных возможностей. Не включай аудиторию, решаемую проблему, границы, общие ограничения или пользовательские сценарии отдельными разделами, если пользователь их явно не запросил и они не нужны для самого краткого описания. Не упоминай устройство внутренних модулей и не пересказывай содержимое тематических карточек.
|
|
74
73
|
|
|
75
|
-
Сравни
|
|
74
|
+
Сравни с реализацией только подтверждённые правила непосредственно текущей темы. Расхождение описывай как отличие наблюдаемого поведения от целевого, без ссылок на исходники и без пересказа устройства кода. В `Расхождения с реализацией` не добавляй наблюдения о соседних модулях, случайно замеченные дефекты, технический долг и неполноту других карточек. Для `about` не перечисляй пофункциональные расхождения: они относятся к отдельным тематическим карточкам. Если прямого существенного расхождения по теме нет, напиши `Известных расхождений не обнаружено.`
|
|
76
75
|
|
|
77
|
-
Покажи человеку
|
|
76
|
+
Покажи человеку короткий текст будущей карточки целиком и запроси итоговое подтверждение через `AskUserQuestion`. Если остаётся спорное решение, сначала закрой его отдельным вопросом. Не записывай карточку до подтверждения.
|
|
78
77
|
|
|
79
78
|
### 4. Записать карточку и индекс
|
|
80
79
|
|
|
81
80
|
Используй стабильное имя файла в lowercase ASCII kebab-case: `docs/business/<topic>.md`.
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
У обычной тематической карточки нет обязательного набора содержательных разделов. Выбирай структуру по сложности темы и фиксируй в ней всю значимую подтверждённую конкретику без лишних разделов, например:
|
|
84
83
|
|
|
85
84
|
```markdown
|
|
86
85
|
# <Название темы>
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
<что покрывает тема и что не покрывает>
|
|
87
|
+
<краткое описание темы>
|
|
90
88
|
|
|
91
|
-
##
|
|
92
|
-
<роли и доменные понятия>
|
|
89
|
+
## Правила
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
<согласованные требования и инварианты>
|
|
91
|
+
- <только необходимые согласованные правила>
|
|
96
92
|
|
|
97
|
-
##
|
|
98
|
-
|
|
93
|
+
## Расхождения с реализацией
|
|
94
|
+
|
|
95
|
+
<подтверждённые отличия с доказательствами либо «Известных расхождений не обнаружено.»>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Если отдельный раздел `Правила` не нужен, не создавай его. Для сложной темы добавь столько смысловых разделов, сколько требуется, чтобы не смешивать правила, алгоритмы, состояния, исключения и критерии. Для простой темы не создавай пустые или формальные разделы.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
<переходы, ограничения, ошибки и пограничные случаи>
|
|
100
|
+
Для `about.md` используй простой обзорный формат:
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
```markdown
|
|
103
|
+
# О проекте
|
|
104
|
+
|
|
105
|
+
<краткое описание проекта>
|
|
106
|
+
|
|
107
|
+
## Основные возможности
|
|
108
|
+
|
|
109
|
+
- <возможность на уровне пользователя>
|
|
105
110
|
|
|
106
111
|
## Расхождения с реализацией
|
|
107
|
-
|
|
112
|
+
|
|
113
|
+
Известных расхождений не обнаружено.
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
Сохраняй `Расхождения с реализацией` последним разделом любой карточки.
|
|
111
117
|
|
|
112
118
|
Создай или обнови `docs/business.md` как короткое оглавление только существующих согласованных карточек:
|
|
113
119
|
|
|
@@ -116,7 +122,7 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
116
122
|
|
|
117
123
|
| Описание | Карточка |
|
|
118
124
|
|---|---|
|
|
119
|
-
|
|
|
125
|
+
| Краткое описание проекта и основные возможности | [О проекте](business/about.md) |
|
|
120
126
|
| Регистрация, вход, восстановление доступа и права пользователей | [Авторизация](business/auth.md) |
|
|
121
127
|
```
|
|
122
128
|
|
|
@@ -128,6 +134,11 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
128
134
|
|
|
129
135
|
- индекс содержит только существующие согласованные карточки и ровно две колонки `Описание` и `Карточка`;
|
|
130
136
|
- новая или обновлённая карточка соответствует подтверждённому содержанию;
|
|
137
|
+
- карточка не содержит сведений о соседних темах и не раздута необязательными разделами;
|
|
138
|
+
- `about` остаётся коротким обзором проекта и его основных возможностей без описания внутренних модулей;
|
|
139
|
+
- сложная тема подробно фиксирует все значимые подтверждённые правила, алгоритмы, состояния и исключения;
|
|
140
|
+
- текст карточки не ссылается на файлы, строки, классы, функции и внутренние модули текущей реализации;
|
|
141
|
+
- выбранный механизм поведения отделён от языка, framework, библиотеки, конкретной СУБД и схемы реализации;
|
|
131
142
|
- каждое правило однозначно и проверяемо на уровне поведения;
|
|
132
143
|
- техническая реализация не выдана за бизнес-требование;
|
|
133
144
|
- раздел `Расхождения с реализацией` последний и отделяет целевое состояние от текущего;
|
|
@@ -142,6 +153,10 @@ description: 'Создаёт и обновляет согласованное о
|
|
|
142
153
|
- Записывать неподтверждённые темы или черновики в индекс.
|
|
143
154
|
- Выводить бизнес-правило только из текущего кода и сразу считать его целевым.
|
|
144
155
|
- Подменять карточку исследованием, roadmap, архитектурой или планом реализации.
|
|
156
|
+
- Сокращать сложную тему до общего описания и терять подтверждённые правила или алгоритмы.
|
|
157
|
+
- Переписывать в карточку структуру кода, пути, строки, классы, функции и внутренние модули.
|
|
158
|
+
- Использовать `about` как сводку всех доменов, модулей, правил и расхождений проекта.
|
|
159
|
+
- Переносить в текущую карточку подробности и расхождения соседней темы «для контекста».
|
|
145
160
|
- Создавать ссылки из индекса на отсутствующие файлы.
|
|
146
161
|
- Молча удалять, переименовывать или ослаблять подтверждённые требования.
|
|
147
162
|
- Сохранять business-документацию вне `docs/business.md` и `docs/business/`.
|