Add route guardrails to Ranker handoff
This commit is contained in:
@@ -829,6 +829,27 @@ function guardrailTextItems(value = [], maxItems = 8) {
|
||||
return cleanFlexibleTextList(value, maxItems, 260).filter(item => /\b(avoid|no|do not|don't|dont|must not|never|non-goal|non goal|not yet|out of scope|defer|hold for later|set aside|probably noise|park|do not let this become|don't let this become|not a dashboard|dashboard swamp)\b/i.test(item));
|
||||
}
|
||||
|
||||
function inferIdeaRouteFromText(value = '') {
|
||||
const text = String(value || '').toLowerCase();
|
||||
if (/\b(game|games|gaming|player|players|playtest|prototype|steam|itch|console|pc|deck|roguelike|roguelite|rpg|shooter|bullet\s*hell|bullet-heaven|survival|enemy|enemies|weapon|weapons|level|arena|controller|joystick|driving|car|vehicle|combat|fps|platformer|metroidvania|puzzle game)\b/.test(text)) return 'game';
|
||||
if (/\b(service|agency|consulting|freelance|offer|client|local|shop|restaurant|webshop|sales|appointment)\b/.test(text)) return 'service_business';
|
||||
if (/\b(book|novel|story|comic|film|music|art|creative|writing|podcast|newsletter|course|zine)\b/.test(text)) return 'creative_project';
|
||||
if (/\b(community|members|audience|creator|content|social|discord|forum|club|fans|followers)\b/.test(text)) return 'content_community';
|
||||
if (/\b(physical|hardware|device|toy|wearable|material|manufactur|packaging|retail|kitchen|furniture|sensor)\b/.test(text)) return 'physical_product';
|
||||
if (/\b(internal|ops|admin|backoffice|team tool|employee|staff|inventory|support queue|process)\b/.test(text)) return 'internal_tool';
|
||||
if (/\b(saas|app|software|dashboard|workflow|api|plugin|extension|tool|users?|accounts?|subscription|crm|automation|webapp|mobile app)\b/.test(text)) return 'saas_app';
|
||||
return '';
|
||||
}
|
||||
|
||||
function routeGuardrailNonGoals(route = '') {
|
||||
if (route === 'game') {
|
||||
return [
|
||||
'Avoid accounts, dashboards, workspaces, collaboration, CRM, admin panels, onboarding, saved boards, and subscription tiers unless the source explicitly asks for business software.',
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function cleanDecisionContext(input = {}) {
|
||||
const envelope = bridgeEnvelopeFrom(input);
|
||||
const featureSet = featureSetFrom(input);
|
||||
@@ -873,7 +894,24 @@ function cleanDecisionContext(input = {}) {
|
||||
...guardrailTextItems(featureSet.threads_to_hold || featureSet.threadsToHold || featureSet.actionThreads || featureSet.action_threads, 8),
|
||||
...guardrailTextItems(input.threads_to_hold || input.threadsToHold || input.actionThreads || input.action_threads, 8),
|
||||
].filter(Boolean).join('\n'));
|
||||
const ideaRoute = cleanText(input.ideaType || input.idea_type || input.category || input.route || envelope.ideaType || envelope.idea_type || featureSet.ideaType || featureSet.idea_type || artifact.ideaType || artifact.idea_type || conceptMap.ideaType || conceptMap.idea_type || snapshot.ideaType || snapshot.idea_type || inferIdeaRouteFromText([
|
||||
input.idea,
|
||||
input.ideaText,
|
||||
input.idea_text,
|
||||
input.context,
|
||||
input.opening_reflection,
|
||||
input.restated_idea,
|
||||
envelope.idea,
|
||||
envelope.ideaText,
|
||||
envelope.context,
|
||||
conceptMap.opening_reflection,
|
||||
conceptMap.restated_idea,
|
||||
snapshot.restated_idea,
|
||||
lensContent(conceptMapLenses.shape),
|
||||
lensContent(conceptMapLenses.channel),
|
||||
].filter(Boolean).join('\n')), 60);
|
||||
return {
|
||||
ideaRoute,
|
||||
targetAudience: cleanText(input.targetAudience || input.target_audience || envelope.targetAudience || envelope.target_audience || featureSet.targetAudience || featureSet.target_audience || snapshot.targetAudience || snapshot.target_audience || firstContextText(contextSources, ['targetAudience', 'target_audience', 'audience', 'who', 'whoItHelps', 'who_it_helps', 'customer', 'users']) || conceptMap.targetAudience || conceptMap.target_audience || lensContent(audienceLens), 180),
|
||||
constraints: uniqueList([
|
||||
...cleanFlexibleTextList(input.constraints || envelope.constraints || featureSet.constraints || snapshot.constraints || conceptMap.constraints, 8, 180),
|
||||
@@ -885,6 +923,7 @@ function cleanDecisionContext(input = {}) {
|
||||
...cleanFlexibleTextList(input.nonGoals || input.non_goals || input.avoid || envelope.nonGoals || envelope.non_goals || envelope.avoid || featureSet.nonGoals || featureSet.non_goals || featureSet.avoid || snapshot.nonGoals || snapshot.non_goals || snapshot.avoid || conceptMap.nonGoals || conceptMap.non_goals || conceptMap.avoid, 8, 180),
|
||||
...collectContextList(contextSources, ['nonGoals', 'non_goals', 'nonGoal', 'non_goal', 'avoid', 'notYet', 'not_yet', 'doNotBuild', 'do_not_build'], 8),
|
||||
...textContextGuardrails.nonGoals,
|
||||
...routeGuardrailNonGoals(ideaRoute),
|
||||
], 8),
|
||||
assumptions: uniqueList([
|
||||
...cleanFlexibleTextList(input.assumptions || envelope.assumptions || featureSet.assumptions || snapshot.assumptions || conceptMap.assumptions, 6, 180),
|
||||
@@ -1786,6 +1825,7 @@ function copyableHandoffText({ ranked = [], provenance = {}, decisionContext = {
|
||||
? `Source summary: ${cleanText(provenance.sourceSummary, 240)}`
|
||||
: '';
|
||||
const contextLines = [
|
||||
decisionContext?.ideaRoute ? `Idea route: ${decisionContext.ideaRoute}` : '',
|
||||
decisionContext?.targetAudience ? `Audience: ${decisionContext.targetAudience}` : '',
|
||||
...(decisionContext?.constraints || []).slice(0, 3).map(item => `Constraint: ${item}`),
|
||||
...(decisionContext?.nonGoals || []).slice(0, 3).map(item => `Non-goal: ${item}`),
|
||||
@@ -1877,6 +1917,7 @@ function createHandoffContract({ ranked, provenance, decisionContext }) {
|
||||
requiresSourceTrace: expectsSourceTrace,
|
||||
},
|
||||
decisionContext: {
|
||||
ideaRoute: decisionContext?.ideaRoute || '',
|
||||
targetAudience: decisionContext?.targetAudience || '',
|
||||
constraints: decisionContext?.constraints || [],
|
||||
nonGoals: decisionContext?.nonGoals || [],
|
||||
|
||||
Reference in New Issue
Block a user