Harden Scattermind bridge envelope import
This commit is contained in:
@@ -1043,7 +1043,50 @@ try {
|
||||
assert.equal(summaryGuardrail.ranked.find(item => item.id === 'billing-summary').lane.source, 'source-non-goal');
|
||||
assert.deepEqual(summaryGuardrail.handoff.warnings, []);
|
||||
|
||||
console.log(JSON.stringify({ ok: true, top: data.ranked[0].id, hintedTop: hinted.ranked[0].id, actionTop: actions.ranked[0].id, nestedConceptTop: nestedConcept.ranked[0].id, nonGoalTop: nonGoal.ranked[0].id, structuredContextTop: structuredContext.ranked[0].id, lensOnlyTop: lensOnly.ranked[0].id, scattermindPaidShapeTop: scattermindPaidShape.ranked[0].id, mergedContextTop: mergedContext.ranked[0].id, embeddedJsonTop: embeddedJson.ranked[0].id, fencedJsonTop: fencedJson.ranked[0].id, embeddedSnapshotTop: embeddedSnapshot.ranked[0].id, sourceExcerptTop: sourceExcerpt.ranked[0].id, snakeCaseBridgeTop: snakeCaseBridge.ranked[0].id, nextStepsAliasTop: nextStepsAlias.ranked[0].id, summaryGuardrailTop: summaryGuardrail.ranked[0].id, duplicateIds: duplicateIds.ranked.map(item => item.id), readiness: data.handoff.readiness.status, provenance: data.input.provenance, buildOrder: data.buildOrder }, null, 2));
|
||||
const bridgeEnvelopeResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
schema: 'scattermind-ranker-bridge-v1',
|
||||
rankerInput: {
|
||||
schema: 'prioritix-feature-set-v1',
|
||||
sourceName: 'Scattermind',
|
||||
reference_code: 'SM-BRIDGE-ENV-1',
|
||||
working_name: 'Envelope bridge export',
|
||||
ideaText: 'A paid Concept Map clarified the idea and now needs a defended build order.',
|
||||
context: {
|
||||
targetAudience: 'Tired solo operator',
|
||||
constraints: ['Manual source-traced proof before product shell'],
|
||||
avoid: ['Avoid accounts, billing, and saved workspaces before bridge proof'],
|
||||
},
|
||||
candidateSet: {
|
||||
nextActions: [
|
||||
{ id: 'envelope-manual-proof', action: 'Envelope manual build-order proof', why: 'Proves a wrapped Scattermind export can become a Rank-ready first move.', evidenceNeeded: 'Can one wrapped Concept Map produce a traceable Do first lane?', sourceSection: 'rankerInput.candidateSet.nextActions', sourceItemId: 'env-next-1', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } },
|
||||
{ id: 'envelope-copyable-brief', action: 'Envelope copyable decision brief', why: 'Keeps provenance and next step portable.', evidenceNeeded: 'Does the copyable handoff include the wrapped source?', sourceSection: 'rankerInput.candidateSet.nextActions', sourceItemId: 'env-next-2', suggestedLane: 'validate-next' },
|
||||
],
|
||||
parkingLot: [
|
||||
{ id: 'envelope-workspace', action: 'Envelope saved workspace dashboard', why: 'Accounts, billing, saved projects, and collaboration.', evidenceNeeded: 'No bridge proof yet.', suggestedLane: 'park', sourceSection: 'rankerInput.candidateSet.parkingLot', sourceItemId: 'env-park-1' },
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
assert.equal(bridgeEnvelopeResponse.status, 200);
|
||||
const bridgeEnvelope = await bridgeEnvelopeResponse.json();
|
||||
assert.equal(bridgeEnvelope.input.provenance.artifactId, 'SM-BRIDGE-ENV-1');
|
||||
assert.equal(bridgeEnvelope.input.provenance.snapshotTitle, 'Envelope bridge export');
|
||||
assert.equal(bridgeEnvelope.input.provenance.originalPrompt, 'A paid Concept Map clarified the idea and now needs a defended build order.');
|
||||
assert.equal(bridgeEnvelope.input.decisionContext.targetAudience, 'Tired solo operator');
|
||||
assert.ok(bridgeEnvelope.input.decisionContext.nonGoals.includes('Avoid accounts, billing, and saved workspaces before bridge proof'));
|
||||
assert.equal(bridgeEnvelope.input.context, 'Target audience: Tired solo operator\nConstraint: Manual source-traced proof before product shell\nNon-goal: Avoid accounts, billing, and saved workspaces before bridge proof');
|
||||
assert.equal(bridgeEnvelope.ranked[0].id, 'envelope-manual-proof');
|
||||
assert.equal(bridgeEnvelope.ranked[0].provenance.sourceSection, 'rankerInput.candidateSet.nextActions');
|
||||
assert.equal(bridgeEnvelope.ranked.find(item => item.id === 'envelope-workspace').lane.id, 'park');
|
||||
assert.equal(bridgeEnvelope.handoff.readiness.status, 'ready');
|
||||
assert.match(bridgeEnvelope.handoff.copyableText, /SM-BRIDGE-ENV-1/);
|
||||
assert.deepEqual(bridgeEnvelope.handoff.warnings, []);
|
||||
|
||||
console.log(JSON.stringify({ ok: true, top: data.ranked[0].id, hintedTop: hinted.ranked[0].id, actionTop: actions.ranked[0].id, nestedConceptTop: nestedConcept.ranked[0].id, nonGoalTop: nonGoal.ranked[0].id, structuredContextTop: structuredContext.ranked[0].id, lensOnlyTop: lensOnly.ranked[0].id, scattermindPaidShapeTop: scattermindPaidShape.ranked[0].id, mergedContextTop: mergedContext.ranked[0].id, embeddedJsonTop: embeddedJson.ranked[0].id, fencedJsonTop: fencedJson.ranked[0].id, embeddedSnapshotTop: embeddedSnapshot.ranked[0].id, sourceExcerptTop: sourceExcerpt.ranked[0].id, snakeCaseBridgeTop: snakeCaseBridge.ranked[0].id, nextStepsAliasTop: nextStepsAlias.ranked[0].id, summaryGuardrailTop: summaryGuardrail.ranked[0].id, bridgeEnvelopeTop: bridgeEnvelope.ranked[0].id, duplicateIds: duplicateIds.ranked.map(item => item.id), readiness: data.handoff.readiness.status, provenance: data.input.provenance, buildOrder: data.buildOrder }, null, 2));
|
||||
} finally {
|
||||
server.kill('SIGTERM');
|
||||
}
|
||||
|
||||
@@ -486,11 +486,61 @@ function objectFrom(value) {
|
||||
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
||||
}
|
||||
|
||||
function bridgeEnvelopeFrom(input = {}) {
|
||||
const body = objectFrom(input);
|
||||
return objectFrom(
|
||||
body.rankerInput
|
||||
|| body.ranker_input
|
||||
|| body.rankerHandoff
|
||||
|| body.ranker_handoff
|
||||
|| body.rankReady
|
||||
|| body.rank_ready
|
||||
|| body.bridge
|
||||
|| body.bridgePayload
|
||||
|| body.bridge_payload
|
||||
);
|
||||
}
|
||||
|
||||
function featureSetFrom(input = {}) {
|
||||
const body = objectFrom(input);
|
||||
const envelope = bridgeEnvelopeFrom(body);
|
||||
return objectFrom(
|
||||
body.featureSet
|
||||
|| body.feature_set
|
||||
|| body.candidateSet
|
||||
|| body.candidate_set
|
||||
|| body.candidateFeatureSet
|
||||
|| body.candidate_feature_set
|
||||
|| body.rankReadyFeatureSet
|
||||
|| body.rank_ready_feature_set
|
||||
|| envelope.featureSet
|
||||
|| envelope.feature_set
|
||||
|| envelope.candidateSet
|
||||
|| envelope.candidate_set
|
||||
|| envelope.candidateFeatureSet
|
||||
|| envelope.candidate_feature_set
|
||||
|| envelope.rankReadyFeatureSet
|
||||
|| envelope.rank_ready_feature_set
|
||||
);
|
||||
}
|
||||
|
||||
function looksLikeRankPayload(value = {}) {
|
||||
return Boolean(
|
||||
value.schema
|
||||
|| value.featureSet
|
||||
|| value.feature_set
|
||||
|| value.candidateSet
|
||||
|| value.candidate_set
|
||||
|| value.candidateFeatureSet
|
||||
|| value.candidate_feature_set
|
||||
|| value.rankerInput
|
||||
|| value.ranker_input
|
||||
|| value.rankerHandoff
|
||||
|| value.ranker_handoff
|
||||
|| value.rankReady
|
||||
|| value.rank_ready
|
||||
|| value.bridgePayload
|
||||
|| value.bridge_payload
|
||||
|| value.snapshot
|
||||
|| value.conceptMap
|
||||
|| value.concept_map
|
||||
@@ -589,19 +639,20 @@ function expandEmbeddedRankPayload(body = {}) {
|
||||
}
|
||||
|
||||
function cleanProvenance(input = {}) {
|
||||
const featureSet = objectFrom(input.featureSet || input.feature_set);
|
||||
const artifact = objectFrom(input.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(input.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const source = objectFrom(input.source || featureSet.source || artifact.source);
|
||||
const sourceSummary = input.sourceSummary || input.source_summary || input.opening_reflection || input.restated_idea || artifact.sourceSummary || artifact.source_summary || artifact.opening_reflection || snapshot.sourceSummary || snapshot.source_summary || snapshot.restated_idea || conceptMap.sourceSummary || conceptMap.source_summary || conceptMap.opening_reflection || conceptMap.restated_idea || '';
|
||||
const envelope = bridgeEnvelopeFrom(input);
|
||||
const featureSet = featureSetFrom(input);
|
||||
const artifact = objectFrom(input.artifact || envelope.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(input.snapshot || envelope.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const source = objectFrom(input.source || envelope.source || featureSet.source || artifact.source);
|
||||
const sourceSummary = input.sourceSummary || input.source_summary || input.opening_reflection || input.restated_idea || envelope.sourceSummary || envelope.source_summary || envelope.opening_reflection || envelope.restated_idea || artifact.sourceSummary || artifact.source_summary || artifact.opening_reflection || snapshot.sourceSummary || snapshot.source_summary || snapshot.restated_idea || conceptMap.sourceSummary || conceptMap.source_summary || conceptMap.opening_reflection || conceptMap.restated_idea || '';
|
||||
return {
|
||||
schema: cleanText(input.schema || featureSet.schema || artifact.schema || input.type || 'prioritix-feature-set-v1', 80),
|
||||
source: cleanText(input.sourceName || input.source_name || featureSet.sourceName || featureSet.source_name || source.name || artifact.sourceName || artifact.source_name || 'Scattermind', 80),
|
||||
artifactId: cleanText(input.artifactId || input.artifact_id || input.sourceArtifactId || input.source_artifact_id || input.referenceCode || input.reference_code || artifact.id || source.artifactId || source.artifact_id || conceptMap.artifactId || conceptMap.artifact_id || conceptMap.id || conceptMap.referenceCode || conceptMap.reference_code || snapshot.artifactId || snapshot.artifact_id || snapshot.id || '', 120),
|
||||
snapshotTitle: cleanText(input.snapshotTitle || input.snapshot_title || input.working_name || input.workingName || artifact.snapshotTitle || artifact.snapshot_title || snapshot.title || snapshot.name || conceptMap.snapshotTitle || conceptMap.snapshot_title || conceptMap.working_name || conceptMap.workingName || input.ideaTitle || input.idea_title || '', 160),
|
||||
conceptMapId: cleanText(input.conceptMapId || input.concept_map_id || artifact.conceptMapId || artifact.concept_map_id || conceptMap.id || conceptMap.artifactId || conceptMap.artifact_id || input.referenceCode || input.reference_code || conceptMap.referenceCode || conceptMap.reference_code || '', 120),
|
||||
originalPrompt: cleanMultiline(input.originalPrompt || input.original_prompt || input.initialPrompt || input.initial_prompt || input.ideaText || input.idea_text || input.prompt || artifact.originalPrompt || artifact.original_prompt || source.originalPrompt || source.original_prompt || snapshot.originalPrompt || snapshot.original_prompt || snapshot.prompt || conceptMap.originalPrompt || conceptMap.original_prompt || conceptMap.ideaText || conceptMap.idea_text || input.idea || '', 1200),
|
||||
schema: cleanText(input.schema || envelope.schema || featureSet.schema || artifact.schema || input.type || envelope.type || 'prioritix-feature-set-v1', 80),
|
||||
source: cleanText(input.sourceName || input.source_name || envelope.sourceName || envelope.source_name || featureSet.sourceName || featureSet.source_name || source.name || artifact.sourceName || artifact.source_name || 'Scattermind', 80),
|
||||
artifactId: cleanText(input.artifactId || input.artifact_id || input.sourceArtifactId || input.source_artifact_id || input.referenceCode || input.reference_code || envelope.artifactId || envelope.artifact_id || envelope.sourceArtifactId || envelope.source_artifact_id || envelope.referenceCode || envelope.reference_code || artifact.id || source.artifactId || source.artifact_id || conceptMap.artifactId || conceptMap.artifact_id || conceptMap.id || conceptMap.referenceCode || conceptMap.reference_code || snapshot.artifactId || snapshot.artifact_id || snapshot.id || '', 120),
|
||||
snapshotTitle: cleanText(input.snapshotTitle || input.snapshot_title || input.working_name || input.workingName || envelope.snapshotTitle || envelope.snapshot_title || envelope.working_name || envelope.workingName || artifact.snapshotTitle || artifact.snapshot_title || snapshot.title || snapshot.name || conceptMap.snapshotTitle || conceptMap.snapshot_title || conceptMap.working_name || conceptMap.workingName || input.ideaTitle || input.idea_title || envelope.ideaTitle || envelope.idea_title || '', 160),
|
||||
conceptMapId: cleanText(input.conceptMapId || input.concept_map_id || envelope.conceptMapId || envelope.concept_map_id || artifact.conceptMapId || artifact.concept_map_id || conceptMap.id || conceptMap.artifactId || conceptMap.artifact_id || input.referenceCode || input.reference_code || envelope.referenceCode || envelope.reference_code || conceptMap.referenceCode || conceptMap.reference_code || '', 120),
|
||||
originalPrompt: cleanMultiline(input.originalPrompt || input.original_prompt || input.initialPrompt || input.initial_prompt || input.ideaText || input.idea_text || input.prompt || envelope.originalPrompt || envelope.original_prompt || envelope.initialPrompt || envelope.initial_prompt || envelope.ideaText || envelope.idea_text || envelope.prompt || artifact.originalPrompt || artifact.original_prompt || source.originalPrompt || source.original_prompt || snapshot.originalPrompt || snapshot.original_prompt || snapshot.prompt || conceptMap.originalPrompt || conceptMap.original_prompt || conceptMap.ideaText || conceptMap.idea_text || input.idea || envelope.idea || '', 1200),
|
||||
sourceSummary: cleanMultiline(sourceSummary, 1200),
|
||||
};
|
||||
}
|
||||
@@ -643,11 +694,12 @@ function contextGuardrailText(value = '') {
|
||||
}
|
||||
|
||||
function cleanDecisionContext(input = {}) {
|
||||
const featureSet = objectFrom(input.featureSet || input.feature_set);
|
||||
const artifact = objectFrom(input.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(input.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const conceptMapLenses = objectFrom(conceptMap.lenses || input.lenses || featureSet.lenses);
|
||||
const envelope = bridgeEnvelopeFrom(input);
|
||||
const featureSet = featureSetFrom(input);
|
||||
const artifact = objectFrom(input.artifact || envelope.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(input.snapshot || envelope.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const conceptMapLenses = objectFrom(conceptMap.lenses || input.lenses || envelope.lenses || featureSet.lenses);
|
||||
const riskLens = conceptMapLenses.risk || conceptMapLenses.risks || conceptMapLenses.boundaries || conceptMapLenses.notYet;
|
||||
const audienceLens = conceptMapLenses.audience || conceptMapLenses.who || conceptMapLenses.customer || conceptMapLenses.users;
|
||||
const constraintsLens = conceptMapLenses.constraints || conceptMapLenses.boundaries || conceptMapLenses.scope;
|
||||
@@ -655,11 +707,13 @@ function cleanDecisionContext(input = {}) {
|
||||
const structuredContext = objectFrom(input.context);
|
||||
const contextSources = [
|
||||
input.decisionContext,
|
||||
envelope.decisionContext,
|
||||
featureSet.decisionContext,
|
||||
artifact.decisionContext,
|
||||
conceptMap.decisionContext,
|
||||
snapshot.decisionContext,
|
||||
structuredContext,
|
||||
envelope.context,
|
||||
conceptMap.context,
|
||||
snapshot.context,
|
||||
featureSet.context,
|
||||
@@ -667,6 +721,7 @@ function cleanDecisionContext(input = {}) {
|
||||
];
|
||||
const textContextGuardrails = guardrailsFromContextText([
|
||||
contextGuardrailText(input.context || ''),
|
||||
contextGuardrailText(envelope.context || ''),
|
||||
contextGuardrailText(featureSet.context || ''),
|
||||
contextGuardrailText(artifact.context || ''),
|
||||
contextGuardrailText(snapshot.context || ''),
|
||||
@@ -677,20 +732,20 @@ function cleanDecisionContext(input = {}) {
|
||||
snapshot.risk || snapshot.whatNotToBuildYet || snapshot.notYet || '',
|
||||
].filter(Boolean).join('\n'));
|
||||
return {
|
||||
targetAudience: cleanText(input.targetAudience || input.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),
|
||||
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 || featureSet.constraints || snapshot.constraints || conceptMap.constraints, 8, 180),
|
||||
...cleanFlexibleTextList(input.constraints || envelope.constraints || featureSet.constraints || snapshot.constraints || conceptMap.constraints, 8, 180),
|
||||
...collectContextList(contextSources, ['constraints', 'constraint', 'boundaries', 'scope'], 8),
|
||||
...cleanSentenceList(lensContent(constraintsLens), 8, 180),
|
||||
...textContextGuardrails.constraints,
|
||||
], 8),
|
||||
nonGoals: uniqueList([
|
||||
...cleanFlexibleTextList(input.nonGoals || input.non_goals || input.avoid || featureSet.nonGoals || featureSet.non_goals || featureSet.avoid || snapshot.nonGoals || snapshot.non_goals || snapshot.avoid || conceptMap.nonGoals || conceptMap.non_goals || conceptMap.avoid, 8, 180),
|
||||
...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,
|
||||
], 8),
|
||||
assumptions: uniqueList([
|
||||
...cleanFlexibleTextList(input.assumptions || featureSet.assumptions || snapshot.assumptions || conceptMap.assumptions, 6, 180),
|
||||
...cleanFlexibleTextList(input.assumptions || envelope.assumptions || featureSet.assumptions || snapshot.assumptions || conceptMap.assumptions, 6, 180),
|
||||
...collectContextList(contextSources, ['assumptions', 'assumption', 'unknowns', 'openQuestions'], 6),
|
||||
...cleanSentenceList(lensContent(assumptionsLens), 6, 180),
|
||||
], 6),
|
||||
@@ -865,16 +920,19 @@ function optionsFromBuildOrderText(text = '', sourceSection = 'concept-map.lense
|
||||
}
|
||||
|
||||
function optionsFromBody(body = {}) {
|
||||
const featureSet = objectFrom(body.featureSet || body.feature_set);
|
||||
const artifact = objectFrom(body.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(body.conceptMap || body.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(body.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const conceptMapLenses = objectFrom(conceptMap.lenses || body.lenses || featureSet.lenses);
|
||||
const envelope = bridgeEnvelopeFrom(body);
|
||||
const featureSet = featureSetFrom(body);
|
||||
const artifact = objectFrom(body.artifact || envelope.artifact || featureSet.artifact);
|
||||
const conceptMap = objectFrom(body.conceptMap || body.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||
const snapshot = objectFrom(body.snapshot || envelope.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||
const conceptMapLenses = objectFrom(conceptMap.lenses || body.lenses || envelope.lenses || featureSet.lenses);
|
||||
const buildOrderLens = objectFrom(conceptMapLenses.channel || conceptMapLenses.buildOrder || conceptMap.buildOrder);
|
||||
const directCandidateGroup = compactCandidateGroup([
|
||||
{ items: body.features, sourceSection: 'features' },
|
||||
{ items: envelope.features, sourceSection: 'ranker-input.features' },
|
||||
{ items: featureSet.features, sourceSection: 'feature-set.features' },
|
||||
{ items: body.actions, sourceSection: 'actions' },
|
||||
{ items: envelope.actions, sourceSection: 'ranker-input.actions' },
|
||||
{ items: featureSet.actions, sourceSection: 'feature-set.actions' },
|
||||
{ items: body.nextActions || body.next_actions || body.nextSteps || body.next_steps || body.recommendedNextSteps || body.recommended_next_steps, sourceSection: 'nextActions' },
|
||||
{ items: featureSet.nextActions || featureSet.next_actions || featureSet.nextSteps || featureSet.next_steps || featureSet.recommendedNextSteps || featureSet.recommended_next_steps, sourceSection: 'feature-set.nextActions' },
|
||||
@@ -888,6 +946,9 @@ function optionsFromBody(body = {}) {
|
||||
{ items: featureSet.experiments, sourceSection: 'feature-set.experiments', defaultLane: 'validate-next' },
|
||||
{ items: featureSet.validationTests || featureSet.validation_tests, sourceSection: 'feature-set.experiments', defaultLane: 'validate-next' },
|
||||
{ items: featureSet.proofTests || featureSet.proof_tests, sourceSection: 'feature-set.experiments', defaultLane: 'validate-next' },
|
||||
{ items: featureSet.validateNext || featureSet.validate_next || featureSet.validate || featureSet.validation, sourceSection: 'feature-set.validateNext', defaultLane: 'validate-next' },
|
||||
{ items: featureSet.deferred || featureSet.defer || featureSet.later, sourceSection: 'feature-set.deferred', defaultLane: 'defer' },
|
||||
{ items: featureSet.parkingLot || featureSet.parking_lot || featureSet.park || featureSet.parked, sourceSection: 'feature-set.parkingLot', defaultLane: 'park' },
|
||||
]);
|
||||
const conceptMapCandidateGroup = compactCandidateGroup([
|
||||
{ items: conceptMap.nextActions || conceptMap.next_actions || conceptMap.nextSteps || conceptMap.next_steps || conceptMap.recommendedNextSteps || conceptMap.recommended_next_steps, sourceSection: 'concept-map.nextActions' },
|
||||
@@ -919,6 +980,7 @@ function optionsFromBody(body = {}) {
|
||||
...snapshotCandidateGroup,
|
||||
...conceptMapCandidateGroup,
|
||||
...buildOrderSectionGroup(body.buildOrder || body.build_order, 'buildOrder'),
|
||||
...buildOrderSectionGroup(envelope.buildOrder || envelope.build_order, 'ranker-input.buildOrder'),
|
||||
...buildOrderSectionGroup(featureSet.buildOrder || featureSet.build_order, 'feature-set.buildOrder'),
|
||||
...buildOrderSectionGroup(snapshot.buildOrder || snapshot.build_order, 'snapshot.buildOrder'),
|
||||
...buildOrderSectionGroup(conceptMap.buildOrder || conceptMap.build_order, 'concept-map.buildOrder'),
|
||||
@@ -943,8 +1005,8 @@ function optionsFromBody(body = {}) {
|
||||
if (Array.isArray(body.options)) {
|
||||
return normalizeOptionIds(body.options.slice(0, 24).map((item, index) => normalizeFeatureOption(item, index, 'option', 'options')).filter(item => item.title));
|
||||
}
|
||||
const fallbackText = body.optionsText || featureSet.optionsText || conceptMap.optionsText || body.idea || body.ideaText || '';
|
||||
const fallbackSourceSection = body.optionsText || featureSet.optionsText || conceptMap.optionsText
|
||||
const fallbackText = body.optionsText || envelope.optionsText || featureSet.optionsText || conceptMap.optionsText || body.idea || body.ideaText || envelope.idea || envelope.ideaText || '';
|
||||
const fallbackSourceSection = body.optionsText || envelope.optionsText || featureSet.optionsText || conceptMap.optionsText
|
||||
? 'optionsText'
|
||||
: body.idea
|
||||
? 'idea'
|
||||
@@ -1402,9 +1464,10 @@ function createHandoffContract({ ranked, provenance, decisionContext }) {
|
||||
|
||||
app.post('/api/rank-feedback', (req, res) => {
|
||||
const body = expandEmbeddedRankPayload(req.body || {});
|
||||
const idea = cleanMultiline(body?.idea || body?.opening_reflection || body?.restated_idea || '', 3000);
|
||||
const context = cleanContextText(body?.context || '');
|
||||
const modeId = cleanText(body?.mode || 'progress', 40);
|
||||
const envelope = bridgeEnvelopeFrom(body);
|
||||
const idea = cleanMultiline(body?.idea || body?.ideaText || body?.idea_text || body?.opening_reflection || body?.restated_idea || envelope.idea || envelope.ideaText || envelope.idea_text || envelope.opening_reflection || envelope.restated_idea || '', 3000);
|
||||
const context = cleanContextText(body?.context || envelope.context || '');
|
||||
const modeId = cleanText(body?.mode || envelope.mode || 'progress', 40);
|
||||
const mode = judgementModes[modeId] || judgementModes.progress;
|
||||
const provenance = cleanProvenance(body || {});
|
||||
const decisionContext = cleanDecisionContext(body || {});
|
||||
|
||||
Reference in New Issue
Block a user