mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
478325a2dd |
@@ -4902,6 +4902,13 @@
|
||||
saveSession();
|
||||
}
|
||||
|
||||
function completeParameterGenerationIfReady() {
|
||||
if (expectedVariants <= 0 || arrivedVariants < expectedVariants) return;
|
||||
if (parameterGenerationState === 'pending' || parameterGenerationState === 'loading') {
|
||||
completeParameterPublication();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTunePopover() {
|
||||
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
||||
if (tuneOpen) { closeTunePopover(); return; }
|
||||
@@ -5796,7 +5803,7 @@
|
||||
setLiveState('CYCLING');
|
||||
showOrUpdateCyclingBar();
|
||||
saveSession();
|
||||
if (parameterGenerationState === 'loading') completeParameterPublication();
|
||||
completeParameterGenerationIfReady();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5884,7 +5891,7 @@
|
||||
refreshParamsPanel();
|
||||
positionBar();
|
||||
saveSession();
|
||||
if (parameterGenerationState === 'loading') completeParameterPublication();
|
||||
completeParameterGenerationIfReady();
|
||||
console.log('[impeccable] Mounted ' + arrivedVariants + ' ' + manifest.framework + ' component variants.');
|
||||
} catch (err) {
|
||||
console.error('[impeccable] Failed to mount component-preview variants:', err);
|
||||
@@ -6329,7 +6336,7 @@
|
||||
refreshParamsPanel();
|
||||
positionBar();
|
||||
saveSession();
|
||||
if (parameterGenerationState === 'loading') completeParameterPublication();
|
||||
completeParameterGenerationIfReady();
|
||||
console.log('[impeccable] Injected ' + arrivedVariants + ' variants from source file.');
|
||||
})
|
||||
.catch(err => {
|
||||
@@ -6836,6 +6843,7 @@
|
||||
|
||||
const expected = parseInt(wrapper.dataset.impeccableVariantCount || '0');
|
||||
if (expected > 0) expectedVariants = expected;
|
||||
completeParameterGenerationIfReady();
|
||||
|
||||
if (arrivedVariants > 0) {
|
||||
setLiveState('CYCLING');
|
||||
|
||||
@@ -944,42 +944,8 @@ export async function commitManualEdits({
|
||||
};
|
||||
}
|
||||
|
||||
const repairContext = {
|
||||
batch,
|
||||
cwd,
|
||||
pageUrl,
|
||||
count,
|
||||
provider,
|
||||
env,
|
||||
timeoutMs,
|
||||
applyBatchToSource,
|
||||
chatAvailable,
|
||||
transactionId,
|
||||
};
|
||||
|
||||
const baseRollbackScope = collectApplyOwnedFiles(batch, cwd);
|
||||
const rollbackSnapshot = snapshotRollbackFiles(cwd, baseRollbackScope);
|
||||
const failWithRollback = ({
|
||||
scope = baseRollbackScope,
|
||||
extraFiles = [],
|
||||
failed,
|
||||
files = [],
|
||||
details = {},
|
||||
}) => {
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, extraFiles, scope);
|
||||
return {
|
||||
applied: [],
|
||||
failed,
|
||||
files,
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
...details,
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
};
|
||||
let result;
|
||||
try {
|
||||
result = repairOnly
|
||||
@@ -999,27 +965,42 @@ export async function commitManualEdits({
|
||||
chatAvailable,
|
||||
});
|
||||
} catch (err) {
|
||||
return failWithRollback({
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, [], baseRollbackScope);
|
||||
return {
|
||||
applied: [],
|
||||
failed: batch.entries.map((entry) => ({
|
||||
id: entry.id,
|
||||
reason: err.message || String(err),
|
||||
candidates: candidatesForEntry(batch, entry.id),
|
||||
})),
|
||||
});
|
||||
files: [],
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status === 'error') {
|
||||
const rollbackScope = collectApplyOwnedFiles(batch, cwd, result.files || []);
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, result.files || [], rollbackScope);
|
||||
const failed = normalizeFailedEntries(batch, result, result.message || 'AI copy edit failed');
|
||||
return failWithRollback({
|
||||
scope: rollbackScope,
|
||||
extraFiles: result.files || [],
|
||||
return {
|
||||
applied: [],
|
||||
failed: failed.length > 0
|
||||
? failed
|
||||
: verificationFailuresForEntries(batch, batch.entries, result.message || 'AI copy edit failed'),
|
||||
files: result.files || [],
|
||||
details: { notes: result.notes || [] },
|
||||
});
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
notes: result.notes || [],
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
const reportedAppliedIds = uniqueStrings(result.appliedEntryIds || []);
|
||||
@@ -1032,44 +1013,72 @@ export async function commitManualEdits({
|
||||
const conflictingAppliedIds = reportedAppliedIds.filter((id) => failedIds.has(id));
|
||||
|
||||
if (conflictingAppliedIds.length > 0) {
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, result.files || [], rollbackScope);
|
||||
const conflictingEntries = batch.entries.filter((entry) => conflictingAppliedIds.includes(entry.id));
|
||||
return failWithRollback({
|
||||
scope: rollbackScope,
|
||||
extraFiles: result.files || [],
|
||||
return {
|
||||
applied: [],
|
||||
failed: [
|
||||
...verificationFailuresForEntries(batch, conflictingEntries, 'conflicting_apply_result'),
|
||||
...aiFailed.filter((item) => !conflictingAppliedIds.includes(item.id)),
|
||||
],
|
||||
files: result.files || [],
|
||||
details: { notes: result.notes || [] },
|
||||
});
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
notes: result.notes || [],
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
const unreportedFiles = unreportedChangedFiles(cwd, rollbackSnapshot, result.files || [], rollbackScope);
|
||||
if (unreportedFiles.length > 0) {
|
||||
return failWithRollback({
|
||||
scope: [...rollbackScope, ...unreportedFiles],
|
||||
extraFiles: result.files || [],
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, result.files || [], [...rollbackScope, ...unreportedFiles]);
|
||||
return {
|
||||
applied: [],
|
||||
failed: verificationFailuresForEntries(batch, batch.entries, 'unreported_source_changes', { files: unreportedFiles }),
|
||||
files: result.files || [],
|
||||
details: { unreportedFiles, notes: result.notes || [] },
|
||||
});
|
||||
unreportedFiles,
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
notes: result.notes || [],
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status === 'done' && reportedAppliedIds.length === 0) {
|
||||
return failWithRollback({
|
||||
scope: rollbackScope,
|
||||
extraFiles: result.files || [],
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, result.files || [], rollbackScope);
|
||||
return {
|
||||
applied: [],
|
||||
failed: verificationFailuresForEntries(batch, batch.entries, 'missing_applied_entry_ids'),
|
||||
files: result.files || [],
|
||||
details: { notes: result.notes || [] },
|
||||
});
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
notes: result.notes || [],
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
const reportedAppliedEntries = batch.entries.filter((entry) => reportedAppliedIds.includes(entry.id));
|
||||
if (reportedAppliedIds.length > 0 && reportedFiles.length === 0) {
|
||||
return repairPostApplyValidation({
|
||||
...repairContext,
|
||||
batch,
|
||||
cwd,
|
||||
pageUrl,
|
||||
count,
|
||||
provider,
|
||||
env,
|
||||
timeoutMs,
|
||||
applyBatchToSource,
|
||||
chatAvailable,
|
||||
transactionId,
|
||||
appliedEntryIds: reportedAppliedIds,
|
||||
files: result.files || [],
|
||||
failed: aiFailed,
|
||||
@@ -1080,10 +1089,21 @@ export async function commitManualEdits({
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
verifiedIds: verifiedAppliedIds,
|
||||
failed: verificationFailed,
|
||||
} = verifyEntriesAfterRepair({ batch, appliedEntryIds: reportedAppliedIds, files: reportedFiles, cwd });
|
||||
const verifiedAppliedIds = [];
|
||||
const verificationFailed = [];
|
||||
for (const entry of reportedAppliedEntries) {
|
||||
const failures = verifyAppliedEntry({ batch, entry, reportedFiles, cwd });
|
||||
if (failures.length === 0) {
|
||||
verifiedAppliedIds.push(entry.id);
|
||||
} else {
|
||||
verificationFailed.push({
|
||||
id: entry.id,
|
||||
reason: 'source_verification_failed',
|
||||
failures,
|
||||
candidates: candidatesForEntry(batch, entry.id),
|
||||
});
|
||||
}
|
||||
}
|
||||
const unreportedEntries = result.status === 'done' || result.status === 'partial'
|
||||
? batch.entries.filter((entry) => !reportedAppliedIds.includes(entry.id) && !aiFailed.some((item) => item.id === entry.id))
|
||||
: [];
|
||||
@@ -1113,22 +1133,37 @@ export async function commitManualEdits({
|
||||
reason: 'rolled_back_due_to_failed_entry_source_changed',
|
||||
candidates: candidatesForEntry(batch, entry.id),
|
||||
}));
|
||||
return failWithRollback({
|
||||
scope: rollbackScope,
|
||||
extraFiles: result.files || [],
|
||||
const rollback = rollbackChangedFiles(cwd, rollbackSnapshot, result.files || [], rollbackScope);
|
||||
return {
|
||||
applied: [],
|
||||
failed: [
|
||||
...leakedUnapplied,
|
||||
...failed.filter((item) => !leakedIds.has(item.id)),
|
||||
...rolledBackVerified,
|
||||
],
|
||||
files: result.files || [],
|
||||
details: { notes: result.notes || [] },
|
||||
});
|
||||
cleared: 0,
|
||||
count,
|
||||
pageUrl,
|
||||
rolledBackFiles: rollback.rolledBackFiles,
|
||||
rollbackFailures: rollback.rollbackFailures,
|
||||
notes: result.notes || [],
|
||||
...countByPage(cwd),
|
||||
};
|
||||
}
|
||||
|
||||
if (verificationFailed.length > 0) {
|
||||
return repairPostApplyValidation({
|
||||
...repairContext,
|
||||
batch,
|
||||
cwd,
|
||||
pageUrl,
|
||||
count,
|
||||
provider,
|
||||
env,
|
||||
timeoutMs,
|
||||
applyBatchToSource,
|
||||
chatAvailable,
|
||||
transactionId,
|
||||
appliedEntryIds: reportedAppliedIds,
|
||||
files: result.files || [],
|
||||
failed: nonRepairFailed,
|
||||
@@ -1145,7 +1180,16 @@ export async function commitManualEdits({
|
||||
? reportedAppliedEntries.filter((entry) => verifiedAppliedIds.includes(entry.id))
|
||||
: batch.entries;
|
||||
return repairPostApplyValidation({
|
||||
...repairContext,
|
||||
batch,
|
||||
cwd,
|
||||
pageUrl,
|
||||
count,
|
||||
provider,
|
||||
env,
|
||||
timeoutMs,
|
||||
applyBatchToSource,
|
||||
chatAvailable,
|
||||
transactionId,
|
||||
appliedEntryIds: verifiedAppliedIds.length > 0
|
||||
? verifiedAppliedIds
|
||||
: postCheckEntries.map((entry) => entry.id).filter(Boolean),
|
||||
|
||||
@@ -1032,6 +1032,15 @@ describe('live-browser.js regression guards', () => {
|
||||
/case 'variant_progress':[\s\S]{0,120}?if \(msg\.publicationKind === 'params'\) parameterGenerationState = 'loading';/,
|
||||
'a params-only publication must mark Tune controls loading even though the variant count is unchanged',
|
||||
);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/function completeParameterGenerationIfReady\(\) \{[\s\S]{0,240}?arrivedVariants < expectedVariants[\s\S]{0,160}?parameterGenerationState === 'pending'[\s\S]{0,120}?completeParameterPublication\(\);/,
|
||||
'the completed variants publication must resolve pending Tune controls even when no params publication follows',
|
||||
);
|
||||
assert.ok(
|
||||
(SOURCE.match(/completeParameterGenerationIfReady\(\);/g) || []).length >= 4,
|
||||
'every DOM, source, and component-preview completion path must resolve pending Tune controls',
|
||||
);
|
||||
assert.match(SOURCE, /revisionDomain: 'browser'/, 'browser checkpoints must use their own revision domain');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user