Accept wrapped Scattermind thread fallbacks
This commit is contained in:
@@ -290,6 +290,35 @@ try {
|
|||||||
assert.match(storedRowPaste.handoff.copyableText, /CM-STORED-77/);
|
assert.match(storedRowPaste.handoff.copyableText, /CM-STORED-77/);
|
||||||
assert.equal(storedRowPaste.ranked.find(item => /Account dashboard/i.test(item.title)).lane.id, 'park');
|
assert.equal(storedRowPaste.ranked.find(item => /Account dashboard/i.test(item.title)).lane.id, 'park');
|
||||||
|
|
||||||
|
const wrappedThreadFallbackResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
mode: 'mvp',
|
||||||
|
rankerInput: {
|
||||||
|
sourceName: 'Scattermind',
|
||||||
|
artifactId: 'CM-WRAPPED-THREADS',
|
||||||
|
snapshotTitle: 'Wrapped thread fallback Concept Map',
|
||||||
|
originalPrompt: 'I clarified an idea, but the bridge envelope only has action threads so far.',
|
||||||
|
context: 'Solo builder. Manual proof first. Avoid saved workspaces and account dashboards before evidence.',
|
||||||
|
threadsToHold: [
|
||||||
|
'Start by manually turning one Concept Map into a source-traced build order preview',
|
||||||
|
'Validate with three tired non-AI-native users before adding product UI',
|
||||||
|
'Hold for later: polished saved workspace after proof',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
assert.equal(wrappedThreadFallbackResponse.status, 200);
|
||||||
|
const wrappedThreadFallback = await wrappedThreadFallbackResponse.json();
|
||||||
|
assert.equal(wrappedThreadFallback.input.provenance.artifactId, 'CM-WRAPPED-THREADS');
|
||||||
|
assert.equal(wrappedThreadFallback.input.optionCount, 3);
|
||||||
|
assert.equal(wrappedThreadFallback.ranked[0].provenance.sourceSection, 'ranker-input.threadsToHold');
|
||||||
|
assert.match(wrappedThreadFallback.brief.quickGlance.topPick, /source-traced build order preview/i);
|
||||||
|
assert.equal(wrappedThreadFallback.ranked.find(item => /saved workspace/i.test(item.title)).lane.id, 'defer');
|
||||||
|
assert.equal(wrappedThreadFallback.handoff.readiness.status, 'ready');
|
||||||
|
assert.deepEqual(wrappedThreadFallback.handoff.warnings, []);
|
||||||
|
|
||||||
const snapshotOnlyResponse = await fetch(`${base}/api/rank-feedback`, {
|
const snapshotOnlyResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|||||||
@@ -1116,6 +1116,10 @@ function optionsFromSnapshotReading(source = {}, sourceSection = 'snapshot') {
|
|||||||
return options.length >= 2 ? options : [];
|
return options.length >= 2 ? options : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function firstArraySource(entries = []) {
|
||||||
|
return entries.find(entry => Array.isArray(entry.items) && entry.items.length > 0) || { items: [], sourceSection: '' };
|
||||||
|
}
|
||||||
|
|
||||||
function optionsFromBody(body = {}) {
|
function optionsFromBody(body = {}) {
|
||||||
const envelope = bridgeEnvelopeFrom(body);
|
const envelope = bridgeEnvelopeFrom(body);
|
||||||
const featureSet = featureSetFrom(body);
|
const featureSet = featureSetFrom(body);
|
||||||
@@ -1221,18 +1225,32 @@ function optionsFromBody(body = {}) {
|
|||||||
);
|
);
|
||||||
const buildOrderOptions = optionsFromBuildOrderText(buildOrderText, 'concept-map.lenses.channel', buildOrderSourceTitle);
|
const buildOrderOptions = optionsFromBuildOrderText(buildOrderText, 'concept-map.lenses.channel', buildOrderSourceTitle);
|
||||||
if (buildOrderOptions.length) return normalizeCandidateGroup([{ items: buildOrderOptions, sourceSection: 'concept-map.lenses.channel' }]);
|
if (buildOrderOptions.length) return normalizeCandidateGroup([{ items: buildOrderOptions, sourceSection: 'concept-map.lenses.channel' }]);
|
||||||
|
const actionThreadSource = firstArraySource([
|
||||||
|
{ items: conceptMap.threads_to_hold || conceptMap.threadsToHold || conceptMap.actionThreads || conceptMap.action_threads, sourceSection: 'concept-map.threadsToHold' },
|
||||||
|
{ items: snapshot.threads_to_hold || snapshot.threadsToHold || snapshot.actionThreads || snapshot.action_threads, sourceSection: 'snapshot.threadsToHold' },
|
||||||
|
{ items: envelope.threads_to_hold || envelope.threadsToHold || envelope.actionThreads || envelope.action_threads, sourceSection: 'ranker-input.threadsToHold' },
|
||||||
|
{ items: featureSet.threads_to_hold || featureSet.threadsToHold || featureSet.actionThreads || featureSet.action_threads, sourceSection: 'feature-set.threadsToHold' },
|
||||||
|
{ items: body.threads_to_hold || body.threadsToHold || body.actionThreads || body.action_threads, sourceSection: 'threadsToHold' },
|
||||||
|
]);
|
||||||
const actionThreadOptions = optionsFromActionThreads(
|
const actionThreadOptions = optionsFromActionThreads(
|
||||||
body.threads_to_hold || body.threadsToHold || body.actionThreads || body.action_threads || conceptMap.threads_to_hold || conceptMap.threadsToHold || conceptMap.actionThreads || conceptMap.action_threads,
|
actionThreadSource.items,
|
||||||
conceptMap.threads_to_hold || conceptMap.threadsToHold || conceptMap.actionThreads || conceptMap.action_threads ? 'concept-map.threadsToHold' : 'threadsToHold',
|
actionThreadSource.sourceSection || 'threadsToHold',
|
||||||
'Thread to hold'
|
'Thread to hold'
|
||||||
);
|
);
|
||||||
if (actionThreadOptions.length >= 2) return normalizeCandidateGroup([{ items: actionThreadOptions, sourceSection: 'concept-map.threadsToHold' }]);
|
if (actionThreadOptions.length >= 2) return normalizeCandidateGroup([{ items: actionThreadOptions, sourceSection: actionThreadSource.sourceSection || 'threadsToHold' }]);
|
||||||
|
const questionSource = firstArraySource([
|
||||||
|
{ items: conceptMap.questions_to_sit_with || conceptMap.questionsToSitWith || conceptMap.openQuestions || conceptMap.open_questions, sourceSection: 'concept-map.questionsToSitWith' },
|
||||||
|
{ items: snapshot.questions_to_sit_with || snapshot.questionsToSitWith || snapshot.openQuestions || snapshot.open_questions, sourceSection: 'snapshot.questionsToSitWith' },
|
||||||
|
{ items: envelope.questions_to_sit_with || envelope.questionsToSitWith || envelope.openQuestions || envelope.open_questions, sourceSection: 'ranker-input.questionsToSitWith' },
|
||||||
|
{ items: featureSet.questions_to_sit_with || featureSet.questionsToSitWith || featureSet.openQuestions || featureSet.open_questions, sourceSection: 'feature-set.questionsToSitWith' },
|
||||||
|
{ items: body.questions_to_sit_with || body.questionsToSitWith || body.openQuestions || body.open_questions, sourceSection: 'questionsToSitWith' },
|
||||||
|
]);
|
||||||
const questionOptions = optionsFromQuestionsToSitWith(
|
const questionOptions = optionsFromQuestionsToSitWith(
|
||||||
body.questions_to_sit_with || body.questionsToSitWith || body.openQuestions || body.open_questions || conceptMap.questions_to_sit_with || conceptMap.questionsToSitWith || conceptMap.openQuestions || conceptMap.open_questions,
|
questionSource.items,
|
||||||
conceptMap.questions_to_sit_with || conceptMap.questionsToSitWith || conceptMap.openQuestions || conceptMap.open_questions ? 'concept-map.questionsToSitWith' : 'questionsToSitWith',
|
questionSource.sourceSection || 'questionsToSitWith',
|
||||||
'Question to sit with'
|
'Question to sit with'
|
||||||
);
|
);
|
||||||
if (questionOptions.length >= 2) return normalizeCandidateGroup([{ items: questionOptions, sourceSection: 'concept-map.questionsToSitWith', defaultLane: 'validate-next' }]);
|
if (questionOptions.length >= 2) return normalizeCandidateGroup([{ items: questionOptions, sourceSection: questionSource.sourceSection || 'questionsToSitWith', defaultLane: 'validate-next' }]);
|
||||||
const nestedSnapshotReadingOptions = optionsFromSnapshotReading(snapshot, 'snapshot');
|
const nestedSnapshotReadingOptions = optionsFromSnapshotReading(snapshot, 'snapshot');
|
||||||
const snapshotReadingOptions = nestedSnapshotReadingOptions.length
|
const snapshotReadingOptions = nestedSnapshotReadingOptions.length
|
||||||
? nestedSnapshotReadingOptions
|
? nestedSnapshotReadingOptions
|
||||||
|
|||||||
Reference in New Issue
Block a user