Accept softer Scattermind continuation aliases
This commit is contained in:
@@ -51,7 +51,7 @@ Candidate items may include optional 1–10 `rankerHints` (`value`, `effort`, `c
|
||||
|
||||
Candidate trace note: candidate-level `sourceItemId` / `traceId`, `sourceTitle` / `lensTitle`, and `sourceExcerpt` / `sourceQuote` are preserved in ranked items, `buildOrderDetails`, and `handoff.itemTrace`. Lens-only Build Order text is also split into deterministic `concept-map.lenses.channel#N` source IDs with the original labelled sentence carried as `sourceQuote`, so pasted paid Concept Maps remain traceable even without explicit candidate objects. String items in laned Build Order arrays now also receive deterministic section-local source IDs such as `concept-map.buildOrder.validateNext#1` and carry the original string as `sourceQuote`, so simple Scattermind exports stay addressable downstream instead of becoming anonymous `feature-1` rows. Ranker also accepts the current Scattermind storage-row shape with `referenceCode`, `ideaText`, `context`, and string-valued `fullReadingJson` / `full_reading_json`; it expands the saved paid Concept Map before ranking so operators do not have to hand-copy lenses out of Appwrite rows. If the row only has free Snapshot data (`glimpseJson` / `glimpse_json` / `snapshotJson`), Ranker expands that Snapshot into a minimal continuation order: one manual proof plus the first evidence question, with the Snapshot reference code/title preserved for provenance. The public paste form mirrors this: a prose-wrapped/fenced Appwrite row paste stays intact for the API instead of unwrapping the stringified reading into nonsense fields. The decision `brief.quickGlance.sourceTrace` now repeats the winning item's source section/id/title/quote, and both `brief.source.originalPromptExcerpt` / `handoff.source.originalPromptExcerpt` or, when the original prompt is unavailable, `sourceSummaryExcerpt` carry the source context so a downstream Scattermind handoff can show why the build order exists without digging through `input.provenance`. Scattermind should use these when a next move came from a specific Concept Map lens sentence, so Ranker can defend not just what wins but where the judgement came from.
|
||||
|
||||
Soft Scattermind labels are accepted at the bridge boundary so Scattermind does not need to use harsh verdict copy in its own product surface. Lens text can say `Continue first`, `Make tangible`, `Try next`, `Evidence next`, `Hold for later`, or `Set aside`; Build Order objects and direct bridge/envelope sections can use matching camel/snake-case keys such as `continueFirst`, `evidenceNext`, `holdForLater`, and `setAside`. Ranker maps those to `doFirst / validateNext / defer / park` while preserving the softer original label in `sourceQuote` or candidate source trace.
|
||||
Soft Scattermind labels are accepted at the bridge boundary so Scattermind does not need to use harsh verdict copy in its own product surface. Lens text can say `Continue first`, `Make tangible`, `Try next`, `Evidence next`, `Hold for later`, or `Set aside`; Build Order objects and direct bridge/envelope sections can use matching camel/snake-case keys such as `continueFirst`, `evidenceNext`, `holdForLater`, and `setAside`. Ranker maps those to `doFirst / validateNext / defer / park` while preserving the softer original label in `sourceQuote` or candidate source trace. Ranker also accepts softer continuation envelopes named `rankerBridge`, `continuation`, or `continuationPlan`, candidate arrays named `possibleNextMoves`, `suggestedNextMoves`, `recommendations`, or `opportunities`, and laned `buildOrderPreview` / `build_order_preview` objects so Scattermind can pass a paid Concept Map preview without renaming it into software-feature language.
|
||||
|
||||
Lane safety note: explicit Scattermind `defer` / `park` hints are hard rails, not mild suggestions. Source `nonGoals` / `avoid` guardrails are also hard enough to keep conflicting candidates out of Do first / Validate next even when their local scoring hints look attractive; soft guardrail language such as “this is not a dashboard” or “keep auth/billing/workspaces out until proof” is promoted into non-goals, not merely background context. The result will mark the lane source as `source-non-goal` so the handoff can explain that the candidate needs guardrail resolution before active work. Handoff `source.requiresSourceTrace` is true only when a real source artifact/title is present; plain idea-only ranking still warns about a missing artifact ID when it carries prompt provenance, but it does not spam source-section/evidence warnings meant for Scattermind artifacts. Handoff `readiness` now gives downstream bridge consumers a deterministic gate: `ready`, `usable-with-warnings`, `needs-source-context`, or `blocked`, with blockers and next checks for missing evidence, source trace, duplicate IDs, or active source-non-goal conflicts. Handoff `activeSlice` (`ranker-active-slice-v1`) is the compact machine-readable continuation unit: one active item, its proof/evidence/success/kill signals, source anchor, held-back items, readiness status, and the rule that only this slice is build-ready. For tired first-screen users, `brief.decisionReceipt` repeats the one active move, first proof step, evidence question, held-back items, source anchor, and the handoff rule that only Do first is active; use it as the compact result strip before showing the full lane board. For low-friction handoff, `/api/rank-feedback` also detects a raw Scattermind/Concept Map JSON object pasted into `idea`, `ideaText`, `optionsText`, or wrapper keys such as `payload`; it expands that object before ranking and reports `input.embeddedPayloadSource` so the public form can accept copy/paste exports without a custom import screen. Exact free Snapshot JSON (`working_name`, `restated_idea`, `lenses.shape`, `questions_to_sit_with`, `reference_code`) is rankable too: Ranker derives a manual proof active slice plus evidence questions, carrying the Snapshot reference code/title into provenance so a Snapshot-only handoff does not need a paid Concept Map before it can produce a useful build order. If a Concept Map only carries `questions_to_sit_with` / `questionsToSitWith` / `openQuestions` and no explicit build-order lanes or action threads, Ranker converts those questions into Validate-next evidence actions with source trace instead of pretending they are software features.
|
||||
|
||||
|
||||
+5
-3
@@ -63,9 +63,9 @@ function parsePastedJsonPayload(value) {
|
||||
const looksLikeBridgePayload = parsed && typeof parsed === 'object' && !Array.isArray(parsed) && (
|
||||
parsed.schema || parsed.featureSet || parsed.feature_set || parsed.candidateSet || parsed.candidate_set || parsed.candidateFeatureSet || parsed.candidate_feature_set || parsed.rankReadyFeatureSet || parsed.rank_ready_feature_set
|
||||
|| parsed.snapshot || parsed.conceptMap || parsed.concept_map || parsed.buildOrder || parsed.build_order || parsed.lenses
|
||||
|| parsed.payload || parsed.rankPayload || parsed.scattermindPayload || parsed.conceptMapJson || parsed.rankerInput || parsed.ranker_input || parsed.rankerHandoff || parsed.ranker_handoff || parsed.rankReady || parsed.rank_ready || parsed.bridge || parsed.bridgePayload || parsed.bridge_payload
|
||||
|| parsed.payload || parsed.rankPayload || parsed.scattermindPayload || parsed.conceptMapJson || parsed.rankerInput || parsed.ranker_input || parsed.rankerHandoff || parsed.ranker_handoff || parsed.rankerBridge || parsed.ranker_bridge || parsed.rankReady || parsed.rank_ready || parsed.bridge || parsed.bridgePayload || parsed.bridge_payload || parsed.continuation || parsed.continuationPlan || parsed.continuation_plan
|
||||
|| parsed.concept_map_json || parsed.fullReadingJson || parsed.full_reading_json || parsed.fullReading || parsed.full_reading
|
||||
|| parsed.glimpseJson || parsed.glimpse_json || parsed.snapshotJson || parsed.snapshot_json
|
||||
|| parsed.glimpseJson || parsed.glimpse_json || parsed.snapshotJson || parsed.snapshot_json || parsed.buildOrderPreview || parsed.build_order_preview
|
||||
|| parsed.reference_code || parsed.referenceCode || parsed.artifactId || parsed.sourceArtifactId || parsed.source_artifact_id
|
||||
|| parsed.ideaText || parsed.idea_text || parsed.originalPrompt || parsed.original_prompt || parsed.sourceSummary || parsed.source_summary || parsed.opening_reflection || parsed.restated_idea
|
||||
|| Array.isArray(parsed.features) || Array.isArray(parsed.actions) || Array.isArray(parsed.candidates)
|
||||
@@ -73,6 +73,8 @@ function parsePastedJsonPayload(value) {
|
||||
|| Array.isArray(parsed.rankReadyActions) || Array.isArray(parsed.rank_ready_actions)
|
||||
|| Array.isArray(parsed.recommendedActions) || Array.isArray(parsed.recommended_actions) || Array.isArray(parsed.suggestedActions) || Array.isArray(parsed.suggested_actions)
|
||||
|| Array.isArray(parsed.nextActions) || Array.isArray(parsed.next_actions) || Array.isArray(parsed.nextMoves) || Array.isArray(parsed.next_moves)
|
||||
|| Array.isArray(parsed.possibleNextMoves) || Array.isArray(parsed.possible_next_moves) || Array.isArray(parsed.suggestedNextMoves) || Array.isArray(parsed.suggested_next_moves)
|
||||
|| Array.isArray(parsed.recommendations) || Array.isArray(parsed.opportunities)
|
||||
|| Array.isArray(parsed.doFirst) || Array.isArray(parsed.do_first) || Array.isArray(parsed.continueFirst) || Array.isArray(parsed.continue_first) || Array.isArray(parsed.makeTangible) || Array.isArray(parsed.make_tangible)
|
||||
|| Array.isArray(parsed.validateNext) || Array.isArray(parsed.validate_next) || Array.isArray(parsed.evidenceNext) || Array.isArray(parsed.evidence_next) || Array.isArray(parsed.tryNext) || Array.isArray(parsed.try_next)
|
||||
|| Array.isArray(parsed.deferred) || Array.isArray(parsed.holdForLater) || Array.isArray(parsed.hold_for_later)
|
||||
@@ -121,7 +123,7 @@ function payloadFromForm(formPayload) {
|
||||
const optionsJson = parsePastedJsonPayload(formPayload.optionsText);
|
||||
const embedded = ideaJson || optionsJson;
|
||||
if (!embedded) return formPayload;
|
||||
const unwrapCandidate = embedded.payload || embedded.rankPayload || embedded.scattermindPayload || embedded;
|
||||
const unwrapCandidate = embedded.payload || embedded.rankPayload || embedded.scattermindPayload || embedded.rankerBridge || embedded.ranker_bridge || embedded.continuation || embedded.continuationPlan || embedded.continuation_plan || embedded;
|
||||
const unwrapped = unwrapCandidate && typeof unwrapCandidate === 'object' && !Array.isArray(unwrapCandidate) ? unwrapCandidate : embedded;
|
||||
const merged = { ...unwrapped };
|
||||
if (!merged.mode && formPayload.mode) merged.mode = formPayload.mode;
|
||||
|
||||
@@ -1573,7 +1573,67 @@ try {
|
||||
assert.equal(rankReadyActionsEnvelope.handoff.readiness.status, 'ready');
|
||||
assert.deepEqual(rankReadyActionsEnvelope.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, directEnvelopeSectionsTop: directEnvelopeSections.ranked[0].id, softDirectLaneAliasesTop: softDirectLaneAliases.ranked[0].id, threadsFallbackTop: threadsFallback.ranked[0].id, questionsFallbackTop: questionsFallback.ranked[0].id, freeSnapshotTop: freeSnapshot.ranked[0].id, storedScattermindRowTop: storedScattermindRow.ranked[0].id, candidateActionsAliasTop: candidateActionsAlias.ranked[0].id, rankReadyActionsEnvelopeTop: rankReadyActionsEnvelope.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 continuationEnvelopeResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
sourceName: 'Scattermind',
|
||||
continuationPlan: {
|
||||
reference_code: 'SM-CONTINUATION-ALIASES-1',
|
||||
working_name: 'Continuation alias bridge',
|
||||
ideaText: 'Scattermind exported softer continuation language rather than a formal feature set.',
|
||||
context: 'Solo builder. Keep this out of workspace/dashboard/billing land until one manual proof works.',
|
||||
possible_next_moves: [
|
||||
{ id: 'possible-manual-proof', action: 'Possible manual proof card', why: 'Turn the Concept Map into one active proof card with source trace.', evidence_needed: 'Can one tired user say what to do first?', suggested_lane: 'do-first', source_item_id: 'possible-move-1', source_title: 'Possible next moves', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } },
|
||||
{ id: 'possible-copy-brief', action: 'Possible copyable handoff', why: 'Let the user carry the defended order into notes.', evidence_needed: 'Does the copied handoff preserve the active move?', suggested_lane: 'validate-next', source_item_id: 'possible-move-2', source_title: 'Possible next moves' },
|
||||
{ id: 'possible-dashboard', action: 'Possible saved dashboard', why: 'Saved workspace dashboard with accounts, billing, and collaboration.', suggested_lane: 'park', source_item_id: 'possible-move-3', source_title: 'Possible next moves' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
});
|
||||
assert.equal(continuationEnvelopeResponse.status, 200);
|
||||
const continuationEnvelope = await continuationEnvelopeResponse.json();
|
||||
assert.equal(continuationEnvelope.input.provenance.artifactId, 'SM-CONTINUATION-ALIASES-1');
|
||||
assert.equal(continuationEnvelope.input.provenance.snapshotTitle, 'Continuation alias bridge');
|
||||
assert.equal(continuationEnvelope.input.optionCount, 3);
|
||||
assert.equal(continuationEnvelope.ranked[0].id, 'possible-manual-proof');
|
||||
assert.equal(continuationEnvelope.ranked[0].provenance.sourceSection, 'ranker-input.possibleNextMoves');
|
||||
assert.equal(continuationEnvelope.ranked[0].provenance.sourceId, 'possible-move-1');
|
||||
assert.equal(continuationEnvelope.ranked.find(item => item.id === 'possible-dashboard').lane.id, 'park');
|
||||
assert.equal(continuationEnvelope.handoff.readiness.status, 'ready');
|
||||
assert.deepEqual(continuationEnvelope.handoff.warnings, []);
|
||||
|
||||
const buildOrderPreviewResponse = await fetch(`${base}/api/rank-feedback`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
sourceName: 'Scattermind',
|
||||
artifactId: 'SM-BUILD-ORDER-PREVIEW-1',
|
||||
snapshotTitle: 'Build Order Preview alias',
|
||||
originalPrompt: 'Use a paid Concept Map build order preview without renaming the object.',
|
||||
context: 'Manual proof first. Avoid saved workspace dashboards.',
|
||||
conceptMap: {
|
||||
build_order_preview: {
|
||||
continue_first: [{ id: 'preview-active-slice', action: 'Preview active slice', evidence_needed: 'Can the preview name one first move?', source_item_id: 'preview-1', source_title: 'Build Order Preview', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }],
|
||||
evidence_next: [{ id: 'preview-evidence-test', action: 'Preview evidence test', evidence_needed: 'Does the user know what signal to collect?', source_item_id: 'preview-2', source_title: 'Build Order Preview' }],
|
||||
hold_for_later: [{ id: 'preview-polish', action: 'Preview visual polish', evidence_needed: 'Does polish matter after the proof?', source_item_id: 'preview-3', source_title: 'Build Order Preview' }],
|
||||
set_aside: [{ id: 'preview-workspace', action: 'Preview workspace dashboard', evidence_needed: 'Not before proof.', source_item_id: 'preview-4', source_title: 'Build Order Preview' }],
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
assert.equal(buildOrderPreviewResponse.status, 200);
|
||||
const buildOrderPreview = await buildOrderPreviewResponse.json();
|
||||
assert.equal(buildOrderPreview.input.optionCount, 4);
|
||||
assert.equal(buildOrderPreview.ranked[0].id, 'preview-active-slice');
|
||||
assert.equal(buildOrderPreview.ranked[0].provenance.sourceSection, 'concept-map.buildOrderPreview.doFirst');
|
||||
assert.equal(buildOrderPreview.ranked.find(item => item.id === 'preview-evidence-test').lane.id, 'test');
|
||||
assert.equal(buildOrderPreview.ranked.find(item => item.id === 'preview-polish').lane.id, 'defer');
|
||||
assert.equal(buildOrderPreview.ranked.find(item => item.id === 'preview-workspace').lane.id, 'park');
|
||||
assert.equal(buildOrderPreview.handoff.readiness.status, 'ready');
|
||||
assert.deepEqual(buildOrderPreview.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, directEnvelopeSectionsTop: directEnvelopeSections.ranked[0].id, softDirectLaneAliasesTop: softDirectLaneAliases.ranked[0].id, threadsFallbackTop: threadsFallback.ranked[0].id, questionsFallbackTop: questionsFallback.ranked[0].id, freeSnapshotTop: freeSnapshot.ranked[0].id, storedScattermindRowTop: storedScattermindRow.ranked[0].id, candidateActionsAliasTop: candidateActionsAlias.ranked[0].id, rankReadyActionsEnvelopeTop: rankReadyActionsEnvelope.ranked[0].id, continuationEnvelopeTop: continuationEnvelope.ranked[0].id, buildOrderPreviewTop: buildOrderPreview.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');
|
||||
}
|
||||
|
||||
@@ -495,11 +495,16 @@ function bridgeEnvelopeFrom(input = {}) {
|
||||
|| body.ranker_input
|
||||
|| body.rankerHandoff
|
||||
|| body.ranker_handoff
|
||||
|| body.rankerBridge
|
||||
|| body.ranker_bridge
|
||||
|| body.rankReady
|
||||
|| body.rank_ready
|
||||
|| body.bridge
|
||||
|| body.bridgePayload
|
||||
|| body.bridge_payload
|
||||
|| body.continuation
|
||||
|| body.continuationPlan
|
||||
|| body.continuation_plan
|
||||
);
|
||||
}
|
||||
|
||||
@@ -515,6 +520,8 @@ function featureSetFrom(input = {}) {
|
||||
|| body.candidate_feature_set
|
||||
|| body.rankReadyFeatureSet
|
||||
|| body.rank_ready_feature_set
|
||||
|| body.buildOrderPreview
|
||||
|| body.build_order_preview
|
||||
|| envelope.featureSet
|
||||
|| envelope.feature_set
|
||||
|| envelope.candidateSet
|
||||
@@ -523,6 +530,8 @@ function featureSetFrom(input = {}) {
|
||||
|| envelope.candidate_feature_set
|
||||
|| envelope.rankReadyFeatureSet
|
||||
|| envelope.rank_ready_feature_set
|
||||
|| envelope.buildOrderPreview
|
||||
|| envelope.build_order_preview
|
||||
);
|
||||
}
|
||||
|
||||
@@ -539,11 +548,16 @@ function looksLikeRankPayload(value = {}) {
|
||||
|| value.ranker_input
|
||||
|| value.rankerHandoff
|
||||
|| value.ranker_handoff
|
||||
|| value.rankerBridge
|
||||
|| value.ranker_bridge
|
||||
|| value.rankReady
|
||||
|| value.rank_ready
|
||||
|| value.bridge
|
||||
|| value.bridgePayload
|
||||
|| value.bridge_payload
|
||||
|| value.continuation
|
||||
|| value.continuationPlan
|
||||
|| value.continuation_plan
|
||||
|| value.snapshot
|
||||
|| value.conceptMap
|
||||
|| value.concept_map
|
||||
@@ -571,6 +585,8 @@ function looksLikeRankPayload(value = {}) {
|
||||
|| value.full_reading
|
||||
|| value.conceptMapJson
|
||||
|| value.concept_map_json
|
||||
|| value.buildOrderPreview
|
||||
|| value.build_order_preview
|
||||
|| value.opening_reflection
|
||||
|| value.restated_idea
|
||||
|| value.ideaText
|
||||
@@ -585,6 +601,12 @@ function looksLikeRankPayload(value = {}) {
|
||||
|| Array.isArray(value.next_actions)
|
||||
|| Array.isArray(value.nextMoves)
|
||||
|| Array.isArray(value.next_moves)
|
||||
|| Array.isArray(value.possibleNextMoves)
|
||||
|| Array.isArray(value.possible_next_moves)
|
||||
|| Array.isArray(value.suggestedNextMoves)
|
||||
|| Array.isArray(value.suggested_next_moves)
|
||||
|| Array.isArray(value.recommendations)
|
||||
|| Array.isArray(value.opportunities)
|
||||
|| Array.isArray(value.candidates)
|
||||
|| Array.isArray(value.candidateActions)
|
||||
|| Array.isArray(value.candidate_actions)
|
||||
@@ -1158,6 +1180,9 @@ function optionsFromBody(body = {}) {
|
||||
{ items: body.nextMoves || body.next_moves, sourceSection: 'nextMoves' },
|
||||
{ items: envelope.nextMoves || envelope.next_moves, sourceSection: 'ranker-input.nextMoves' },
|
||||
{ items: featureSet.nextMoves || featureSet.next_moves, sourceSection: 'feature-set.nextMoves' },
|
||||
{ items: body.possibleNextMoves || body.possible_next_moves || body.suggestedNextMoves || body.suggested_next_moves || body.recommendations || body.opportunities, sourceSection: 'possibleNextMoves' },
|
||||
{ items: envelope.possibleNextMoves || envelope.possible_next_moves || envelope.suggestedNextMoves || envelope.suggested_next_moves || envelope.recommendations || envelope.opportunities, sourceSection: 'ranker-input.possibleNextMoves' },
|
||||
{ items: featureSet.possibleNextMoves || featureSet.possible_next_moves || featureSet.suggestedNextMoves || featureSet.suggested_next_moves || featureSet.recommendations || featureSet.opportunities, sourceSection: 'feature-set.possibleNextMoves' },
|
||||
{ items: body.candidates, sourceSection: 'candidates' },
|
||||
{ items: envelope.candidates, sourceSection: 'ranker-input.candidates' },
|
||||
{ items: featureSet.candidates, sourceSection: 'feature-set.candidates' },
|
||||
@@ -1189,6 +1214,7 @@ function optionsFromBody(body = {}) {
|
||||
const conceptMapCandidateGroup = compactCandidateGroup([
|
||||
{ items: conceptMap.nextActions || conceptMap.next_actions || conceptMap.nextSteps || conceptMap.next_steps || conceptMap.recommendedNextSteps || conceptMap.recommended_next_steps || conceptMap.recommendedActions || conceptMap.recommended_actions || conceptMap.suggestedActions || conceptMap.suggested_actions, sourceSection: 'concept-map.nextActions' },
|
||||
{ items: conceptMap.nextMoves || conceptMap.next_moves, sourceSection: 'concept-map.nextMoves' },
|
||||
{ items: conceptMap.possibleNextMoves || conceptMap.possible_next_moves || conceptMap.suggestedNextMoves || conceptMap.suggested_next_moves || conceptMap.recommendations || conceptMap.opportunities, sourceSection: 'concept-map.possibleNextMoves' },
|
||||
{ items: conceptMap.features, sourceSection: 'concept-map.features' },
|
||||
{ items: conceptMap.candidates, sourceSection: 'concept-map.candidates' },
|
||||
{ items: conceptMap.candidateActions || conceptMap.candidate_actions || conceptMap.candidateMoves || conceptMap.candidate_moves || conceptMap.rankReadyActions || conceptMap.rank_ready_actions, sourceSection: 'concept-map.candidateActions' },
|
||||
@@ -1203,6 +1229,7 @@ function optionsFromBody(body = {}) {
|
||||
const snapshotCandidateGroup = compactCandidateGroup([
|
||||
{ items: snapshot.nextActions || snapshot.next_actions || snapshot.nextSteps || snapshot.next_steps || snapshot.recommendedNextSteps || snapshot.recommended_next_steps || snapshot.recommendedActions || snapshot.recommended_actions || snapshot.suggestedActions || snapshot.suggested_actions, sourceSection: 'snapshot.nextActions' },
|
||||
{ items: snapshot.nextMoves || snapshot.next_moves, sourceSection: 'snapshot.nextMoves' },
|
||||
{ items: snapshot.possibleNextMoves || snapshot.possible_next_moves || snapshot.suggestedNextMoves || snapshot.suggested_next_moves || snapshot.recommendations || snapshot.opportunities, sourceSection: 'snapshot.possibleNextMoves' },
|
||||
{ items: snapshot.actions, sourceSection: 'snapshot.actions' },
|
||||
{ items: snapshot.features, sourceSection: 'snapshot.features' },
|
||||
{ items: snapshot.candidates, sourceSection: 'snapshot.candidates' },
|
||||
@@ -1220,10 +1247,15 @@ function optionsFromBody(body = {}) {
|
||||
...snapshotCandidateGroup,
|
||||
...conceptMapCandidateGroup,
|
||||
...buildOrderSectionGroup(body.buildOrder || body.build_order, 'buildOrder'),
|
||||
...buildOrderSectionGroup(body.buildOrderPreview || body.build_order_preview, 'buildOrderPreview'),
|
||||
...buildOrderSectionGroup(envelope.buildOrder || envelope.build_order, 'ranker-input.buildOrder'),
|
||||
...buildOrderSectionGroup(envelope.buildOrderPreview || envelope.build_order_preview, 'ranker-input.buildOrderPreview'),
|
||||
...buildOrderSectionGroup(featureSet.buildOrder || featureSet.build_order, 'feature-set.buildOrder'),
|
||||
...buildOrderSectionGroup(featureSet.buildOrderPreview || featureSet.build_order_preview, 'feature-set.buildOrderPreview'),
|
||||
...buildOrderSectionGroup(snapshot.buildOrder || snapshot.build_order, 'snapshot.buildOrder'),
|
||||
...buildOrderSectionGroup(snapshot.buildOrderPreview || snapshot.build_order_preview, 'snapshot.buildOrderPreview'),
|
||||
...buildOrderSectionGroup(conceptMap.buildOrder || conceptMap.build_order, 'concept-map.buildOrder'),
|
||||
...buildOrderSectionGroup(conceptMap.buildOrderPreview || conceptMap.build_order_preview, 'concept-map.buildOrderPreview'),
|
||||
];
|
||||
if (groupedCandidates.length) return normalizeCandidateGroup(groupedCandidates);
|
||||
const buildOrderText = lensContent(conceptMapLenses.channel)
|
||||
|
||||
Reference in New Issue
Block a user