fix(release-gate): skip duplicate CI work and stop live LLM blowups

Shared paths like db.mjs were pulling PAGE/DATA live agent suites into every
hotfix. Keep those cases for actual page-data changes, resume passed suites on
the same artifact, and fail fast on Docker/port issues instead of rerunning 100+
scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-14 22:15:16 +08:00
parent 293ac69a76
commit 2f240e7500
14 changed files with 487 additions and 26 deletions
+33 -2
View File
@@ -17,6 +17,25 @@ export const CORE_SCENARIO_IDS = Object.freeze([
'COMP-09',
]);
// Live LLM product scenarios. Dependency closure from db.mjs / shared infra
// still selects the DATA/PAGE deterministic suites; these four-to-six cases
// only run when page-delivery or Page Data product code actually changed.
export const LIVE_LLM_SCENARIO_IDS = Object.freeze([
'PAGE-01',
'PAGE-02',
'DATA-01',
'DATA-02',
'DATA-03',
'DATA-04',
]);
const LIVE_LLM_PATH_PATTERNS = Object.freeze([
/(?:^|\/)page-data-[^/]+\.mjs$/i,
/(?:^|\/)mindspace-public-finish-sync\.mjs$/i,
/(?:^|\/)mindspace-page-data[^/]*\.mjs$/i,
/^scripts\/run-release-gate-page(?:-data)?-scenarios\.mjs$/i,
]);
const CRITICAL_IMPACT_RULES = Object.freeze([
{
groups: ['AGENT', 'CFG', 'UI'],
@@ -58,6 +77,7 @@ const NON_RUNTIME_PATHS = Object.freeze([
/^\.gitea\/workflows\//i,
/^\.runtime\//i,
/^docs\//i,
/^scenarios\//i,
/^\.cursor\//i,
/^\.codex\//i,
/^scripts\/dev(?:-|\.|\/)/i,
@@ -79,7 +99,7 @@ const IMPACT_RULES = Object.freeze([
{ groups: ['SCHED'], pattern: /(?:schedule|scheduler|reminder|cron)/i },
{ groups: ['SEARCH'], pattern: /(?:search|weather|market|news-provider)/i },
{ groups: ['XLS'], pattern: /(?:excel|xlsx|spreadsheet)/i },
{ groups: ['IMGPG'], pattern: /(?:image|thumbnail|cover|imgproxy)/i },
{ groups: ['IMGPG'], pattern: /(?:image-to-page|image-generation|imgproxy|thumbnails?|user-image-url|plaza-cover)/i },
{ groups: ['FILE'], pattern: /(?:file|attachment|upload|document|pdf|docx|csv)/i },
{ groups: ['MS'], pattern: /mindspace/i },
{ groups: ['PAGE'], pattern: /(?:public-(?:page|finish)|published-page|publication|page-delivery|mindspace-public)/i },
@@ -114,6 +134,13 @@ function matchesAny(patterns, relativePath) {
return patterns.some((pattern) => pattern.test(relativePath));
}
export function pathTriggersLiveLlmScenarios(changedPaths) {
return normalizePaths(changedPaths).some((relativePath) => (
!matchesAny(NON_RUNTIME_PATHS, relativePath)
&& LIVE_LLM_PATH_PATTERNS.some((pattern) => pattern.test(relativePath))
));
}
function closeGroupDependencies(initialGroups) {
const groups = new Set(initialGroups);
const pending = [...groups];
@@ -172,10 +199,13 @@ export function selectImpactScenarios({
}
const impactGroups = closeGroupDependencies(directGroups);
const strategy = impactGroups.length > 0 ? 'impact' : 'core';
const includeLiveLlm = pathTriggersLiveLlmScenarios(normalizedPaths);
const selected = new Set(CORE_SCENARIO_IDS);
for (const scenario of catalog) {
if (impactGroups.includes(scenario.group)) selected.add(scenario.id);
if (!impactGroups.includes(scenario.group)) continue;
if (!includeLiveLlm && LIVE_LLM_SCENARIO_IDS.includes(scenario.id)) continue;
selected.add(scenario.id);
}
const selectedIds = catalog
@@ -193,5 +223,6 @@ export function selectImpactScenarios({
full_gate_reasons: [],
selected_ids: selectedIds,
selected_total: selectedIds.length,
live_llm_selected: includeLiveLlm,
};
}