@yasserkhanorg/e2e-agents 0.7.3 → 0.7.5
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/dist/agent/plan.d.ts +1 -0
- package/dist/agent/plan.d.ts.map +1 -1
- package/dist/engine/ai_enrichment.d.ts.map +1 -1
- package/dist/engine/ai_enrichment.js +6 -2
- package/dist/engine/plan_builder.d.ts.map +1 -1
- package/dist/engine/plan_builder.js +66 -19
- package/dist/esm/engine/ai_enrichment.js +6 -2
- package/dist/esm/engine/plan_builder.js +66 -19
- package/package.json +1 -1
package/dist/agent/plan.d.ts
CHANGED
package/dist/agent/plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/agent/plan.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,eAAe,GAAG,kBAAkB,CAAC;CACjD;AAED,MAAM,WAAW,kBAAkB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/agent/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai_enrichment.d.ts","sourceRoot":"","sources":["../../src/engine/ai_enrichment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAGpE,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,mBAAmB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;CAC/C;AAED,MAAM,WAAW,mBAAmB;IAChC,mBAAmB,EAAE,YAAY,CAAC;IAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;
|
|
1
|
+
{"version":3,"file":"ai_enrichment.d.ts","sourceRoot":"","sources":["../../src/engine/ai_enrichment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gCAAgC,CAAC;AAGpE,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,mBAAmB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC;CAC/C;AAED,MAAM,WAAW,mBAAmB;IAChC,mBAAmB,EAAE,YAAY,CAAC;IAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AA0JD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkIlG"}
|
|
@@ -64,6 +64,10 @@ function buildPrompt(options) {
|
|
|
64
64
|
lines.push('## Instructions');
|
|
65
65
|
lines.push('Return ONLY valid JSON (no markdown fences, no explanation) in this exact shape:');
|
|
66
66
|
lines.push('');
|
|
67
|
+
lines.push('Rules for missingScenarios:');
|
|
68
|
+
lines.push('- For coverage=uncovered: list all scenarios the feature needs.');
|
|
69
|
+
lines.push('- For coverage=covered or coverage=partial: ONLY list scenarios introduced by THIS diff that are likely not covered by existing tests. If the diff adds no new user-visible behavior, return []. Do not pad with generic scenarios.');
|
|
70
|
+
lines.push('');
|
|
67
71
|
lines.push(JSON.stringify({
|
|
68
72
|
impactedFlows: [
|
|
69
73
|
{
|
|
@@ -71,10 +75,10 @@ function buildPrompt(options) {
|
|
|
71
75
|
name: '<human-readable flow name>',
|
|
72
76
|
priority: 'P0|P1|P2',
|
|
73
77
|
reasons: [
|
|
74
|
-
'<EXACTLY 1-2 sentences describing user-visible behavioral impact. Focus on what a user would observe or do differently — NOT file names, NOT implementation details
|
|
78
|
+
'<EXACTLY 1-2 sentences describing user-visible behavioral impact. Focus on what a user would observe or do differently — NOT file names, NOT implementation details.>',
|
|
75
79
|
],
|
|
76
80
|
coveredBy: ['<spec file paths that cover this flow>'],
|
|
77
|
-
missingScenarios: ['<concrete
|
|
81
|
+
missingScenarios: ['<concrete scenario title for a new or changed behavior introduced by THIS diff. E.g. "Thread popout preserves scroll position on reload">'],
|
|
78
82
|
},
|
|
79
83
|
],
|
|
80
84
|
unboundFileAnalysis: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan_builder.d.ts","sourceRoot":"","sources":["../../src/engine/plan_builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D,OAAO,KAAK,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,EAIrB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAC,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAC,CAAC;AAqOxD,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EACtC,YAAY,CAAC,EAAE,kBAAkB,GAClC,UAAU,
|
|
1
|
+
{"version":3,"file":"plan_builder.d.ts","sourceRoot":"","sources":["../../src/engine/plan_builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D,OAAO,KAAK,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,EAIrB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAC,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAC,CAAC;AAqOxD,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,YAAY,EACpB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EACtC,YAAY,CAAC,EAAE,kBAAkB,GAClC,UAAU,CA0IZ;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAMzE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAuGhE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,SAAiC,GAAG,MAAM,CAMvH"}
|
|
@@ -264,15 +264,25 @@ function buildPlanFromImpact(impact, policyOverride, aiEnrichment) {
|
|
|
264
264
|
}
|
|
265
265
|
const coveredFlows = impact.impactedFeatures
|
|
266
266
|
.filter((f) => f.coverageStatus === 'covered')
|
|
267
|
-
.map((f) =>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
267
|
+
.map((f) => {
|
|
268
|
+
const aiFeature = f.featureId
|
|
269
|
+
? (aiFeatureByFeatureId.get(f.featureId) ?? aiFeatureByFamilyId.get(f.familyId))
|
|
270
|
+
: aiFeatureByFamilyId.get(f.familyId);
|
|
271
|
+
// Only surface advisory scenarios when AI found new behavior in this diff
|
|
272
|
+
const advisoryScenarios = aiFeature?.aiMissingScenarios?.length
|
|
273
|
+
? aiFeature.aiMissingScenarios
|
|
274
|
+
: undefined;
|
|
275
|
+
return {
|
|
276
|
+
id: featureLabel(f),
|
|
277
|
+
name: featureLabel(f),
|
|
278
|
+
priority: f.priority,
|
|
279
|
+
coveredBy: [
|
|
280
|
+
...(f.playwrightSpecs.length > 0 ? [`${f.playwrightSpecs.length} Playwright spec(s)`] : []),
|
|
281
|
+
...(f.cypressSpecs.length > 0 ? [`${f.cypressSpecs.length} Cypress spec(s)`] : []),
|
|
282
|
+
].slice(0, 3),
|
|
283
|
+
advisoryScenarios,
|
|
284
|
+
};
|
|
285
|
+
});
|
|
276
286
|
const recommendedTests = buildRecommendedTests(impact);
|
|
277
287
|
const requiredNewTests = gaps.map((f) => `${featureLabel(f)}: Add E2E tests`);
|
|
278
288
|
const p0 = impact.impactedFeatures.filter((f) => f.priority === 'P0').length;
|
|
@@ -325,16 +335,21 @@ function renderCiSummaryMarkdown(plan) {
|
|
|
325
335
|
const lines = [];
|
|
326
336
|
const { uncoveredP0P1Flows, changedFiles, impactedFlows, coveredFlows: coveredCount, partialFlows: partialCount } = plan.metrics;
|
|
327
337
|
const mustAddTests = plan.decision.action === 'must-add-tests';
|
|
338
|
+
const flowsWithAdvisory = plan.coveredFlows.filter((f) => f.advisoryScenarios && f.advisoryScenarios.length > 0);
|
|
339
|
+
const cleanFlows = plan.coveredFlows.filter((f) => !f.advisoryScenarios || f.advisoryScenarios.length === 0);
|
|
328
340
|
const statusEmoji = mustAddTests ? '🔴' : plan.decision.action === 'safe-to-merge' ? '🟢' : '🟡';
|
|
329
341
|
lines.push(`## ${statusEmoji} E2E Coverage: ${plan.decision.title}`);
|
|
330
342
|
lines.push('');
|
|
331
343
|
lines.push(`${plan.decision.summary}`);
|
|
332
344
|
lines.push('');
|
|
333
|
-
//
|
|
345
|
+
// Coverage breakdown: "3 covered · 2 new · 1 gap · 1 partial"
|
|
334
346
|
const parts = [];
|
|
335
347
|
if ((coveredCount ?? 0) > 0) {
|
|
336
348
|
parts.push(`${coveredCount} covered`);
|
|
337
349
|
}
|
|
350
|
+
if (flowsWithAdvisory.length > 0) {
|
|
351
|
+
parts.push(`${flowsWithAdvisory.length} new behavior`);
|
|
352
|
+
}
|
|
338
353
|
if (uncoveredP0P1Flows > 0) {
|
|
339
354
|
parts.push(`${uncoveredP0P1Flows} gap${uncoveredP0P1Flows !== 1 ? 's' : ''}`);
|
|
340
355
|
}
|
|
@@ -343,6 +358,7 @@ function renderCiSummaryMarkdown(plan) {
|
|
|
343
358
|
}
|
|
344
359
|
const breakdown = parts.length > 0 ? ` (${parts.join(' · ')})` : '';
|
|
345
360
|
lines.push(`**${changedFiles}** files changed → **${impactedFlows}** features impacted${breakdown}`);
|
|
361
|
+
// ── Blocking gaps ──────────────────────────────────────────────────────────
|
|
346
362
|
if (mustAddTests && plan.requiredNewTests.length > 0) {
|
|
347
363
|
lines.push('');
|
|
348
364
|
lines.push('### ⚠️ Add E2E tests for these uncovered P0/P1 features');
|
|
@@ -351,26 +367,57 @@ function renderCiSummaryMarkdown(plan) {
|
|
|
351
367
|
lines.push('');
|
|
352
368
|
for (const gap of plan.gapDetails.filter((g) => !g.name.includes('(partial)'))) {
|
|
353
369
|
const aiLabel = gap.source === 'ai+deterministic' ? ' ✦ AI-enriched' : '';
|
|
354
|
-
lines.push(
|
|
370
|
+
lines.push(`> [!WARNING]`);
|
|
371
|
+
lines.push(`> **${gap.name}** · ${gap.priority}${aiLabel}`);
|
|
372
|
+
// AI-provided reasons (skip the first generic deterministic reason)
|
|
373
|
+
const aiReasons = gap.reasons.slice(1);
|
|
374
|
+
if (aiReasons.length > 0) {
|
|
375
|
+
lines.push(`> ${aiReasons.join(' ')}`);
|
|
376
|
+
}
|
|
355
377
|
if (gap.missingScenarios && gap.missingScenarios.length > 0) {
|
|
378
|
+
lines.push(`>`);
|
|
379
|
+
lines.push(`> **Suggested test scenarios:**`);
|
|
356
380
|
for (const scenario of gap.missingScenarios) {
|
|
357
|
-
lines.push(
|
|
381
|
+
lines.push(`> - [ ] ${scenario}`);
|
|
358
382
|
}
|
|
359
383
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
384
|
+
lines.push('');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// ── Advisory: covered flows with new behavior detected ────────────────────
|
|
388
|
+
if (flowsWithAdvisory.length > 0) {
|
|
389
|
+
lines.push('');
|
|
390
|
+
lines.push(`### 💡 New behavior detected in ${flowsWithAdvisory.length} covered feature${flowsWithAdvisory.length !== 1 ? 's' : ''}`);
|
|
391
|
+
lines.push('');
|
|
392
|
+
lines.push('These features already have E2E tests, but this PR introduces new behavior worth covering:');
|
|
393
|
+
lines.push('');
|
|
394
|
+
for (const flow of flowsWithAdvisory) {
|
|
395
|
+
lines.push(`> [!TIP]`);
|
|
396
|
+
lines.push(`> **${flow.name}** · ${flow.priority} — ${flow.coveredBy.join(', ')}`);
|
|
397
|
+
lines.push(`>`);
|
|
398
|
+
lines.push(`> Consider adding tests for:`);
|
|
399
|
+
for (const s of flow.advisoryScenarios) {
|
|
400
|
+
lines.push(`> - [ ] ${s}`);
|
|
364
401
|
}
|
|
402
|
+
lines.push('');
|
|
365
403
|
}
|
|
366
404
|
}
|
|
367
|
-
|
|
405
|
+
// ── Clean covered flows (collapsed) ───────────────────────────────────────
|
|
406
|
+
if (cleanFlows.length > 0 || flowsWithAdvisory.length > 0) {
|
|
368
407
|
lines.push('');
|
|
369
|
-
|
|
408
|
+
const label = cleanFlows.length > 0
|
|
409
|
+
? `✅ Covered flows (${cleanFlows.length})`
|
|
410
|
+
: `✅ All covered flows have advisory notes above`;
|
|
411
|
+
lines.push(`<details><summary>${label}</summary>`);
|
|
370
412
|
lines.push('');
|
|
371
|
-
for (const flow of
|
|
413
|
+
for (const flow of cleanFlows) {
|
|
372
414
|
lines.push(`- **${flow.name}** [${flow.priority}] — ${flow.coveredBy.join(', ')}`);
|
|
373
415
|
}
|
|
416
|
+
for (const flow of flowsWithAdvisory) {
|
|
417
|
+
lines.push(`- **${flow.name}** [${flow.priority}] — ${flow.coveredBy.join(', ')} 💡`);
|
|
418
|
+
}
|
|
419
|
+
lines.push('');
|
|
420
|
+
lines.push('</details>');
|
|
374
421
|
}
|
|
375
422
|
if (plan.confidence < 100) {
|
|
376
423
|
lines.push('');
|
|
@@ -61,6 +61,10 @@ function buildPrompt(options) {
|
|
|
61
61
|
lines.push('## Instructions');
|
|
62
62
|
lines.push('Return ONLY valid JSON (no markdown fences, no explanation) in this exact shape:');
|
|
63
63
|
lines.push('');
|
|
64
|
+
lines.push('Rules for missingScenarios:');
|
|
65
|
+
lines.push('- For coverage=uncovered: list all scenarios the feature needs.');
|
|
66
|
+
lines.push('- For coverage=covered or coverage=partial: ONLY list scenarios introduced by THIS diff that are likely not covered by existing tests. If the diff adds no new user-visible behavior, return []. Do not pad with generic scenarios.');
|
|
67
|
+
lines.push('');
|
|
64
68
|
lines.push(JSON.stringify({
|
|
65
69
|
impactedFlows: [
|
|
66
70
|
{
|
|
@@ -68,10 +72,10 @@ function buildPrompt(options) {
|
|
|
68
72
|
name: '<human-readable flow name>',
|
|
69
73
|
priority: 'P0|P1|P2',
|
|
70
74
|
reasons: [
|
|
71
|
-
'<EXACTLY 1-2 sentences describing user-visible behavioral impact. Focus on what a user would observe or do differently — NOT file names, NOT implementation details
|
|
75
|
+
'<EXACTLY 1-2 sentences describing user-visible behavioral impact. Focus on what a user would observe or do differently — NOT file names, NOT implementation details.>',
|
|
72
76
|
],
|
|
73
77
|
coveredBy: ['<spec file paths that cover this flow>'],
|
|
74
|
-
missingScenarios: ['<concrete
|
|
78
|
+
missingScenarios: ['<concrete scenario title for a new or changed behavior introduced by THIS diff. E.g. "Thread popout preserves scroll position on reload">'],
|
|
75
79
|
},
|
|
76
80
|
],
|
|
77
81
|
unboundFileAnalysis: [
|
|
@@ -258,15 +258,25 @@ export function buildPlanFromImpact(impact, policyOverride, aiEnrichment) {
|
|
|
258
258
|
}
|
|
259
259
|
const coveredFlows = impact.impactedFeatures
|
|
260
260
|
.filter((f) => f.coverageStatus === 'covered')
|
|
261
|
-
.map((f) =>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
261
|
+
.map((f) => {
|
|
262
|
+
const aiFeature = f.featureId
|
|
263
|
+
? (aiFeatureByFeatureId.get(f.featureId) ?? aiFeatureByFamilyId.get(f.familyId))
|
|
264
|
+
: aiFeatureByFamilyId.get(f.familyId);
|
|
265
|
+
// Only surface advisory scenarios when AI found new behavior in this diff
|
|
266
|
+
const advisoryScenarios = aiFeature?.aiMissingScenarios?.length
|
|
267
|
+
? aiFeature.aiMissingScenarios
|
|
268
|
+
: undefined;
|
|
269
|
+
return {
|
|
270
|
+
id: featureLabel(f),
|
|
271
|
+
name: featureLabel(f),
|
|
272
|
+
priority: f.priority,
|
|
273
|
+
coveredBy: [
|
|
274
|
+
...(f.playwrightSpecs.length > 0 ? [`${f.playwrightSpecs.length} Playwright spec(s)`] : []),
|
|
275
|
+
...(f.cypressSpecs.length > 0 ? [`${f.cypressSpecs.length} Cypress spec(s)`] : []),
|
|
276
|
+
].slice(0, 3),
|
|
277
|
+
advisoryScenarios,
|
|
278
|
+
};
|
|
279
|
+
});
|
|
270
280
|
const recommendedTests = buildRecommendedTests(impact);
|
|
271
281
|
const requiredNewTests = gaps.map((f) => `${featureLabel(f)}: Add E2E tests`);
|
|
272
282
|
const p0 = impact.impactedFeatures.filter((f) => f.priority === 'P0').length;
|
|
@@ -319,16 +329,21 @@ export function renderCiSummaryMarkdown(plan) {
|
|
|
319
329
|
const lines = [];
|
|
320
330
|
const { uncoveredP0P1Flows, changedFiles, impactedFlows, coveredFlows: coveredCount, partialFlows: partialCount } = plan.metrics;
|
|
321
331
|
const mustAddTests = plan.decision.action === 'must-add-tests';
|
|
332
|
+
const flowsWithAdvisory = plan.coveredFlows.filter((f) => f.advisoryScenarios && f.advisoryScenarios.length > 0);
|
|
333
|
+
const cleanFlows = plan.coveredFlows.filter((f) => !f.advisoryScenarios || f.advisoryScenarios.length === 0);
|
|
322
334
|
const statusEmoji = mustAddTests ? '🔴' : plan.decision.action === 'safe-to-merge' ? '🟢' : '🟡';
|
|
323
335
|
lines.push(`## ${statusEmoji} E2E Coverage: ${plan.decision.title}`);
|
|
324
336
|
lines.push('');
|
|
325
337
|
lines.push(`${plan.decision.summary}`);
|
|
326
338
|
lines.push('');
|
|
327
|
-
//
|
|
339
|
+
// Coverage breakdown: "3 covered · 2 new · 1 gap · 1 partial"
|
|
328
340
|
const parts = [];
|
|
329
341
|
if ((coveredCount ?? 0) > 0) {
|
|
330
342
|
parts.push(`${coveredCount} covered`);
|
|
331
343
|
}
|
|
344
|
+
if (flowsWithAdvisory.length > 0) {
|
|
345
|
+
parts.push(`${flowsWithAdvisory.length} new behavior`);
|
|
346
|
+
}
|
|
332
347
|
if (uncoveredP0P1Flows > 0) {
|
|
333
348
|
parts.push(`${uncoveredP0P1Flows} gap${uncoveredP0P1Flows !== 1 ? 's' : ''}`);
|
|
334
349
|
}
|
|
@@ -337,6 +352,7 @@ export function renderCiSummaryMarkdown(plan) {
|
|
|
337
352
|
}
|
|
338
353
|
const breakdown = parts.length > 0 ? ` (${parts.join(' · ')})` : '';
|
|
339
354
|
lines.push(`**${changedFiles}** files changed → **${impactedFlows}** features impacted${breakdown}`);
|
|
355
|
+
// ── Blocking gaps ──────────────────────────────────────────────────────────
|
|
340
356
|
if (mustAddTests && plan.requiredNewTests.length > 0) {
|
|
341
357
|
lines.push('');
|
|
342
358
|
lines.push('### ⚠️ Add E2E tests for these uncovered P0/P1 features');
|
|
@@ -345,26 +361,57 @@ export function renderCiSummaryMarkdown(plan) {
|
|
|
345
361
|
lines.push('');
|
|
346
362
|
for (const gap of plan.gapDetails.filter((g) => !g.name.includes('(partial)'))) {
|
|
347
363
|
const aiLabel = gap.source === 'ai+deterministic' ? ' ✦ AI-enriched' : '';
|
|
348
|
-
lines.push(
|
|
364
|
+
lines.push(`> [!WARNING]`);
|
|
365
|
+
lines.push(`> **${gap.name}** · ${gap.priority}${aiLabel}`);
|
|
366
|
+
// AI-provided reasons (skip the first generic deterministic reason)
|
|
367
|
+
const aiReasons = gap.reasons.slice(1);
|
|
368
|
+
if (aiReasons.length > 0) {
|
|
369
|
+
lines.push(`> ${aiReasons.join(' ')}`);
|
|
370
|
+
}
|
|
349
371
|
if (gap.missingScenarios && gap.missingScenarios.length > 0) {
|
|
372
|
+
lines.push(`>`);
|
|
373
|
+
lines.push(`> **Suggested test scenarios:**`);
|
|
350
374
|
for (const scenario of gap.missingScenarios) {
|
|
351
|
-
lines.push(
|
|
375
|
+
lines.push(`> - [ ] ${scenario}`);
|
|
352
376
|
}
|
|
353
377
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
378
|
+
lines.push('');
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// ── Advisory: covered flows with new behavior detected ────────────────────
|
|
382
|
+
if (flowsWithAdvisory.length > 0) {
|
|
383
|
+
lines.push('');
|
|
384
|
+
lines.push(`### 💡 New behavior detected in ${flowsWithAdvisory.length} covered feature${flowsWithAdvisory.length !== 1 ? 's' : ''}`);
|
|
385
|
+
lines.push('');
|
|
386
|
+
lines.push('These features already have E2E tests, but this PR introduces new behavior worth covering:');
|
|
387
|
+
lines.push('');
|
|
388
|
+
for (const flow of flowsWithAdvisory) {
|
|
389
|
+
lines.push(`> [!TIP]`);
|
|
390
|
+
lines.push(`> **${flow.name}** · ${flow.priority} — ${flow.coveredBy.join(', ')}`);
|
|
391
|
+
lines.push(`>`);
|
|
392
|
+
lines.push(`> Consider adding tests for:`);
|
|
393
|
+
for (const s of flow.advisoryScenarios) {
|
|
394
|
+
lines.push(`> - [ ] ${s}`);
|
|
358
395
|
}
|
|
396
|
+
lines.push('');
|
|
359
397
|
}
|
|
360
398
|
}
|
|
361
|
-
|
|
399
|
+
// ── Clean covered flows (collapsed) ───────────────────────────────────────
|
|
400
|
+
if (cleanFlows.length > 0 || flowsWithAdvisory.length > 0) {
|
|
362
401
|
lines.push('');
|
|
363
|
-
|
|
402
|
+
const label = cleanFlows.length > 0
|
|
403
|
+
? `✅ Covered flows (${cleanFlows.length})`
|
|
404
|
+
: `✅ All covered flows have advisory notes above`;
|
|
405
|
+
lines.push(`<details><summary>${label}</summary>`);
|
|
364
406
|
lines.push('');
|
|
365
|
-
for (const flow of
|
|
407
|
+
for (const flow of cleanFlows) {
|
|
366
408
|
lines.push(`- **${flow.name}** [${flow.priority}] — ${flow.coveredBy.join(', ')}`);
|
|
367
409
|
}
|
|
410
|
+
for (const flow of flowsWithAdvisory) {
|
|
411
|
+
lines.push(`- **${flow.name}** [${flow.priority}] — ${flow.coveredBy.join(', ')} 💡`);
|
|
412
|
+
}
|
|
413
|
+
lines.push('');
|
|
414
|
+
lines.push('</details>');
|
|
368
415
|
}
|
|
369
416
|
if (plan.confidence < 100) {
|
|
370
417
|
lines.push('');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yasserkhanorg/e2e-agents",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Pluggable LLM provider library for AI-powered test automation. Use Claude, Ollama, or your own LLM. Integrate with Playwright, Jest, or any test framework. MCP server for test agents, cost tracking, and hybrid provider mode.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|