Add rank handoff readiness gate

This commit is contained in:
OpenClaw Bot
2026-05-27 00:51:03 +02:00
parent 6cd5c52683
commit 9dbcd7770b
3 changed files with 71 additions and 3 deletions
+57 -1
View File
@@ -1141,6 +1141,60 @@ function compactBuildItems(items = []) {
}));
}
function handoffReadinessFor({ ranked = [], provenance = {}, warnings = [], expectsSourceTrace = false }) {
const uniqueWarnings = [...new Set(warnings)];
const activeItems = ranked.filter(item => ['do', 'test'].includes(item.lane?.id));
const guardrailWarnings = uniqueWarnings.filter(item => /^active item .* conflicts with source non-goals/i.test(item));
const sourceWarnings = uniqueWarnings.filter(item => /^missing (source section|original prompt provenance)/i.test(item));
const evidenceWarnings = uniqueWarnings.filter(item => /^missing evidence needed for active item/i.test(item));
const duplicateWarnings = uniqueWarnings.filter(item => /^duplicate source id/i.test(item));
const missingArtifact = uniqueWarnings.includes('missing source artifact id');
const blockers = [
...guardrailWarnings,
...(expectsSourceTrace ? sourceWarnings : []),
...(expectsSourceTrace ? evidenceWarnings : []),
];
const nextChecks = [];
if (guardrailWarnings.length) nextChecks.push('Resolve source non-goal conflicts before treating any active item as build-ready.');
if (expectsSourceTrace && sourceWarnings.length) nextChecks.push('Attach source section / prompt provenance from the Scattermind artifact.');
if (expectsSourceTrace && evidenceWarnings.length) nextChecks.push('Add evidenceNeeded to every Do first / Validate next candidate before handoff.');
if (missingArtifact) nextChecks.push(expectsSourceTrace ? 'Attach the Scattermind artifact id so the build order can be traced back.' : 'Attach a source artifact id if this came from Scattermind rather than a plain paste.');
if (duplicateWarnings.length) nextChecks.push('Review normalized duplicate IDs before downstream tools store references.');
if (!nextChecks.length && activeItems.length) nextChecks.push('Use the Do first item as the only active build slice, then rerank after evidence changes.');
const status = guardrailWarnings.length
? 'blocked'
: blockers.length
? 'needs-source-context'
: uniqueWarnings.length
? 'usable-with-warnings'
: 'ready';
const labels = {
ready: 'Ready for Ranker handoff',
'usable-with-warnings': 'Usable, but provenance is thin',
'needs-source-context': 'Needs source context before handoff',
blocked: 'Blocked by source guardrails',
};
const summaries = {
ready: `Active order is traceable and evidence-shaped for ${activeItems.length} active item${activeItems.length === 1 ? '' : 's'}.`,
'usable-with-warnings': 'Ranking can be read now, but downstream bridge consumers should review the warnings before storing it as a defended handoff.',
'needs-source-context': 'A Scattermind-shaped artifact is present, but active items are missing trace or evidence fields needed to defend the order later.',
blocked: 'An active item conflicts with source non-goals; do not continue until the guardrail is resolved or the item moves out of the active lanes.',
};
return {
status,
label: labels[status],
summary: summaries[status],
blockers,
nextChecks: nextChecks.slice(0, 5),
activeItemCount: activeItems.length,
warningCount: uniqueWarnings.length,
sourceComplete: Boolean(!expectsSourceTrace || (provenance?.originalPrompt && activeItems.every(item => item.provenance?.sourceSection))),
};
}
function createHandoffContract({ ranked, provenance, decisionContext }) {
const warnings = [];
const expectsSourceTrace = Boolean(provenance?.artifactId || provenance?.conceptMapId || provenance?.snapshotTitle);
@@ -1169,6 +1223,7 @@ function createHandoffContract({ ranked, provenance, decisionContext }) {
nonGoalConflicts: item.metrics?.nonGoalConflicts || [],
};
});
const uniqueWarnings = [...new Set(warnings)];
return {
schema: 'rank-feedback-result-v1',
@@ -1189,7 +1244,8 @@ function createHandoffContract({ ranked, provenance, decisionContext }) {
assumptions: decisionContext?.assumptions || [],
},
itemTrace,
warnings: [...new Set(warnings)],
warnings: uniqueWarnings,
readiness: handoffReadinessFor({ ranked, provenance, warnings: uniqueWarnings, expectsSourceTrace }),
};
}