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.equal(summaryGuardrail.ranked.find(item => item.id === 'billing-summary').lane.source, 'source-non-goal');
|
||||||
assert.deepEqual(summaryGuardrail.handoff.warnings, []);
|
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 {
|
} finally {
|
||||||
server.kill('SIGTERM');
|
server.kill('SIGTERM');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -486,11 +486,61 @@ function objectFrom(value) {
|
|||||||
return value && typeof value === 'object' && !Array.isArray(value) ? 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 = {}) {
|
function looksLikeRankPayload(value = {}) {
|
||||||
return Boolean(
|
return Boolean(
|
||||||
value.schema
|
value.schema
|
||||||
|| value.featureSet
|
|| value.featureSet
|
||||||
|| value.feature_set
|
|| 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.snapshot
|
||||||
|| value.conceptMap
|
|| value.conceptMap
|
||||||
|| value.concept_map
|
|| value.concept_map
|
||||||
@@ -589,19 +639,20 @@ function expandEmbeddedRankPayload(body = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanProvenance(input = {}) {
|
function cleanProvenance(input = {}) {
|
||||||
const featureSet = objectFrom(input.featureSet || input.feature_set);
|
const envelope = bridgeEnvelopeFrom(input);
|
||||||
const artifact = objectFrom(input.artifact || featureSet.artifact);
|
const featureSet = featureSetFrom(input);
|
||||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
const artifact = objectFrom(input.artifact || envelope.artifact || featureSet.artifact);
|
||||||
const snapshot = objectFrom(input.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
const conceptMap = objectFrom(input.conceptMap || input.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||||
const source = objectFrom(input.source || featureSet.source || artifact.source);
|
const snapshot = objectFrom(input.snapshot || envelope.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
||||||
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 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 {
|
return {
|
||||||
schema: cleanText(input.schema || featureSet.schema || artifact.schema || input.type || 'prioritix-feature-set-v1', 80),
|
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 || featureSet.sourceName || featureSet.source_name || source.name || artifact.sourceName || artifact.source_name || 'Scattermind', 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 || 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),
|
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 || 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),
|
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 || artifact.conceptMapId || artifact.concept_map_id || conceptMap.id || conceptMap.artifactId || conceptMap.artifact_id || input.referenceCode || input.reference_code || conceptMap.referenceCode || conceptMap.reference_code || '', 120),
|
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 || 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),
|
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),
|
sourceSummary: cleanMultiline(sourceSummary, 1200),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -643,11 +694,12 @@ function contextGuardrailText(value = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanDecisionContext(input = {}) {
|
function cleanDecisionContext(input = {}) {
|
||||||
const featureSet = objectFrom(input.featureSet || input.feature_set);
|
const envelope = bridgeEnvelopeFrom(input);
|
||||||
const artifact = objectFrom(input.artifact || featureSet.artifact);
|
const featureSet = featureSetFrom(input);
|
||||||
const conceptMap = objectFrom(input.conceptMap || input.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
const artifact = objectFrom(input.artifact || envelope.artifact || featureSet.artifact);
|
||||||
const snapshot = objectFrom(input.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
const conceptMap = objectFrom(input.conceptMap || input.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||||
const conceptMapLenses = objectFrom(conceptMap.lenses || input.lenses || featureSet.lenses);
|
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 riskLens = conceptMapLenses.risk || conceptMapLenses.risks || conceptMapLenses.boundaries || conceptMapLenses.notYet;
|
||||||
const audienceLens = conceptMapLenses.audience || conceptMapLenses.who || conceptMapLenses.customer || conceptMapLenses.users;
|
const audienceLens = conceptMapLenses.audience || conceptMapLenses.who || conceptMapLenses.customer || conceptMapLenses.users;
|
||||||
const constraintsLens = conceptMapLenses.constraints || conceptMapLenses.boundaries || conceptMapLenses.scope;
|
const constraintsLens = conceptMapLenses.constraints || conceptMapLenses.boundaries || conceptMapLenses.scope;
|
||||||
@@ -655,11 +707,13 @@ function cleanDecisionContext(input = {}) {
|
|||||||
const structuredContext = objectFrom(input.context);
|
const structuredContext = objectFrom(input.context);
|
||||||
const contextSources = [
|
const contextSources = [
|
||||||
input.decisionContext,
|
input.decisionContext,
|
||||||
|
envelope.decisionContext,
|
||||||
featureSet.decisionContext,
|
featureSet.decisionContext,
|
||||||
artifact.decisionContext,
|
artifact.decisionContext,
|
||||||
conceptMap.decisionContext,
|
conceptMap.decisionContext,
|
||||||
snapshot.decisionContext,
|
snapshot.decisionContext,
|
||||||
structuredContext,
|
structuredContext,
|
||||||
|
envelope.context,
|
||||||
conceptMap.context,
|
conceptMap.context,
|
||||||
snapshot.context,
|
snapshot.context,
|
||||||
featureSet.context,
|
featureSet.context,
|
||||||
@@ -667,6 +721,7 @@ function cleanDecisionContext(input = {}) {
|
|||||||
];
|
];
|
||||||
const textContextGuardrails = guardrailsFromContextText([
|
const textContextGuardrails = guardrailsFromContextText([
|
||||||
contextGuardrailText(input.context || ''),
|
contextGuardrailText(input.context || ''),
|
||||||
|
contextGuardrailText(envelope.context || ''),
|
||||||
contextGuardrailText(featureSet.context || ''),
|
contextGuardrailText(featureSet.context || ''),
|
||||||
contextGuardrailText(artifact.context || ''),
|
contextGuardrailText(artifact.context || ''),
|
||||||
contextGuardrailText(snapshot.context || ''),
|
contextGuardrailText(snapshot.context || ''),
|
||||||
@@ -677,20 +732,20 @@ function cleanDecisionContext(input = {}) {
|
|||||||
snapshot.risk || snapshot.whatNotToBuildYet || snapshot.notYet || '',
|
snapshot.risk || snapshot.whatNotToBuildYet || snapshot.notYet || '',
|
||||||
].filter(Boolean).join('\n'));
|
].filter(Boolean).join('\n'));
|
||||||
return {
|
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([
|
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),
|
...collectContextList(contextSources, ['constraints', 'constraint', 'boundaries', 'scope'], 8),
|
||||||
...cleanSentenceList(lensContent(constraintsLens), 8, 180),
|
...cleanSentenceList(lensContent(constraintsLens), 8, 180),
|
||||||
...textContextGuardrails.constraints,
|
...textContextGuardrails.constraints,
|
||||||
], 8),
|
], 8),
|
||||||
nonGoals: uniqueList([
|
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),
|
...collectContextList(contextSources, ['nonGoals', 'non_goals', 'nonGoal', 'non_goal', 'avoid', 'notYet', 'not_yet', 'doNotBuild', 'do_not_build'], 8),
|
||||||
...textContextGuardrails.nonGoals,
|
...textContextGuardrails.nonGoals,
|
||||||
], 8),
|
], 8),
|
||||||
assumptions: uniqueList([
|
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),
|
...collectContextList(contextSources, ['assumptions', 'assumption', 'unknowns', 'openQuestions'], 6),
|
||||||
...cleanSentenceList(lensContent(assumptionsLens), 6, 180),
|
...cleanSentenceList(lensContent(assumptionsLens), 6, 180),
|
||||||
], 6),
|
], 6),
|
||||||
@@ -865,16 +920,19 @@ function optionsFromBuildOrderText(text = '', sourceSection = 'concept-map.lense
|
|||||||
}
|
}
|
||||||
|
|
||||||
function optionsFromBody(body = {}) {
|
function optionsFromBody(body = {}) {
|
||||||
const featureSet = objectFrom(body.featureSet || body.feature_set);
|
const envelope = bridgeEnvelopeFrom(body);
|
||||||
const artifact = objectFrom(body.artifact || featureSet.artifact);
|
const featureSet = featureSetFrom(body);
|
||||||
const conceptMap = objectFrom(body.conceptMap || body.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
const artifact = objectFrom(body.artifact || envelope.artifact || featureSet.artifact);
|
||||||
const snapshot = objectFrom(body.snapshot || featureSet.snapshot || artifact.snapshot || conceptMap.snapshot);
|
const conceptMap = objectFrom(body.conceptMap || body.concept_map || envelope.conceptMap || envelope.concept_map || featureSet.conceptMap || featureSet.concept_map || artifact.conceptMap || artifact.concept_map);
|
||||||
const conceptMapLenses = objectFrom(conceptMap.lenses || body.lenses || featureSet.lenses);
|
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 buildOrderLens = objectFrom(conceptMapLenses.channel || conceptMapLenses.buildOrder || conceptMap.buildOrder);
|
||||||
const directCandidateGroup = compactCandidateGroup([
|
const directCandidateGroup = compactCandidateGroup([
|
||||||
{ items: body.features, sourceSection: 'features' },
|
{ items: body.features, sourceSection: 'features' },
|
||||||
|
{ items: envelope.features, sourceSection: 'ranker-input.features' },
|
||||||
{ items: featureSet.features, sourceSection: 'feature-set.features' },
|
{ items: featureSet.features, sourceSection: 'feature-set.features' },
|
||||||
{ items: body.actions, sourceSection: 'actions' },
|
{ items: body.actions, sourceSection: 'actions' },
|
||||||
|
{ items: envelope.actions, sourceSection: 'ranker-input.actions' },
|
||||||
{ items: featureSet.actions, sourceSection: 'feature-set.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: 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' },
|
{ 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.experiments, sourceSection: 'feature-set.experiments', defaultLane: 'validate-next' },
|
||||||
{ items: featureSet.validationTests || featureSet.validation_tests, 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.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([
|
const conceptMapCandidateGroup = compactCandidateGroup([
|
||||||
{ items: conceptMap.nextActions || conceptMap.next_actions || conceptMap.nextSteps || conceptMap.next_steps || conceptMap.recommendedNextSteps || conceptMap.recommended_next_steps, sourceSection: 'concept-map.nextActions' },
|
{ 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,
|
...snapshotCandidateGroup,
|
||||||
...conceptMapCandidateGroup,
|
...conceptMapCandidateGroup,
|
||||||
...buildOrderSectionGroup(body.buildOrder || body.build_order, 'buildOrder'),
|
...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(featureSet.buildOrder || featureSet.build_order, 'feature-set.buildOrder'),
|
||||||
...buildOrderSectionGroup(snapshot.buildOrder || snapshot.build_order, 'snapshot.buildOrder'),
|
...buildOrderSectionGroup(snapshot.buildOrder || snapshot.build_order, 'snapshot.buildOrder'),
|
||||||
...buildOrderSectionGroup(conceptMap.buildOrder || conceptMap.build_order, 'concept-map.buildOrder'),
|
...buildOrderSectionGroup(conceptMap.buildOrder || conceptMap.build_order, 'concept-map.buildOrder'),
|
||||||
@@ -943,8 +1005,8 @@ function optionsFromBody(body = {}) {
|
|||||||
if (Array.isArray(body.options)) {
|
if (Array.isArray(body.options)) {
|
||||||
return normalizeOptionIds(body.options.slice(0, 24).map((item, index) => normalizeFeatureOption(item, index, 'option', 'options')).filter(item => item.title));
|
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 fallbackText = body.optionsText || envelope.optionsText || featureSet.optionsText || conceptMap.optionsText || body.idea || body.ideaText || envelope.idea || envelope.ideaText || '';
|
||||||
const fallbackSourceSection = body.optionsText || featureSet.optionsText || conceptMap.optionsText
|
const fallbackSourceSection = body.optionsText || envelope.optionsText || featureSet.optionsText || conceptMap.optionsText
|
||||||
? 'optionsText'
|
? 'optionsText'
|
||||||
: body.idea
|
: body.idea
|
||||||
? 'idea'
|
? 'idea'
|
||||||
@@ -1402,9 +1464,10 @@ function createHandoffContract({ ranked, provenance, decisionContext }) {
|
|||||||
|
|
||||||
app.post('/api/rank-feedback', (req, res) => {
|
app.post('/api/rank-feedback', (req, res) => {
|
||||||
const body = expandEmbeddedRankPayload(req.body || {});
|
const body = expandEmbeddedRankPayload(req.body || {});
|
||||||
const idea = cleanMultiline(body?.idea || body?.opening_reflection || body?.restated_idea || '', 3000);
|
const envelope = bridgeEnvelopeFrom(body);
|
||||||
const context = cleanContextText(body?.context || '');
|
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 modeId = cleanText(body?.mode || 'progress', 40);
|
const context = cleanContextText(body?.context || envelope.context || '');
|
||||||
|
const modeId = cleanText(body?.mode || envelope.mode || 'progress', 40);
|
||||||
const mode = judgementModes[modeId] || judgementModes.progress;
|
const mode = judgementModes[modeId] || judgementModes.progress;
|
||||||
const provenance = cleanProvenance(body || {});
|
const provenance = cleanProvenance(body || {});
|
||||||
const decisionContext = cleanDecisionContext(body || {});
|
const decisionContext = cleanDecisionContext(body || {});
|
||||||
|
|||||||
Reference in New Issue
Block a user