import assert from 'node:assert/strict'; import { spawn } from 'node:child_process'; const port = 43045 + Math.floor(Math.random() * 1000); const base = `http://127.0.0.1:${port}`; const server = spawn(process.execPath, ['server.js'], { cwd: new URL('..', import.meta.url), env: { ...process.env, PORT: String(port), APPWRITE_ENDPOINT: '', APPWRITE_PROJECT_ID: '', APPWRITE_API_KEY: '' }, stdio: ['ignore', 'pipe', 'pipe'], }); let output = ''; server.stdout.on('data', chunk => { output += chunk; }); server.stderr.on('data', chunk => { output += chunk; }); async function waitForServer() { const deadline = Date.now() + 6000; while (Date.now() < deadline) { try { const response = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ optionsText: '- one\n- two' }), }); if (response.status < 500) return; } catch { await new Promise(resolve => setTimeout(resolve, 120)); } } throw new Error(`server did not become ready:\n${output}`); } try { await waitForServer(); const response = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', artifactId: 'snapshot_123', snapshotTitle: 'Tiny shop idea clarity pass', originalPrompt: 'I have a tiny shop idea and do not know what to build first.', idea: 'Scattermind clarified a small product idea. Ranker must defend the next build order, not create a dashboard.', context: 'Solo builder. Need a rank-ready build order after Snapshot / Concept Map. Avoid accounts, workspaces, and team voting.', mode: 'mvp', featureSet: { features: [ { id: 'bridge-contract', title: 'Snapshot to Ranker feature-set contract', description: 'Convert Concept Map next moves into a rank-ready feature set with provenance.', userValue: 'Preserves the user prompt and source artifact so build order is defensible.', evidenceNeeded: 'Can one generated Concept Map create 3-7 sane next moves with source sections?', proofSteps: ['Run one fixture through /api/rank-feedback'], recommendedLane: 'do-first', sourceSection: 'concept-map.nextMoves' }, { id: 'build-order-preview', title: 'Build order preview', description: 'Show do first, validate next, defer, and park with reasons.', userValue: 'A tired builder sees the next move without opening a dashboard.', evidenceNeeded: 'Can 3 non-AI-native users understand the first recommended action?', proofSteps: ['Show a static result screen to 3 people'], recommendedLane: 'validate-next', sourceSection: 'concept-map.nextMoves' }, { id: 'workspace', title: 'Accounts and saved workspaces', description: 'Full dashboard with auth, workspace collaboration, team voting, and sync.', dependencies: ['auth', 'teams', 'saved projects', 'sync'], risk: 'Turns the bridge into generic dashboard swamp before the first proof.', sourceSection: 'concept-map.deferred' }, { id: 'billing', title: 'Subscription billing layer', description: 'Pricing, checkout, invoices, account plans, and admin controls.', dependencies: ['account model', 'checkout', 'fulfillment'], risk: 'Payment machinery before the continuation value is proven.', sourceSection: 'concept-map.deferred' }, { id: 'export', title: 'Exportable decision brief', description: 'Simple brief for sharing the defended build order.', evidenceNeeded: 'Does a plain brief help a user act within 48 hours?', recommendedLane: 'validate-next', sourceSection: 'concept-map.nextMoves' }, { id: 'parked-bridge-dashboard', title: 'Saved Snapshot dashboard with provenance', description: 'Looks bridge-adjacent, but Scattermind already marked it as not-now because it needs auth, saved workspaces, and collaboration first.', recommendedLane: 'park', sourceSection: 'concept-map.parkingLot' }, ], }, }), }); assert.equal(response.status, 200); const data = await response.json(); assert.equal(data.ok, true); assert.equal(data.input.provenance.artifactId, 'snapshot_123'); assert.equal(data.input.provenance.source, 'Scattermind'); assert.match(data.input.provenance.originalPrompt, /tiny shop idea/); assert.equal(data.ranked.length, 6); assert.deepEqual(Object.keys(data.buildOrder), ['doFirst', 'validateNext', 'defer', 'park']); assert.equal(data.ranked[0].id, data.buildOrder.doFirst[0]); assert.equal(data.buildOrderDetails.doFirst[0].id, data.buildOrder.doFirst[0]); assert.equal(data.buildOrderDetails.doFirst[0].sourceSection, 'concept-map.nextMoves'); assert.equal(data.buildOrderDetails.doFirst[0].laneSource, 'ranked'); assert.equal(typeof data.buildOrderDetails.doFirst[0].score, 'number'); assert.equal(typeof data.buildOrderDetails.doFirst[0].confidence, 'number'); assert.match(data.buildOrderDetails.doFirst[0].nextStep, /manual proof/i); assert.notEqual(data.ranked[0].id, 'workspace', 'dashboard swamp must not win the bridge fixture'); assert.ok(['defer', 'park'].includes(data.ranked.find(item => item.id === 'workspace').lane.id)); assert.ok(['defer', 'park'].includes(data.ranked.find(item => item.id === 'billing').lane.id)); assert.equal(data.ranked.find(item => item.id === 'parked-bridge-dashboard').lane.id, 'park', 'explicit Scattermind park hints must stay out of the active proof slice'); assert.equal(data.ranked.find(item => item.id === 'parked-bridge-dashboard').lane.source, 'hint'); assert.equal(data.ranked.find(item => item.id === 'bridge-contract').provenance.sourceSection, 'concept-map.nextMoves'); assert.match(data.ranked.find(item => item.id === 'bridge-contract').factors.evidenceNeeded, /Concept Map/); assert.ok(data.ranked.find(item => item.id === 'bridge-contract').factors.metricHints.value === undefined); assert.equal(data.brief.source.artifactId, 'snapshot_123'); assert.equal(data.brief.decisionReceipt.activeMove, data.brief.quickGlance.topPick); assert.match(data.brief.decisionReceipt.firstProofStep, /manual proof/i); assert.deepEqual(data.brief.decisionReceipt.doNotStartYet.slice(0, 2), ['Subscription billing layer', 'Accounts and saved workspaces']); assert.match(data.brief.decisionReceipt.sourceAnchor, /concept-map\.nextMoves/); assert.match(data.brief.decisionReceipt.handoffRule, /Only the Do first item is active/); assert.match(data.brief.source.originalPromptExcerpt, /tiny shop idea/); assert.match(data.brief.summary, /Source: Tiny shop idea clarity pass · snapshot_123/); assert.equal(data.handoff.schema, 'rank-feedback-result-v1'); assert.equal(data.handoff.source.artifactId, 'snapshot_123'); assert.match(data.handoff.source.originalPromptExcerpt, /tiny shop idea/); assert.equal(data.handoff.source.hasOriginalPrompt, true); assert.equal(data.handoff.source.requiresSourceTrace, true); assert.equal(data.handoff.itemTrace.length, data.ranked.length); assert.equal(data.handoff.itemTrace.find(item => item.id === 'bridge-contract').sourceSection, 'concept-map.nextMoves'); assert.ok(data.input.decisionContext.constraints.includes('Solo builder')); assert.ok(data.input.decisionContext.nonGoals.includes('Avoid accounts, workspaces, and team voting')); assert.deepEqual(data.handoff.decisionContext.nonGoals, ['Avoid accounts, workspaces, and team voting']); assert.ok(data.ranked.find(item => item.id === 'workspace').metrics.nonGoalConflicts.length >= 1, 'flat text avoid guardrails should protect against workspace candidates'); assert.deepEqual(data.handoff.warnings, []); assert.ok(data.brief.next48Hours.some(item => /Open the source artifact \(snapshot_123\)/i.test(item))); assert.ok(data.brief.next48Hours.some(item => /Evidence to collect/i.test(item))); assert.match(data.brief.summary, /nearest follow-up|strongest signal/i); assert.ok(data.brief.whatWouldChangeRanking.some(item => /evidence fails|re-run the order/i.test(item))); assert.ok(Array.isArray(data.brief.assumptions)); assert.equal(data.handoff.readiness.status, 'ready'); assert.equal(data.handoff.activeSlice.schema, 'ranker-active-slice-v1'); assert.equal(data.handoff.activeSlice.item.id, data.buildOrder.doFirst[0]); assert.match(data.handoff.activeSlice.proof.nextStep, /manual proof/i); assert.equal(data.handoff.activeSlice.source.artifactId, 'snapshot_123'); assert.equal(data.handoff.activeSlice.source.sourceSection, 'concept-map.nextMoves'); assert.ok(data.handoff.activeSlice.notNow.some(item => item.id === 'export')); assert.match(data.handoff.activeSlice.rule, /Only this active slice is build-ready/); assert.match(data.handoff.copyableText, /## Active slice/); assert.match(data.handoff.copyableText, /- Do not start yet:/); assert.equal(data.handoff.readiness.sourceComplete, true); assert.ok(data.handoff.readiness.nextChecks.some(item => /Do first item/i.test(item))); assert.match(data.handoff.copyableText, /# Ranker build-order handoff/); assert.match(data.handoff.copyableText, /## Do first\n\n- Snapshot to Ranker feature-set contract/); assert.match(data.handoff.copyableText, /Source: concept-map\.nextMoves/); assert.match(data.handoff.copyableText, /Rule: only the Do first item is active/); const messyIdeaOnlyResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idea: 'I’m building a tool that helps freelancers package their services and decide what to sell first. Maybe offer critique, pricing calculator, proposal generator, landing page copywriter, client persona mapper, and some kind of dashboard later? I only have a week and want the fastest useful proof.', context: 'Solo builder. Manual proof first. Avoid dashboards, accounts, and saved workspaces before evidence.', mode: 'validation', }), }); assert.equal(messyIdeaOnlyResponse.status, 200); const messyIdeaOnly = await messyIdeaOnlyResponse.json(); assert.equal(messyIdeaOnly.input.optionCount, 6, 'idea-only messy dumps should be split into rank-ready candidates'); assert.ok(messyIdeaOnly.ranked.some(item => /Offer critique/i.test(item.title))); assert.ok(messyIdeaOnly.ranked.some(item => /Pricing calculator/i.test(item.title))); assert.equal(messyIdeaOnly.ranked.find(item => /dashboard/i.test(item.title)).lane.source, 'source-non-goal'); assert.ok(!/dashboard/i.test(messyIdeaOnly.ranked[0].title), 'dashboard-flavored candidate must not win tired-user first pass'); assert.equal(messyIdeaOnly.handoff.source.requiresSourceTrace, false); assert.ok(!messyIdeaOnly.handoff.warnings.some(item => /missing source section|missing original prompt/.test(item))); assert.ok(messyIdeaOnly.handoff.warnings.includes('missing source artifact id')); assert.equal(messyIdeaOnly.handoff.readiness.status, 'usable-with-warnings'); assert.ok(messyIdeaOnly.handoff.readiness.nextChecks.some(item => /source artifact id if this came from Scattermind/i.test(item))); const hardRailResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', artifactId: 'concept_map_hard_rails', snapshotTitle: 'Continuation engine guardrail pass', originalPrompt: 'Clarify the continuation engine without turning it into a dashboard.', idea: 'Scattermind clarified that Ranker should defend build order after a Concept Map.', context: 'Solo builder. Avoid dashboards, accounts, saved workspaces, billing, and collaboration before proof.', mode: 'mvp', featureSet: { features: [ { id: 'workspace-autopilot', title: 'Saved workspace autopilot', description: 'A dashboard with accounts, saved workspaces, billing, collaboration, and AI-generated roadmaps.', evidenceNeeded: 'Would teams pay for this later?', rankerHints: { value: 10, effort: 1, confidence: 10, urgency: 10, risk: 1 }, sourceSection: 'concept-map.parkingLot' }, { id: 'manual-source-preview', title: 'Manual source-traced build order preview', description: 'Take one Concept Map and produce a defended do-first / validate-next / defer / park result with source quotes.', evidenceNeeded: 'Can one tired non-AI-native user explain why the first move wins?', rankerHints: { value: 8, effort: 3, confidence: 7, urgency: 7, risk: 3 }, sourceSection: 'concept-map.nextActions' }, { id: 'copyable-brief', title: 'Copyable bridge brief', description: 'Let the user copy the defended order and provenance into notes.', evidenceNeeded: 'Does the copied brief preserve the reason and source trace?', recommendedLane: 'validate-next', sourceSection: 'concept-map.nextActions' }, ], }, }), }); assert.equal(hardRailResponse.status, 200); const hardRail = await hardRailResponse.json(); assert.equal(hardRail.ranked.find(item => item.id === 'workspace-autopilot').lane.source, 'source-non-goal'); assert.equal(hardRail.buildOrder.doFirst[0], 'manual-source-preview', 'first eligible bridge item should become Do first even when a hard-railed candidate scores loudly'); assert.equal(hardRail.brief.quickGlance.topPick, 'Manual source-traced build order preview'); assert.equal(hardRail.handoff.readiness.status, 'ready'); const softGuardrailResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', artifactId: 'concept_map_soft_guardrails', idea: 'A Concept Map clarified that the continuation should stay lightweight and defend one next move.', context: 'Solo builder. This is not a dashboard. Keep auth, billing, saved workspaces, and collaboration out until proof.', mode: 'mvp', featureSet: { features: [ { id: 'decision-strip', title: 'One-screen decision strip', description: 'Show the active build slice with source trace and the first proof step.', evidenceNeeded: 'Can a tired user explain the first move?', rankerHints: { value: 8, effort: 2, confidence: 7, urgency: 7, risk: 2 } }, { id: 'saved-workspace', title: 'Saved workspace dashboard', description: 'Accounts, auth, billing, team collaboration, and saved project dashboards.', rankerHints: { value: 10, effort: 1, confidence: 9, urgency: 9, risk: 1 } }, { id: 'copy-brief', title: 'Copy decision brief', description: 'Copy the defended order and source anchor into notes.', recommendedLane: 'validate-next' }, ], }, }), }); assert.equal(softGuardrailResponse.status, 200); const softGuardrail = await softGuardrailResponse.json(); assert.ok(softGuardrail.input.decisionContext.nonGoals.some(item => /not a dashboard/i.test(item)), 'soft dashboard language should become a non-goal'); assert.ok(softGuardrail.input.decisionContext.nonGoals.some(item => /Keep auth, billing, saved workspaces/i.test(item)), 'keep-out-until-proof language should become a non-goal'); assert.equal(softGuardrail.ranked.find(item => item.id === 'saved-workspace').lane.source, 'source-non-goal'); assert.equal(softGuardrail.buildOrder.doFirst[0], 'decision-strip'); assert.ok(!/dashboard/i.test(softGuardrail.brief.quickGlance.topPick)); const threadGuardrailResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_thread_guardrails', originalPrompt: 'Clarify a service-package idea and decide what should happen next.', conceptMap: { working_name: 'Service package first proof', opening_reflection: 'The Concept Map says the next move is a small proof, not account machinery.', lenses: { channel: { title: 'Build Order', content: 'Build first: Saved workspace dashboard for every package and client. Build first: Manual package teardown preview. Test manually: Copyable decision brief. Defer: Client portal later.', }, }, threads_to_hold: [ 'Do not let this become accounts, saved dashboards, client portals, or a workspace system before the manual proof works.', ], questions_to_sit_with: ['Will one freelancer act on the manual package teardown?'], closing_note: 'Keep the first 48 hours manual and evidence-led.', reference_code: 'SM-THREAD', }, }), }); assert.equal(threadGuardrailResponse.status, 200); const threadGuardrail = await threadGuardrailResponse.json(); assert.ok(threadGuardrail.input.decisionContext.nonGoals.some(item => /Do not let this become accounts/i.test(item)), 'Concept Map threads_to_hold guardrails should be carried into decision context'); assert.equal(threadGuardrail.ranked.find(item => /Saved workspace dashboard/i.test(item.title)).lane.source, 'source-non-goal'); assert.equal(threadGuardrail.buildOrder.doFirst[0], 'build-order-2', 'thread-level guardrail should demote a labelled Build first dashboard and promote the first eligible manual move'); assert.match(threadGuardrail.brief.decisionReceipt.sourceAnchor, /concept-map\.lenses\.channel/); const softDashLabelResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_soft_dash_labels', originalPrompt: 'Scattermind used reader-friendly continuation labels with dashes instead of colon-prefixed lanes.', context: 'Solo builder. Avoid account dashboards and saved workspaces before a manual proof.', conceptMap: { working_name: 'Reader-friendly continuation labels', lenses: { channel: { title: 'Build Order Preview', content: 'Continue first — Manual Concept Map preview with one defended first move. Evidence next – Copy the handoff and ask one tired user what they would do. Hold for later - Polished export templates after proof. Set aside — Saved workspace dashboard with auth and collaboration.', }, }, }, }), }); assert.equal(softDashLabelResponse.status, 200); const softDashLabel = await softDashLabelResponse.json(); assert.equal(softDashLabel.input.optionCount, 4); assert.equal(softDashLabel.buildOrder.doFirst[0], 'build-order-1'); assert.equal(softDashLabel.ranked.find(item => item.id === 'build-order-1').title, 'Manual Concept Map preview with one defended first move'); assert.equal(softDashLabel.ranked.find(item => item.id === 'build-order-2').lane.id, 'test'); assert.equal(softDashLabel.ranked.find(item => item.id === 'build-order-3').lane.id, 'defer'); assert.equal(softDashLabel.ranked.find(item => item.id === 'build-order-4').lane.id, 'park'); assert.match(softDashLabel.handoff.itemTrace.find(item => item.id === 'build-order-1').sourceQuote, /Continue first/); assert.deepEqual(softDashLabel.handoff.warnings, []); const hintedResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', artifactId: 'concept_map_metric_hints', idea: 'A concept map produced possible next moves for an overwhelmed solo builder.', context: 'Defend build order from explicit Scattermind scoring hints plus text; do not let flashy platform language win.', mode: 'mvp', featureSet: { features: [ { id: 'manual-concierge-proof', title: 'Manual concierge proof', description: 'Personally rank three real idea snapshots and turn each into a small build order preview.', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 }, evidenceNeeded: 'Will a tired user act on the first recommended move?', proofSteps: ['Run 3 manual previews'] }, { id: 'ai-autopilot-roadmap', title: 'AI autopilot roadmap platform', description: 'Generate a full automated roadmap with dashboard, workspace, team voting, sync, and integrations.', rankerHints: { value: 5, effort: 9, confidence: 3, urgency: 3, risk: 9 } }, { id: 'nice-export', title: 'Clean export of the build order', description: 'Turn the defended order into a shareable text brief.', scoring: { impact: 7, complexity: 3, certainty: 7, timing: 5, assumptionRisk: 3 }, recommendedLane: 'validate-next' }, ], }, }), }); assert.equal(hintedResponse.status, 200); const hinted = await hintedResponse.json(); assert.equal(hinted.ranked[0].id, 'manual-concierge-proof', 'explicit low-effort/high-confidence Scattermind hints should defend the manual proof slice'); assert.ok(hinted.ranked[0].factors.metricHints.value >= 9); assert.ok(hinted.ranked.find(item => item.id === 'ai-autopilot-roadmap').metrics.risk > hinted.ranked[0].metrics.risk); const actionsResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', artifactId: 'concept_map_actions', snapshotTitle: 'Workshop idea continuation', originalPrompt: 'I want to turn a workshop idea into the first useful thing to build.', idea: 'Scattermind emitted next actions rather than feature objects; Ranker should still defend build order.', context: 'Candidate action set from Concept Map. Keep it action-first and avoid generic workspace layers.', mode: 'mvp', featureSet: { actions: [ { id: 'manual-preview', action: 'Manual build-order preview', why: 'A user sees one defended next move before any app machinery exists.', evidence: 'Can two tired users explain what to do next?', validationSteps: ['Create one static preview from the Concept Map'], suggestedLane: 'do-first', sourceSection: 'concept-map.nextActions' }, { id: 'saved-workspace', action: 'Saved project workspace', why: 'Keep every idea and roadmap in an account dashboard.', dependencies: ['auth', 'database permissions', 'workspace model', 'sync'], risk: 'Dashboard swamp before the continuation proof.', suggestedLane: 'park', sourceSection: 'concept-map.parkingLot' }, { id: 'text-export', action: 'Copyable decision brief', why: 'Let the user paste the defended order into notes or a chat.', evidence: 'Does a plain text brief help them act within 48 hours?', validationSteps: ['Export the top lane and concerns as text'], suggestedLane: 'validate-next', sourceSection: 'concept-map.nextActions' }, ], }, }), }); assert.equal(actionsResponse.status, 200); const actions = await actionsResponse.json(); assert.equal(actions.input.optionCount, 3); assert.equal(actions.ranked[0].id, 'manual-preview', 'action-shaped Concept Map next moves should be rankable without a features wrapper'); assert.equal(actions.ranked.find(item => item.id === 'manual-preview').provenance.sourceSection, 'concept-map.nextActions'); assert.equal(actions.ranked.find(item => item.id === 'saved-workspace').lane.id, 'park'); assert.deepEqual(actions.handoff.warnings, []); const nestedConceptResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', idea: 'Scattermind produced a Concept Map artifact with nested next actions.', context: 'Ranker should consume the artifact directly and preserve provenance without asking Scattermind to rename actions as features.', mode: 'mvp', conceptMap: { id: 'concept_map_nested_42', snapshotTitle: 'Course idea continuation', originalPrompt: 'I have a course idea and need the first build step.', nextActions: [ { id: 'landing-proof', action: 'One-page promise test', why: 'A tired creator can see whether the promise lands before building lessons.', evidence: 'Can 5 target users describe the promised outcome?', validationSteps: ['Write the promise', 'Ask 5 target users'], rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 }, suggestedLane: 'do-first' }, { id: 'lesson-library', action: 'Full lesson library', why: 'Build every module, account dashboard, saved progress, and team workspace.', dependencies: ['auth', 'content system', 'progress tracking', 'workspace'], risk: 'Large platform before promise proof.', suggestedLane: 'park' }, { id: 'copyable-plan', action: 'Copyable build order brief', why: 'Gives the creator a concrete next step to paste into notes.', evidence: 'Does the brief trigger one real follow-up action?', suggestedLane: 'validate-next' }, ], }, }), }); assert.equal(nestedConceptResponse.status, 200); const nestedConcept = await nestedConceptResponse.json(); assert.equal(nestedConcept.input.provenance.artifactId, 'concept_map_nested_42'); assert.equal(nestedConcept.input.provenance.conceptMapId, 'concept_map_nested_42'); assert.equal(nestedConcept.handoff.source.hasOriginalPrompt, true); assert.equal(nestedConcept.ranked[0].id, 'landing-proof'); assert.equal(nestedConcept.ranked.find(item => item.id === 'landing-proof').provenance.sourceSection, 'concept-map.nextActions'); assert.equal(nestedConcept.ranked.find(item => item.id === 'lesson-library').lane.id, 'park'); assert.deepEqual(nestedConcept.handoff.warnings, []); const storedRowPayload = { referenceCode: 'CM-STORED-77', working_name: 'Saved paid Concept Map row', ideaText: 'I sell practical maker workshops and need the first continuation move.', context: 'Solo operator. Manual proof first. Avoid account dashboards before buyer evidence.', fullReadingJson: JSON.stringify({ opening_reflection: 'A maker wants the next build step, not another planning surface.', lenses: { channel: 'Continue first: Concierge build-order preview from one workshop idea. Evidence next: Ask 3 makers whether the preview changes what they would build this week. Hold for later: Polished saved workspace after proof. Set aside: Account dashboard and team voting before evidence.', }, threads_to_hold: ['Start by manually turning one workshop concept into a build order preview', 'Validate with three makers before adding persistence'], }), }; const storedRowPasteResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idea: `Saved Scattermind row pasted from Appwrite:\n\n\`\`\`json\n${JSON.stringify(storedRowPayload)}\n\`\`\``, mode: 'mvp', }), }); assert.equal(storedRowPasteResponse.status, 200); const storedRowPaste = await storedRowPasteResponse.json(); assert.equal(storedRowPaste.input.embeddedPayloadSource, 'idea'); assert.equal(storedRowPaste.input.provenance.artifactId, 'CM-STORED-77'); assert.equal(storedRowPaste.input.provenance.snapshotTitle, 'Saved paid Concept Map row'); assert.match(storedRowPaste.input.provenance.originalPrompt, /maker workshops/); assert.equal(storedRowPaste.ranked[0].id, storedRowPaste.buildOrder.doFirst[0]); assert.match(storedRowPaste.brief.quickGlance.topPick, /Concierge build-order preview/i); assert.match(storedRowPaste.brief.quickGlance.sourceTrace.sourceSection, /concept-map\.lenses\.channel/); assert.equal(storedRowPaste.handoff.source.hasOriginalPrompt, true); assert.equal(storedRowPaste.handoff.readiness.status, 'ready'); assert.match(storedRowPaste.handoff.copyableText, /CM-STORED-77/); 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`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', schema: 'scattermind-snapshot-v1', idea: 'Scattermind has only produced a Snapshot so far; Ranker should still defend a tiny continuation order.', mode: 'mvp', snapshot: { id: 'snapshot_only_17', title: 'Tiny audit service snapshot', originalPrompt: 'I want to sell a small audit service but do not know what to build first.', targetAudience: 'Overwhelmed solo service seller', context: { constraints: ['Manual proof before product shell'], nonGoals: ['Avoid accounts and saved workspaces'], assumptions: ['A one-page promise can validate demand'], }, nextActions: [ { id: 'promise-proof', action: 'One-page promise proof', why: 'Use the Snapshot to test whether buyers understand the outcome before building app machinery.', evidence: 'Can 3 service sellers say what they would buy and why?', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'copyable-brief', action: 'Copyable audit brief', why: 'Turn the defended order into a plain text follow-up.', evidence: 'Does the copied brief make the next move obvious?', suggestedLane: 'validate-next' }, ], parkingLot: [ { id: 'seller-workspace', action: 'Saved seller workspace', why: 'Accounts, saved projects, dashboard, billing, and collaboration for each service seller.', evidence: 'No proof yet' }, ], }, }), }); assert.equal(snapshotOnlyResponse.status, 200); const snapshotOnly = await snapshotOnlyResponse.json(); assert.equal(snapshotOnly.input.provenance.artifactId, 'snapshot_only_17'); assert.equal(snapshotOnly.input.provenance.snapshotTitle, 'Tiny audit service snapshot'); assert.equal(snapshotOnly.input.decisionContext.targetAudience, 'Overwhelmed solo service seller'); assert.deepEqual(snapshotOnly.input.decisionContext.nonGoals, ['Avoid accounts and saved workspaces']); assert.equal(snapshotOnly.ranked[0].id, 'promise-proof', 'Snapshot nextActions should rank without waiting for a Concept Map wrapper'); assert.equal(snapshotOnly.ranked.find(item => item.id === 'promise-proof').provenance.sourceSection, 'snapshot.nextActions'); assert.equal(snapshotOnly.ranked.find(item => item.id === 'copyable-brief').lane.id, 'test'); assert.equal(snapshotOnly.ranked.find(item => item.id === 'seller-workspace').lane.id, 'park'); assert.equal(snapshotOnly.handoff.source.requiresSourceTrace, true); assert.deepEqual(snapshotOnly.handoff.warnings, []); const storedSnapshotRowResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ referenceCode: 'SM-SNAPSHOT-ROW', ideaText: 'I have a tiny paid workshop idea and only the free Snapshot exists so far.', context: 'Solo operator. Manual proof first. Avoid saved workspaces before demand is visible.', status: 'glimpse_ready', glimpseJson: JSON.stringify({ working_name: 'Workshop Seed', restated_idea: 'A tiny workshop offer needs one concrete promise before becoming a platform.', lenses: { shape: { title: 'Product Shape', content: 'Start as a manually sold workshop promise, not a course dashboard. The useful first shape is a short offer and one live test. Avoid saved workspaces until people ask for repeats.', }, }, questions_to_sit_with: ['Will three real prospects understand the workshop promise without extra explanation?'], reference_code: 'SM-SNAPSHOT-ROW', }), mode: 'mvp', }), }); assert.equal(storedSnapshotRowResponse.status, 200); const storedSnapshotRow = await storedSnapshotRowResponse.json(); assert.equal(storedSnapshotRow.input.provenance.artifactId, 'SM-SNAPSHOT-ROW'); assert.equal(storedSnapshotRow.input.provenance.snapshotTitle, 'Workshop Seed'); assert.equal(storedSnapshotRow.input.optionCount, 2, 'stored Snapshot rows should become a manual proof plus evidence question'); assert.equal(storedSnapshotRow.ranked[0].id, 'snapshot-manual-proof'); assert.equal(storedSnapshotRow.ranked[0].provenance.sourceSection, 'snapshot.lenses.shape'); assert.equal(storedSnapshotRow.ranked.find(item => item.id === 'question-1').lane.id, 'test'); assert.match(storedSnapshotRow.handoff.copyableText, /Workshop Seed/); assert.equal(storedSnapshotRow.handoff.readiness.status, 'ready'); assert.deepEqual(storedSnapshotRow.handoff.warnings, []); const sectionedConceptResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_sectioned_lanes', originalPrompt: 'The Concept Map separates next actions, validation ideas, deferred items, and a parking lot.', idea: 'Ranker should combine a sectioned Concept Map into one defended build order without losing lane provenance.', mode: 'mvp', conceptMap: { nextActions: [ { id: 'one-source-preview', action: 'One-source build-order preview', why: 'Turn the Concept Map into a defended first move.', evidence: 'Can one tired user say what to do next?', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, ], validateNext: [ { id: 'copyable-handoff', action: 'Copyable handoff brief', why: 'Let the user paste the build order into notes.', evidence: 'Does the copied brief preserve the action and reason?' }, ], deferred: [ { id: 'visual-polish-pass', action: 'Visual polish pass', why: 'Improve the result screen after the bridge proves useful.', evidence: 'Do users understand the rough brief first?' }, ], parkingLot: [ { id: 'saved-team-workspace', action: 'Saved team workspace', why: 'Accounts, auth dashboard, collaboration, and sync for every idea.', evidence: 'No proof yet' }, ], }, }), }); assert.equal(sectionedConceptResponse.status, 200); const sectionedConcept = await sectionedConceptResponse.json(); assert.equal(sectionedConcept.input.optionCount, 4); assert.equal(sectionedConcept.ranked[0].id, 'one-source-preview'); assert.equal(sectionedConcept.ranked.find(item => item.id === 'copyable-handoff').lane.id, 'test', 'validateNext sections should default into Validate next'); assert.equal(sectionedConcept.ranked.find(item => item.id === 'copyable-handoff').lane.source, 'hint'); assert.equal(sectionedConcept.ranked.find(item => item.id === 'visual-polish-pass').lane.id, 'defer', 'deferred sections should not enter the active proof slice'); assert.equal(sectionedConcept.ranked.find(item => item.id === 'saved-team-workspace').lane.id, 'park', 'parking lot sections should stay parked'); assert.equal(sectionedConcept.handoff.itemTrace.find(item => item.id === 'saved-team-workspace').sourceSection, 'concept-map.parkingLot'); assert.deepEqual(sectionedConcept.handoff.warnings, []); const experimentSectionResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_experiments', originalPrompt: 'The Concept Map emitted experiments separately from next actions.', idea: 'Ranker should merge validation experiments into the build order instead of dropping them.', mode: 'mvp', conceptMap: { nextActions: [ { id: 'manual-build-order', action: 'Manual build-order preview', why: 'Create one defended first move from the source artifact.', evidence: 'Can one tired user act on it?', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, ], experiments: [ { id: 'five-user-comprehension', hypothesis: 'Five-user comprehension test', question: 'Can 3 of 5 non-AI-native users explain the first recommended move?', method: ['Show the copyable brief', 'Ask what they would do next'], sourceItemId: 'experiment-1', sourceTitle: 'Validation experiments' }, ], proofTests: [ { id: 'copy-paste-proof', testName: 'Copy-paste proof test', learningGoal: 'Does the build-order brief survive being pasted into notes?', steps: ['Copy the brief', 'Read it the next morning'], sourceItemId: 'experiment-2', sourceTitle: 'Validation experiments' }, ], parkingLot: [ { id: 'accounted-test-library', action: 'Saved experiment library', why: 'Auth dashboard for every validation test.', evidence: 'No bridge proof yet' }, ], }, }), }); assert.equal(experimentSectionResponse.status, 200); const experimentSection = await experimentSectionResponse.json(); assert.equal(experimentSection.input.optionCount, 4); assert.equal(experimentSection.ranked[0].id, 'manual-build-order'); assert.equal(experimentSection.ranked.find(item => item.id === 'five-user-comprehension').lane.id, 'test'); assert.equal(experimentSection.ranked.find(item => item.id === 'five-user-comprehension').lane.source, 'hint'); assert.equal(experimentSection.ranked.find(item => item.id === 'five-user-comprehension').provenance.sourceSection, 'concept-map.experiments'); assert.equal(experimentSection.ranked.find(item => item.id === 'five-user-comprehension').factors.evidenceNeeded, 'Can 3 of 5 non-AI-native users explain the first recommended move?'); assert.equal(experimentSection.ranked.find(item => item.id === 'copy-paste-proof').lane.id, 'test'); assert.equal(experimentSection.ranked.find(item => item.id === 'copy-paste-proof').provenance.sourceSection, 'concept-map.experiments'); assert.equal(experimentSection.ranked.find(item => item.id === 'accounted-test-library').lane.id, 'park'); assert.deepEqual(experimentSection.handoff.warnings, []); const emptyWrapperResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_empty_wrappers', originalPrompt: 'The export includes empty feature arrays plus real Concept Map next actions.', idea: 'Ranker should ignore empty wrapper arrays and rank the real nested action set.', mode: 'mvp', features: [], featureSet: { features: [], actions: [] }, conceptMap: { nextActions: [ { id: 'source-action-proof', action: 'Source action proof', why: 'Use the Concept Map next action directly to defend the first move.', evidence: 'Can this action become a build-order preview?', suggestedLane: 'do-first' }, { id: 'source-action-export', action: 'Copyable action brief', why: 'Keep the handoff artifact-shaped for a tired user.', evidence: 'Can the brief be pasted into notes?', suggestedLane: 'validate-next' }, { id: 'empty-shadow-dashboard', action: 'Saved dashboard after empty import', why: 'Auth workspace dashboard that should not win.', suggestedLane: 'park' }, ], }, }), }); assert.equal(emptyWrapperResponse.status, 200); const emptyWrapper = await emptyWrapperResponse.json(); assert.equal(emptyWrapper.input.optionCount, 3); assert.equal(emptyWrapper.ranked[0].id, 'source-action-proof', 'empty top-level arrays must not shadow nested Concept Map actions'); assert.equal(emptyWrapper.ranked.find(item => item.id === 'source-action-proof').provenance.sourceSection, 'concept-map.nextActions'); assert.deepEqual(emptyWrapper.handoff.warnings, []); const nonGoalResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_non_goals', originalPrompt: 'I clarified a tiny service idea and need the first build order.', idea: 'Ranker should respect Concept Map non-goals when defending the build order.', mode: 'mvp', conceptMap: { snapshotTitle: 'Non-goal guarded continuation', context: { targetAudience: 'Tired non-AI-native solo operator', constraints: ['No account before first value', 'Manual proof is acceptable'], nonGoals: ['Avoid saved workspaces', 'No auth dashboard', 'No billing layer before proof'], }, nextActions: [ { id: 'workspace-autopilot', action: 'Saved workspace autopilot', why: 'Build accounts, auth dashboard, saved workspaces, and team sync.', evidence: 'None yet', suggestedLane: 'do-first', rankerHints: { value: 10, effort: 2, confidence: 9, urgency: 9, risk: 2 } }, { id: 'manual-next-move', action: 'Manual next-move build order preview', why: 'Turn one source artifact into a defended first action and rank-ready build order without accounts.', evidence: 'Can 3 users act on the first move?', validationSteps: ['Create one static brief'], suggestedLane: 'do-first', rankerHints: { value: 9, effort: 1, confidence: 9, urgency: 9, risk: 1 } }, { id: 'copy-brief', action: 'Copyable build-order brief', why: 'Give the user a plain artifact they can paste into notes.', evidence: 'Does copy/paste preserve the next step?', suggestedLane: 'validate-next' }, ], }, }), }); assert.equal(nonGoalResponse.status, 200); const nonGoal = await nonGoalResponse.json(); assert.equal(nonGoal.input.decisionContext.targetAudience, 'Tired non-AI-native solo operator'); assert.deepEqual(nonGoal.input.decisionContext.nonGoals, ['Avoid saved workspaces', 'No auth dashboard', 'No billing layer before proof']); assert.ok(nonGoal.brief.assumptions.includes('Constraint: No account before first value')); assert.ok(nonGoal.brief.assumptions.includes('Non-goal: Avoid saved workspaces')); assert.equal(nonGoal.ranked[0].id, 'manual-next-move', 'non-goal conflicts should beat flashy positive hints'); const workspace = nonGoal.ranked.find(item => item.id === 'workspace-autopilot'); assert.ok(workspace.metrics.nonGoalConflicts.length >= 2); assert.match(workspace.concern, /Source context says not to do this yet/); assert.equal(workspace.lane.id, 'defer', 'source non-goals should keep conflicted candidates out of the active proof slice even with strong hints'); assert.equal(workspace.lane.source, 'source-non-goal'); assert.deepEqual(nonGoal.handoff.itemTrace.find(item => item.id === 'workspace-autopilot').nonGoalConflicts, workspace.metrics.nonGoalConflicts); assert.ok(!nonGoal.buildOrder.doFirst.includes('workspace-autopilot')); assert.ok(!nonGoal.buildOrder.validateNext.includes('workspace-autopilot')); assert.ok(!nonGoal.handoff.warnings.some(item => /active item workspace-autopilot conflicts/.test(item)), 'conflicted candidates should be demoted before handoff warnings need to flag active-lane conflict'); const mixedWrapperResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_mixed_wrappers', originalPrompt: 'The bridge export contains a normalized feature list plus Concept Map validation and parking sections.', idea: 'Ranker should not lose sectioned Concept Map context when a partial feature wrapper is also present.', mode: 'mvp', featureSet: { features: [ { id: 'manual-bridge-proof', title: 'Manual bridge proof', description: 'Turn one Concept Map into a defended build-order preview.', evidenceNeeded: 'Can one tired user act on the preview?', recommendedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, ], }, conceptMap: { validateNext: [ { id: 'copyable-brief-test', action: 'Copyable brief test', why: 'Check whether the decision brief remains useful outside Ranker.', evidence: 'Can the user paste it into notes and still know the next move?' }, ], parkingLot: [ { id: 'account-dashboard', action: 'Account dashboard', why: 'Saved workspaces, auth, billing, and team sync.', evidence: 'No bridge proof yet' }, ], }, }), }); assert.equal(mixedWrapperResponse.status, 200); const mixedWrapper = await mixedWrapperResponse.json(); assert.equal(mixedWrapper.input.optionCount, 3); assert.equal(mixedWrapper.ranked[0].id, 'manual-bridge-proof'); assert.equal(mixedWrapper.handoff.itemTrace.find(item => item.id === 'manual-bridge-proof').sourceSection, 'feature-set.features'); assert.equal(mixedWrapper.ranked.find(item => item.id === 'copyable-brief-test').lane.id, 'test'); assert.equal(mixedWrapper.handoff.itemTrace.find(item => item.id === 'copyable-brief-test').sourceSection, 'concept-map.validateNext'); assert.equal(mixedWrapper.ranked.find(item => item.id === 'account-dashboard').lane.id, 'park'); assert.equal(mixedWrapper.handoff.itemTrace.find(item => item.id === 'account-dashboard').sourceSection, 'concept-map.parkingLot'); assert.deepEqual(mixedWrapper.handoff.warnings, []); const laneAliasResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_lane_aliases', originalPrompt: 'Scattermind exported normalized candidates with lane fields instead of recommendedLane.', idea: 'Ranker should treat lane as a lane hint when it is do-first/validate-next/defer/park, while preserving the actual source section.', mode: 'mvp', featureSet: { features: [ { id: 'manual-bridge-proof', title: 'Manual bridge proof', description: 'Defended build order from one Concept Map.', evidenceNeeded: 'Can one tired user act on the first move?', lane: 'do-first', sourceSection: 'concept-map.nextActions', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'copyable-decision-brief', title: 'Copyable decision brief', description: 'Export the defended order as plain text.', evidenceNeeded: 'Does the copied brief preserve the next action?', lane: 'validate-next', sourceSection: 'concept-map.nextActions' }, { id: 'auth-workspace', title: 'Auth workspace', description: 'Accounts, dashboard, saved projects, and collaboration.', evidenceNeeded: 'No bridge proof yet.', lane: 'park', sourceSection: 'concept-map.parkingLot' }, ], }, }), }); assert.equal(laneAliasResponse.status, 200); const laneAlias = await laneAliasResponse.json(); assert.equal(laneAlias.ranked[0].id, 'manual-bridge-proof'); assert.equal(laneAlias.ranked.find(item => item.id === 'manual-bridge-proof').provenance.sourceSection, 'concept-map.nextActions'); assert.equal(laneAlias.ranked.find(item => item.id === 'copyable-decision-brief').lane.id, 'test'); assert.equal(laneAlias.ranked.find(item => item.id === 'copyable-decision-brief').lane.source, 'hint'); assert.equal(laneAlias.ranked.find(item => item.id === 'auth-workspace').lane.id, 'park'); assert.equal(laneAlias.ranked.find(item => item.id === 'auth-workspace').lane.source, 'hint'); assert.equal(laneAlias.handoff.itemTrace.find(item => item.id === 'auth-workspace').sourceSection, 'concept-map.parkingLot'); assert.deepEqual(laneAlias.handoff.warnings, []); const duplicateIdResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_duplicate_ids', originalPrompt: 'I pasted duplicated next-move IDs from a messy Concept Map export.', idea: 'Ranker should keep handoff rows addressable even if Scattermind sends duplicate candidate IDs.', mode: 'mvp', conceptMap: { nextActions: [ { id: 'preview', action: 'Manual build-order preview', why: 'Defends the first move without dashboard machinery.', evidence: 'Can one user act on the preview?', suggestedLane: 'do-first' }, { id: 'preview', action: 'Copyable preview brief', why: 'Exports the defended order into notes.', evidence: 'Does the copied brief preserve the next action?', suggestedLane: 'validate-next' }, { id: 'workspace', action: 'Saved workspace', why: 'Auth dashboard for every idea.', evidence: 'None yet', suggestedLane: 'park' }, ], }, }), }); assert.equal(duplicateIdResponse.status, 200); const duplicateIds = await duplicateIdResponse.json(); assert.deepEqual(duplicateIds.ranked.map(item => item.id).sort(), ['preview', 'preview-2', 'workspace']); assert.equal(new Set(duplicateIds.handoff.itemTrace.map(item => item.id)).size, duplicateIds.handoff.itemTrace.length); assert.equal(duplicateIds.handoff.itemTrace.find(item => item.id === 'preview-2').originalId, 'preview'); assert.equal(duplicateIds.handoff.itemTrace.find(item => item.id === 'preview-2').idNormalized, true); assert.ok(duplicateIds.handoff.warnings.some(item => /duplicate source id preview normalized to preview-2/.test(item))); assert.ok(Object.values(duplicateIds.buildOrder).flat().includes('preview-2')); assert.equal(duplicateIds.handoff.readiness.status, 'usable-with-warnings'); assert.ok(duplicateIds.handoff.readiness.nextChecks.some(item => /duplicate IDs/i.test(item))); const structuredContextResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_structured_context', originalPrompt: 'Scattermind sent a structured context object instead of a flat context string.', idea: 'Ranker should preserve structured context and not turn it into [object Object].', mode: 'mvp', context: { summary: 'Bridge proof for a tired non-AI-native user.', targetAudience: 'Tired non-AI-native solo builder', constraints: ['No account before first value', 'Use a copyable artifact first'], nonGoals: ['Avoid auth dashboard', 'Avoid saved workspaces'], assumptions: ['Manual proof is acceptable for the first pass'], }, conceptMap: { nextActions: [ { id: 'copyable-bridge-artifact', action: 'Copyable bridge artifact', why: 'Turn the source Concept Map into one defended build-order brief.', evidence: 'Can the user paste it and know the first move?', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'auth-dashboard', action: 'Auth dashboard', why: 'Accounts and saved workspaces for every idea.', evidence: 'None yet', suggestedLane: 'do-first', rankerHints: { value: 10, effort: 2, confidence: 9, urgency: 9, risk: 2 } }, ], }, }), }); assert.equal(structuredContextResponse.status, 200); const structuredContext = await structuredContextResponse.json(); assert.doesNotMatch(structuredContext.input.context, /\[object Object\]/); assert.match(structuredContext.input.context, /Target audience: Tired non-AI-native solo builder/); assert.deepEqual(structuredContext.input.decisionContext.constraints, ['No account before first value', 'Use a copyable artifact first']); assert.deepEqual(structuredContext.handoff.decisionContext.nonGoals, ['Avoid auth dashboard', 'Avoid saved workspaces']); assert.equal(structuredContext.ranked[0].id, 'copyable-bridge-artifact'); assert.equal(structuredContext.ranked.find(item => item.id === 'auth-dashboard').lane.source, 'source-non-goal'); const lensOnlyResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_lens_only', originalPrompt: 'Scattermind produced the current paid Concept Map shape: lenses with a Build Order paragraph, not arrays.', idea: 'Ranker should turn the Build Order lens into rank-ready candidates without asking Scattermind to rename fields first.', mode: 'mvp', conceptMap: { snapshotTitle: 'Lens-only Concept Map bridge', lenses: { risk: { title: 'What Can Mislead You', content: 'Avoid saved workspaces and auth dashboard before one manual proof. Do not build billing yet.', }, channel: { title: 'Build Order', content: 'Build first: Manual build-order preview from one Concept Map - prove the bridge before adding product machinery. Test manually: Copyable decision brief - show it to 3 tired users and ask what they would do next. Defer: Visual polish pass after the rough artifact is understood. Probably noise: Saved workspace dashboard with auth, billing, and team collaboration.', }, }, }, }), }); assert.equal(lensOnlyResponse.status, 200); const lensOnly = await lensOnlyResponse.json(); assert.equal(lensOnly.input.optionCount, 4); assert.equal(lensOnly.ranked[0].id, 'build-order-1'); assert.equal(lensOnly.ranked[0].provenance.sourceSection, 'concept-map.lenses.channel'); assert.equal(lensOnly.ranked[0].provenance.sourceId, 'concept-map.lenses.channel#1'); assert.equal(lensOnly.ranked[0].provenance.sourceTitle, 'Build Order'); assert.match(lensOnly.ranked[0].provenance.sourceQuote, /Build first: Manual build-order preview/); assert.equal(lensOnly.brief.quickGlance.sourceTrace.sourceId, 'concept-map.lenses.channel#1'); assert.equal(lensOnly.ranked.find(item => item.id === 'build-order-2').lane.id, 'test'); assert.equal(lensOnly.ranked.find(item => item.id === 'build-order-3').lane.id, 'defer'); assert.equal(lensOnly.ranked.find(item => item.id === 'build-order-4').lane.id, 'park'); assert.ok(lensOnly.input.decisionContext.nonGoals.includes('Avoid saved workspaces and auth dashboard before one manual proof')); assert.ok(lensOnly.input.decisionContext.nonGoals.includes('Do not build billing yet')); assert.ok(lensOnly.ranked.find(item => item.id === 'build-order-4').metrics.nonGoalConflicts.length >= 1); assert.deepEqual(lensOnly.handoff.warnings, []); const scattermindPaidShapeResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reference_code: 'SM-PAID1', working_name: 'Neighborhood Supper Club', ideaText: 'I want to test a tiny paid supper club before building a food community app.', context: 'Solo operator. Manual proof first. Avoid accounts and saved workspaces before anyone pays.', mode: 'mvp', lenses: { audience: 'First buyers are local neighbors who already attend small food events and want a low-pressure dinner plan.', risk: 'Avoid accounts and saved workspaces before anyone pays. Do not build subscriptions or an app dashboard yet.', question: 'Proof steps: Ask ten neighbors if they would pay for the first dinner before building software. Run one manual invite script and collect yes/no replies.', channel: 'Build first: One manual supper-club offer page - collect three real yes/no replies before building machinery. Test manually: Concierge invitation script - ask ten neighbors if they would pay for the first dinner. Defer: Pretty event calendar after the first paid table. Probably noise: Saved member workspace with accounts, billing, subscriptions, and team dashboard.', }, }), }); assert.equal(scattermindPaidShapeResponse.status, 200); const scattermindPaidShape = await scattermindPaidShapeResponse.json(); assert.equal(scattermindPaidShape.input.provenance.artifactId, 'SM-PAID1'); assert.equal(scattermindPaidShape.input.provenance.snapshotTitle, 'Neighborhood Supper Club'); assert.match(scattermindPaidShape.input.provenance.originalPrompt, /supper club/); assert.equal(scattermindPaidShape.input.optionCount, 6); assert.equal(scattermindPaidShape.ranked[0].id, 'build-order-1'); assert.equal(scattermindPaidShape.ranked[0].provenance.sourceId, 'concept-map.lenses.channel#1'); assert.equal(scattermindPaidShape.ranked[0].provenance.sourceTitle, 'Build Order'); assert.equal(scattermindPaidShape.ranked.find(item => item.id === 'proof-step-1').lane.id, 'test'); assert.equal(scattermindPaidShape.ranked.find(item => item.id === 'proof-step-1').provenance.sourceSection, 'concept-map.lenses.question'); assert.match(scattermindPaidShape.ranked.find(item => item.id === 'proof-step-1').factors.evidenceNeeded, /Ask ten neighbors/); assert.equal(scattermindPaidShape.handoff.itemTrace.find(item => item.id === 'proof-step-1').sourceTitle, 'Proof Steps'); assert.match(scattermindPaidShape.handoff.itemTrace.find(item => item.id === 'build-order-1').sourceQuote, /One manual supper-club offer page/); assert.equal(scattermindPaidShape.ranked.find(item => item.id === 'build-order-4').lane.id, 'park'); assert.ok(scattermindPaidShape.input.decisionContext.nonGoals.includes('Avoid accounts and saved workspaces before anyone pays')); assert.ok(scattermindPaidShape.ranked.find(item => item.id === 'build-order-4').metrics.nonGoalConflicts.length >= 1); assert.deepEqual(scattermindPaidShape.handoff.warnings, []); const softLabelLensResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reference_code: 'SM-SOFT-LABELS', working_name: 'Gentle Scattermind continuation labels', ideaText: 'Scattermind avoids verdict language but still needs to hand Ranker a continuation order.', context: 'Solo builder. Manual proof before machinery. Avoid accounts and saved workspaces.', mode: 'mvp', lenses: { risk: 'Avoid accounts and saved workspaces until one copyable result makes sense.', channel: 'Continue first: One source-traced build order preview - make the next move tangible without a dashboard. Try next: Copyable decision brief - ask three tired users what they would do next. Hold for later: Visual polish after the rough brief works. Set aside: Saved workspace with accounts, auth, billing, and collaboration.', }, }), }); assert.equal(softLabelLensResponse.status, 200); const softLabelLens = await softLabelLensResponse.json(); assert.equal(softLabelLens.input.optionCount, 4); assert.equal(softLabelLens.ranked[0].id, 'build-order-1'); assert.equal(softLabelLens.ranked[0].lane.id, 'do'); assert.match(softLabelLens.ranked[0].provenance.sourceQuote, /Continue first: One source-traced build order preview/); assert.equal(softLabelLens.ranked.find(item => item.id === 'build-order-2').lane.id, 'test'); assert.equal(softLabelLens.ranked.find(item => item.id === 'build-order-3').lane.id, 'defer'); assert.equal(softLabelLens.ranked.find(item => item.id === 'build-order-4').lane.id, 'park'); assert.equal(softLabelLens.handoff.readiness.status, 'ready'); assert.deepEqual(softLabelLens.handoff.warnings, []); const summaryOnlyConceptMapResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reference_code: 'SM-SUMMARY-ONLY', working_name: 'Tired maker continuation pass', opening_reflection: 'A tired maker needs one defended first-week build order after Scattermind clarified the idea.', context: 'Solo builder. Manual proof first. Avoid accounts and saved workspaces before the build order lands.', mode: 'mvp', lenses: { risk: 'Avoid accounts and saved workspaces before the first copyable result works.', channel: 'First week: Manual source-traced preview - turn the Concept Map into one defended next move. Evidence next: Copyable handoff comprehension check - ask three tired users what they would do next. Hold for later: Visual polish after comprehension proof. Set aside: Saved account workspace with dashboard and billing.', }, }), }); assert.equal(summaryOnlyConceptMapResponse.status, 200); const summaryOnlyConceptMap = await summaryOnlyConceptMapResponse.json(); assert.equal(summaryOnlyConceptMap.input.idea, 'A tired maker needs one defended first-week build order after Scattermind clarified the idea.'); assert.equal(summaryOnlyConceptMap.input.provenance.artifactId, 'SM-SUMMARY-ONLY'); assert.equal(summaryOnlyConceptMap.input.provenance.snapshotTitle, 'Tired maker continuation pass'); assert.match(summaryOnlyConceptMap.input.provenance.sourceSummary, /first-week build order/); assert.equal(summaryOnlyConceptMap.input.provenance.originalPrompt, ''); assert.equal(summaryOnlyConceptMap.ranked[0].lane.id, 'do'); assert.match(summaryOnlyConceptMap.ranked[0].provenance.sourceQuote, /First week: Manual source-traced preview/); assert.equal(summaryOnlyConceptMap.ranked.find(item => item.id === 'build-order-2').lane.id, 'test'); assert.equal(summaryOnlyConceptMap.handoff.source.hasOriginalPrompt, false); assert.equal(summaryOnlyConceptMap.handoff.source.hasSourceSummary, true); assert.equal(summaryOnlyConceptMap.handoff.readiness.status, 'ready'); assert.equal(summaryOnlyConceptMap.handoff.readiness.sourceComplete, true); assert.deepEqual(summaryOnlyConceptMap.handoff.warnings, []); assert.match(summaryOnlyConceptMap.handoff.copyableText, /Source summary: A tired maker needs one defended first-week build order/); assert.match(summaryOnlyConceptMap.brief.source.sourceSummaryExcerpt, /first-week build order/); const softLabelObjectResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_soft_object_labels', originalPrompt: 'Scattermind exported soft continuation sections instead of verdict-named lanes.', idea: 'Ranker should accept softer object keys without forcing Scattermind to say build/kill.', mode: 'mvp', conceptMap: { buildOrder: { continueFirst: [{ id: 'manual-preview', move: 'Manual continuation preview', evidenceQuestion: 'Can one user explain the next move?' }], evidenceNext: ['Copyable brief comprehension check'], holdForLater: ['Visual system polish'], setAside: ['Account workspace dashboard'], }, }, }), }); assert.equal(softLabelObjectResponse.status, 200); const softLabelObject = await softLabelObjectResponse.json(); assert.equal(softLabelObject.input.optionCount, 4); assert.equal(softLabelObject.buildOrder.doFirst[0], 'manual-preview'); assert.equal(softLabelObject.ranked.find(item => item.id === 'feature-1').lane.id, 'test'); assert.equal(softLabelObject.ranked.find(item => item.title === 'Visual system polish').lane.id, 'defer'); assert.equal(softLabelObject.ranked.find(item => item.title === 'Account workspace dashboard').lane.id, 'park'); const mergedContextResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_merged_context', originalPrompt: 'Scattermind sent summary context plus deeper Concept Map guardrails and lenses.', idea: 'Ranker should merge context sources instead of letting a shallow top-level summary shadow Concept Map constraints.', mode: 'mvp', context: { summary: 'Continuation bridge for an overwhelmed non-AI-native operator.' }, conceptMap: { context: { targetAudience: 'Overwhelmed non-AI-native shop owner', constraints: ['Manual proof before saved projects'], nonGoals: ['Avoid workspace dashboard'], assumptions: ['A copyable brief is enough for the first pass'], }, lenses: { constraints: { content: 'No auth before first value. Keep the result copyable.' }, assumptions: { content: 'The user is tired; one defended next move beats a backlog.' }, }, nextActions: [ { id: 'defended-next-move', action: 'Defended next-move brief', why: 'One copyable build order with source provenance.', evidence: 'Can the shop owner name the next step?', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'workspace-dashboard', action: 'Workspace dashboard', why: 'Accounts, saved projects, and auth dashboard.', evidence: 'No proof yet', suggestedLane: 'do-first', rankerHints: { value: 10, effort: 2, confidence: 9, urgency: 9, risk: 2 } }, ], }, }), }); assert.equal(mergedContextResponse.status, 200); const mergedContext = await mergedContextResponse.json(); assert.equal(mergedContext.input.decisionContext.targetAudience, 'Overwhelmed non-AI-native shop owner'); assert.ok(mergedContext.input.decisionContext.constraints.includes('Manual proof before saved projects')); assert.ok(mergedContext.input.decisionContext.constraints.includes('No auth before first value')); assert.ok(mergedContext.input.decisionContext.nonGoals.includes('Avoid workspace dashboard')); assert.ok(mergedContext.input.decisionContext.assumptions.includes('A copyable brief is enough for the first pass')); assert.ok(mergedContext.input.decisionContext.assumptions.includes('The user is tired')); assert.equal(mergedContext.ranked[0].id, 'defended-next-move'); assert.equal(mergedContext.ranked.find(item => item.id === 'workspace-dashboard').lane.source, 'source-non-goal'); assert.deepEqual(mergedContext.handoff.warnings, []); const objectBuildOrderResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_object_build_order', originalPrompt: 'Scattermind exported a Build Order object instead of nextActions arrays.', idea: 'Ranker should accept an already-laned Build Order object and preserve lane provenance.', mode: 'mvp', conceptMap: { snapshotTitle: 'Object Build Order bridge', context: { targetAudience: 'Tired local service seller', constraints: ['Copyable output before accounts'], nonGoals: ['Avoid saved workspace dashboard'], }, buildOrder: { doFirst: [ { id: 'manual-offer-proof', move: 'Manual offer proof', why: 'Send one copyable offer to three real prospects.', questionToAnswer: 'Will one prospect ask for the next step?', nextAction: 'Send the offer to three named prospects before touching the page design.', successSignal: 'One prospect asks how to buy or book the next step.', killSignal: 'All three prospects understand it but none want the next step.' }, ], validateNext: [ 'Copyable follow-up script', ], deferred: [ { id: 'visual-refresh', title: 'Visual refresh after proof', evidenceQuestion: 'Does the rough brief work first?' }, ], parkingLot: [ { id: 'workspace-dashboard', title: 'Saved workspace dashboard', description: 'Accounts, auth, and saved projects for every offer.', evidenceNeeded: 'No proof yet' }, ], }, }, }), }); assert.equal(objectBuildOrderResponse.status, 200); const objectBuildOrder = await objectBuildOrderResponse.json(); assert.equal(objectBuildOrder.input.optionCount, 4); assert.equal(objectBuildOrder.ranked[0].id, 'manual-offer-proof'); assert.equal(objectBuildOrder.ranked[0].factors.evidenceNeeded, 'Will one prospect ask for the next step?'); assert.equal(objectBuildOrder.ranked[0].nextStep, 'Send the offer to three named prospects before touching the page design.'); assert.equal(objectBuildOrder.ranked[0].successSignal, 'One prospect asks how to buy or book the next step.'); assert.equal(objectBuildOrder.ranked[0].killSignal, 'All three prospects understand it but none want the next step.'); assert.equal(objectBuildOrder.buildOrderDetails.doFirst[0].successSignal, 'One prospect asks how to buy or book the next step.'); assert.equal(objectBuildOrder.handoff.itemTrace.find(item => item.id === 'manual-offer-proof').nextStep, 'Send the offer to three named prospects before touching the page design.'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'feature-1').title, 'Copyable follow-up script'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'feature-1').provenance.sourceId, 'concept-map.buildOrder.validateNext#1'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'feature-1').provenance.sourceQuote, 'Copyable follow-up script'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'feature-1').lane.id, 'test'); assert.equal(objectBuildOrder.handoff.itemTrace.find(item => item.id === 'feature-1').sourceSection, 'concept-map.buildOrder.validateNext'); assert.equal(objectBuildOrder.handoff.itemTrace.find(item => item.id === 'feature-1').sourceId, 'concept-map.buildOrder.validateNext#1'); assert.equal(objectBuildOrder.handoff.itemTrace.find(item => item.id === 'feature-1').sourceQuote, 'Copyable follow-up script'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'workspace-dashboard').lane.id, 'park'); assert.equal(objectBuildOrder.ranked.find(item => item.id === 'workspace-dashboard').lane.source, 'hint'); assert.ok(objectBuildOrder.handoff.warnings.includes('missing evidence needed for active item feature-1')); assert.equal(objectBuildOrder.handoff.readiness.status, 'needs-source-context'); assert.ok(objectBuildOrder.handoff.readiness.blockers.includes('missing evidence needed for active item feature-1')); assert.ok(objectBuildOrder.handoff.readiness.nextChecks.some(item => /evidenceNeeded/i.test(item))); const embeddedJsonResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idea: JSON.stringify({ reference_code: 'SM-PASTE1', working_name: 'Raw pasted Concept Map', ideaText: 'The user pasted a raw Scattermind Concept Map JSON blob into the public Ranker form.', lenses: { risk: 'Avoid saved workspaces before one copyable result lands.', channel: 'Build first: Raw JSON handoff detection - turn the pasted Concept Map into a defended build order. Test manually: Copy the decision brief into notes and check whether the first move survives. Probably noise: Saved workspace with accounts and team dashboard.', }, }), mode: 'mvp', context: '', }), }); assert.equal(embeddedJsonResponse.status, 200); const embeddedJson = await embeddedJsonResponse.json(); assert.equal(embeddedJson.input.embeddedPayloadSource, 'idea'); assert.equal(embeddedJson.input.provenance.artifactId, 'SM-PASTE1'); assert.equal(embeddedJson.input.optionCount, 3); assert.equal(embeddedJson.ranked[0].id, 'build-order-1'); assert.equal(embeddedJson.ranked.find(item => item.id === 'build-order-3').lane.id, 'park'); assert.ok(embeddedJson.input.decisionContext.nonGoals.includes('Avoid saved workspaces before one copyable result lands')); assert.deepEqual(embeddedJson.handoff.warnings, []); const fencedJsonResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ optionsText: `Here is the Scattermind export I copied:\n\n\`\`\`json\n${JSON.stringify({ reference_code: 'SM-FENCE1', working_name: 'Fenced pasted Concept Map', ideaText: 'The user copied a fenced Scattermind JSON export plus surrounding prose.', lenses: { risk: 'Avoid saved workspaces and account dashboard before the first manual proof.', channel: 'Build first: Fenced JSON handoff - detect the pasted Concept Map and defend the first move. Test manually: Copy the ranked brief into notes and ask one user what they would do next. Probably noise: Account dashboard with saved workspaces and collaboration.', }, })}\n\`\`\`\n\nPlease rank this.`, mode: 'mvp', }), }); assert.equal(fencedJsonResponse.status, 200); const fencedJson = await fencedJsonResponse.json(); assert.equal(fencedJson.input.embeddedPayloadSource, 'optionsText'); assert.equal(fencedJson.input.provenance.artifactId, 'SM-FENCE1'); assert.equal(fencedJson.input.optionCount, 3); assert.equal(fencedJson.ranked[0].id, 'build-order-1'); assert.equal(fencedJson.ranked.find(item => item.id === 'build-order-3').lane.id, 'park'); assert.ok(fencedJson.input.decisionContext.nonGoals.includes('Avoid saved workspaces and account dashboard before the first manual proof')); assert.deepEqual(fencedJson.handoff.warnings, []); const embeddedSnapshotResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idea: `Pasted Snapshot export:\n${JSON.stringify({ snapshot: { id: 'SNAP-PASTE1', title: 'Schema-light Snapshot paste', originalPrompt: 'I only have a Snapshot JSON export and need the first continuation move.', context: { targetAudience: 'Tired solo builder', constraints: ['Manual proof first'], nonGoals: ['Avoid account dashboard'], }, nextActions: [ { id: 'manual-snapshot-preview', action: 'Manual Snapshot build-order preview', why: 'Turn the Snapshot into one defended first move.', evidence: 'Can one user say what to do next?', suggestedLane: 'do-first' }, { id: 'copyable-snapshot-brief', action: 'Copyable Snapshot brief', why: 'Let the user paste the defended order elsewhere.', evidence: 'Does the pasted brief preserve the next action?', suggestedLane: 'validate-next' }, { id: 'account-dashboard', action: 'Account dashboard', why: 'Saved projects and auth dashboard for every Snapshot.', evidence: 'No proof yet', suggestedLane: 'park' }, ], }, })}`, mode: 'mvp', }), }); assert.equal(embeddedSnapshotResponse.status, 200); const embeddedSnapshot = await embeddedSnapshotResponse.json(); assert.equal(embeddedSnapshot.input.embeddedPayloadSource, 'idea'); assert.equal(embeddedSnapshot.input.provenance.artifactId, 'SNAP-PASTE1'); assert.equal(embeddedSnapshot.input.provenance.snapshotTitle, 'Schema-light Snapshot paste'); assert.equal(embeddedSnapshot.input.optionCount, 3); assert.equal(embeddedSnapshot.ranked[0].id, 'manual-snapshot-preview'); assert.equal(embeddedSnapshot.ranked.find(item => item.id === 'manual-snapshot-preview').provenance.sourceSection, 'snapshot.nextActions'); assert.equal(embeddedSnapshot.ranked.find(item => item.id === 'account-dashboard').lane.id, 'park'); assert.deepEqual(embeddedSnapshot.handoff.warnings, []); const sourceExcerptResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_source_excerpts', originalPrompt: 'Scattermind exported source excerpts for each recommended move.', idea: 'Ranker should preserve source excerpts so the defended build order can point back to the exact Concept Map note.', mode: 'mvp', conceptMap: { nextActions: [ { id: 'manual-proof', action: 'Manual proof preview', why: 'Show one defended next move before adding machinery.', evidence: 'Can one tired user act on it?', sourceItemId: 'lens-channel-1', sourceTitle: 'Build Order', sourceExcerpt: 'Build first: show one defended next move before adding machinery.', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'copyable-brief', action: 'Copyable brief', why: 'Let the user paste the defended order into notes.', evidence: 'Does the pasted brief preserve the first move?', sourceItemId: 'lens-channel-2', lensTitle: 'Build Order', quote: 'Test manually: copy the ranked brief into notes.', suggestedLane: 'validate-next' }, { id: 'saved-workspace', action: 'Saved workspace', why: 'Accounts and saved projects for every idea.', evidence: 'No bridge proof yet.', sourceItemId: 'lens-risk-1', sourceHeading: 'What can mislead you', sourceQuote: 'Probably noise: saved workspace with accounts before proof.', suggestedLane: 'park' }, ], }, }), }); assert.equal(sourceExcerptResponse.status, 200); const sourceExcerpt = await sourceExcerptResponse.json(); assert.equal(sourceExcerpt.ranked[0].id, 'manual-proof'); assert.equal(sourceExcerpt.ranked[0].provenance.sourceId, 'lens-channel-1'); assert.equal(sourceExcerpt.ranked[0].provenance.sourceTitle, 'Build Order'); assert.match(sourceExcerpt.ranked[0].provenance.sourceQuote, /Build first/); assert.match(sourceExcerpt.brief.source.originalPromptExcerpt, /source excerpts/); assert.equal(sourceExcerpt.brief.quickGlance.sourceTrace.sourceId, 'lens-channel-1'); assert.match(sourceExcerpt.brief.quickGlance.sourceTrace.sourceQuote, /defended next move/); assert.equal(sourceExcerpt.handoff.source.originalPromptExcerpt, 'Scattermind exported source excerpts for each recommended move.'); assert.equal(sourceExcerpt.buildOrderDetails.doFirst[0].sourceId, 'lens-channel-1'); assert.match(sourceExcerpt.buildOrderDetails.doFirst[0].sourceQuote, /defended next move/); assert.equal(sourceExcerpt.handoff.itemTrace.find(item => item.id === 'copyable-brief').sourceTitle, 'Build Order'); assert.match(sourceExcerpt.handoff.itemTrace.find(item => item.id === 'saved-workspace').sourceQuote, /Probably noise/); assert.deepEqual(sourceExcerpt.handoff.warnings, []); assert.equal(sourceExcerpt.handoff.readiness.status, 'ready'); assert.equal(sourceExcerpt.handoff.readiness.activeItemCount, 2); const snakeCaseBridgeResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'scattermind-concept-map-v1', source_name: 'Scattermind', source_artifact_id: 'SM-SNAKE-1', snapshot_title: 'Snake-case bridge export', concept_map_id: 'CM-SNAKE-1', original_prompt: 'I have a clarified idea and need a defended build order from snake_case JSON.', context: { target_audience: 'Tired non-AI-native solo builder', constraints: ['Manual proof before product shell'], non_goals: ['Avoid account dashboards and saved workspaces before proof'], }, concept_map: { next_actions: [ { id: 'manual-bridge-proof', action: 'Manual bridge proof preview', why: 'Show the defended first move with source trace.', evidence_needed: 'Can one tired user say why this wins?', proof_steps: ['Create one static preview'], recommended_lane: 'do-first', source_section: 'concept-map.next_actions', source_item_id: 'snake-next-1', source_title: 'Build order lens', source_excerpt: 'Build first: manual bridge proof preview.', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'copyable-handoff', action: 'Copyable handoff brief', why: 'Preserve the decision outside the app.', evidence_needed: 'Does the copied brief retain source and next step?', suggested_lane: 'validate-next', source_section: 'concept-map.next_actions', source_item_id: 'snake-next-2' }, ], parking_lot: [ { id: 'saved-workspace', action: 'Saved workspace dashboard', why: 'Accounts, dashboards, and saved projects for every idea.', evidence_needed: 'No proof yet.', suggested_lane: 'park', source_section: 'concept-map.parking_lot', source_item_id: 'snake-park-1' }, ], }, }), }); assert.equal(snakeCaseBridgeResponse.status, 200); const snakeCaseBridge = await snakeCaseBridgeResponse.json(); assert.equal(snakeCaseBridge.input.provenance.artifactId, 'SM-SNAKE-1'); assert.equal(snakeCaseBridge.input.provenance.snapshotTitle, 'Snake-case bridge export'); assert.equal(snakeCaseBridge.input.provenance.conceptMapId, 'CM-SNAKE-1'); assert.equal(snakeCaseBridge.input.provenance.originalPrompt, 'I have a clarified idea and need a defended build order from snake_case JSON.'); assert.equal(snakeCaseBridge.input.decisionContext.targetAudience, 'Tired non-AI-native solo builder'); assert.ok(snakeCaseBridge.input.decisionContext.nonGoals.includes('Avoid account dashboards and saved workspaces before proof')); assert.equal(snakeCaseBridge.ranked[0].id, 'manual-bridge-proof'); assert.equal(snakeCaseBridge.ranked[0].provenance.sourceSection, 'concept-map.next_actions'); assert.equal(snakeCaseBridge.ranked[0].provenance.sourceId, 'snake-next-1'); assert.equal(snakeCaseBridge.ranked[0].factors.evidenceNeeded, 'Can one tired user say why this wins?'); assert.ok(snakeCaseBridge.ranked[0].factors.proofSteps.includes('Create one static preview')); assert.ok(snakeCaseBridge.ranked[0].factors.metricHints.value >= 9); assert.equal(snakeCaseBridge.ranked.find(item => item.id === 'saved-workspace').lane.id, 'park'); assert.equal(snakeCaseBridge.handoff.readiness.status, 'ready'); assert.deepEqual(snakeCaseBridge.handoff.warnings, []); const nextStepsAliasResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_next_steps_aliases', originalPrompt: 'Scattermind exported next_steps / recommended_next_steps rather than nextActions.', idea: 'Ranker should keep schema-light continuation exports rankable without asking Scattermind to rename step fields.', mode: 'mvp', context: { targetAudience: 'Tired non-AI-native solo builder', nonGoals: ['Avoid saved workspaces before the first proof'], }, concept_map: { next_steps: [ { id: 'manual-step-preview', next_step: 'Manual step preview', why: 'Turn one Concept Map into a defended first move.', evidence_needed: 'Can one tired user explain the first move?', suggested_lane: 'do-first', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'copyable-followup', recommended_next_step: 'Copyable follow-up brief', why: 'Let the build order survive outside Ranker.', evidence_needed: 'Does the brief preserve reason and source?', suggested_lane: 'validate-next' }, ], recommended_next_steps: [], parking_lot: [ { id: 'saved-workspace', next_step: 'Saved workspace dashboard', why: 'Accounts and saved projects for every idea.', evidence_needed: 'No proof yet.', suggested_lane: 'park' }, ], }, }), }); assert.equal(nextStepsAliasResponse.status, 200); const nextStepsAlias = await nextStepsAliasResponse.json(); assert.equal(nextStepsAlias.input.optionCount, 3); assert.equal(nextStepsAlias.ranked[0].id, 'manual-step-preview'); assert.equal(nextStepsAlias.ranked[0].title, 'Manual step preview'); assert.equal(nextStepsAlias.ranked[0].provenance.sourceSection, 'concept-map.nextActions'); assert.equal(nextStepsAlias.ranked.find(item => item.id === 'copyable-followup').title, 'Copyable follow-up brief'); assert.equal(nextStepsAlias.ranked.find(item => item.id === 'copyable-followup').lane.id, 'test'); assert.equal(nextStepsAlias.ranked.find(item => item.id === 'saved-workspace').lane.id, 'park'); assert.deepEqual(nextStepsAlias.handoff.warnings, []); const recommendedActionsAliasResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_recommended_actions_aliases', originalPrompt: 'Scattermind exported recommended_actions instead of next_actions.', idea: 'Ranker should treat recommendation-shaped Concept Map actions as candidates without making Scattermind rename its product copy.', mode: 'mvp', context: { targetAudience: 'Tired non-AI-native solo builder', nonGoals: ['Avoid saved workspaces before a source-traced build order works'], }, concept_map: { recommended_actions: [ { id: 'recommended-manual-preview', action: 'Recommended manual preview', why: 'Turn the Concept Map into one defended build order result.', evidence_needed: 'Can one tired user explain the first move?', suggested_lane: 'do-first', source_item_id: 'recommended-action-1', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'recommended-copy', action: 'Recommended copyable handoff', why: 'Keep the defended order portable.', evidence_needed: 'Does the copied handoff preserve source and rule?', suggested_lane: 'validate-next', source_item_id: 'recommended-action-2' }, ], suggested_actions: [], parking_lot: [ { id: 'recommended-workspace', action: 'Recommended saved workspace', why: 'Saved account dashboard for every clarified idea.', evidence_needed: 'No proof yet.', suggested_lane: 'park', source_item_id: 'recommended-park-1' }, ], }, }), }); assert.equal(recommendedActionsAliasResponse.status, 200); const recommendedActionsAlias = await recommendedActionsAliasResponse.json(); assert.equal(recommendedActionsAlias.input.optionCount, 3); assert.equal(recommendedActionsAlias.ranked[0].id, 'recommended-manual-preview'); assert.equal(recommendedActionsAlias.ranked[0].provenance.sourceSection, 'concept-map.nextActions'); assert.equal(recommendedActionsAlias.ranked[0].provenance.sourceId, 'recommended-action-1'); assert.equal(recommendedActionsAlias.ranked.find(item => item.id === 'recommended-copy').lane.id, 'test'); assert.equal(recommendedActionsAlias.ranked.find(item => item.id === 'recommended-workspace').lane.id, 'park'); assert.equal(recommendedActionsAlias.handoff.readiness.status, 'ready'); assert.deepEqual(recommendedActionsAlias.handoff.warnings, []); const summaryGuardrailResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'context_summary_guardrails', originalPrompt: 'Scattermind exported guardrails in context summaries rather than explicit nonGoals arrays.', mode: 'mvp', context: { summary: 'Solo builder. Manual proof first. No account dashboards or saved workspaces before the first useful result.', targetAudience: 'Tired non-AI-native solo builder', }, conceptMap: { context: { summary: 'Avoid billing, auth, and collaboration until the bridge proves one defended build order.', }, nextActions: [ { id: 'manual-summary-proof', action: 'Manual summary-context build order preview', why: 'Show one defended first move from a Concept Map.', evidenceNeeded: 'Can one tired user name the first move?', suggestedLane: 'do-first', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'workspace-summary', action: 'Saved workspace and account dashboard', why: 'Auth-backed saved projects and collaboration for every idea.', evidenceNeeded: 'No bridge proof yet.', rankerHints: { value: 10, effort: 1, confidence: 10, urgency: 10, risk: 1 } }, { id: 'billing-summary', action: 'Billing and subscription admin', why: 'Checkout, invoices, plans, and account controls.', evidenceNeeded: 'No buyer proof yet.', rankerHints: { value: 10, effort: 1, confidence: 10, urgency: 10, risk: 1 } }, ], }, }), }); assert.equal(summaryGuardrailResponse.status, 200); const summaryGuardrail = await summaryGuardrailResponse.json(); assert.ok(summaryGuardrail.input.decisionContext.nonGoals.includes('No account dashboards or saved workspaces before the first useful result')); assert.ok(summaryGuardrail.input.decisionContext.nonGoals.includes('Avoid billing, auth, and collaboration until the bridge proves one defended build order')); assert.equal(summaryGuardrail.ranked[0].id, 'manual-summary-proof'); assert.equal(summaryGuardrail.ranked.find(item => item.id === 'workspace-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, []); 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, []); const directEnvelopeSectionsResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'scattermind-ranker-bridge-v1', rankReady: { schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', reference_code: 'SM-DIRECT-ENV-1', working_name: 'Direct envelope sections', ideaText: 'Scattermind wrapped the Ranker handoff but put the lanes directly under the envelope.', context: { targetAudience: 'Tired non-AI-native maker', constraints: ['Use the source artifact before building UI layers'], nonGoals: ['Avoid account dashboard before the first manual proof'], }, next_actions: [ { id: 'direct-envelope-preview', next_step: 'Direct envelope preview', why: 'Rank one wrapped next_actions array without requiring a candidateSet wrapper.', evidence_needed: 'Can a direct envelope become a traceable Do first item?', suggested_lane: 'do-first', source_item_id: 'direct-next-1', source_section: 'rankReady.next_actions', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, ], validate_next: [ { id: 'direct-envelope-copy', next_step: 'Direct envelope copyable handoff', why: 'Keep the decision portable.', evidence_needed: 'Does copyable text preserve direct envelope source?', source_item_id: 'direct-test-1', source_section: 'rankReady.validate_next' }, ], parking_lot: [ { id: 'direct-envelope-dashboard', next_step: 'Direct envelope account dashboard', why: 'Saved workspaces, auth, and dashboards before proof.', evidence_needed: 'No proof yet.', source_item_id: 'direct-park-1', source_section: 'rankReady.parking_lot' }, ], }, }), }); assert.equal(directEnvelopeSectionsResponse.status, 200); const directEnvelopeSections = await directEnvelopeSectionsResponse.json(); assert.equal(directEnvelopeSections.input.provenance.artifactId, 'SM-DIRECT-ENV-1'); assert.equal(directEnvelopeSections.input.optionCount, 3); assert.equal(directEnvelopeSections.ranked[0].id, 'direct-envelope-preview'); assert.equal(directEnvelopeSections.ranked[0].provenance.sourceSection, 'rankReady.next_actions'); assert.equal(directEnvelopeSections.ranked.find(item => item.id === 'direct-envelope-copy').lane.id, 'test'); assert.equal(directEnvelopeSections.ranked.find(item => item.id === 'direct-envelope-copy').lane.source, 'hint'); assert.equal(directEnvelopeSections.ranked.find(item => item.id === 'direct-envelope-dashboard').lane.id, 'park'); assert.equal(directEnvelopeSections.handoff.itemTrace.find(item => item.id === 'direct-envelope-copy').sourceId, 'direct-test-1'); assert.equal(directEnvelopeSections.handoff.readiness.status, 'ready'); assert.deepEqual(directEnvelopeSections.handoff.warnings, []); const softDirectLaneAliasesResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'scattermind-ranker-bridge-v1', rankReady: { schema: 'prioritix-feature-set-v1', sourceName: 'Scattermind', reference_code: 'SM-SOFT-LANES-1', working_name: 'Soft direct lane labels', ideaText: 'Scattermind used human-friendly direct lane labels rather than a buildOrder wrapper.', context: { targetAudience: 'Tired non-AI-native maker', constraints: ['Keep the bridge action-first'], avoid: ['Avoid saved workspaces before manual proof'], }, continueFirst: [ { id: 'soft-continue-proof', move: 'Soft-labelled continuation proof', why: 'Accept Continue first as the active build-order lane without asking Scattermind for harsher copy.', evidenceNeeded: 'Can one soft-labelled export produce a Do first lane?', sourceItemId: 'soft-do-1', sourceSection: 'rankReady.continueFirst', rankerHints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, ], evidenceNext: [ { id: 'soft-evidence-copy', move: 'Soft-labelled evidence brief', why: 'Preserve Evidence next as Validate next.', evidenceNeeded: 'Does the handoff keep the softer source label traceable?', sourceItemId: 'soft-test-1', sourceSection: 'rankReady.evidenceNext' }, ], holdForLater: [ { id: 'soft-later-export', move: 'Soft-labelled later export polish', why: 'Nice after proof, but not first.', evidenceNeeded: 'Does polish matter after the first proof?', sourceItemId: 'soft-defer-1', sourceSection: 'rankReady.holdForLater' }, ], setAside: [ { id: 'soft-saved-workspace', move: 'Soft-labelled saved workspace dashboard', why: 'Accounts and saved projects before proof.', evidenceNeeded: 'No proof yet.', sourceItemId: 'soft-park-1', sourceSection: 'rankReady.setAside' }, ], }, }), }); assert.equal(softDirectLaneAliasesResponse.status, 200); const softDirectLaneAliases = await softDirectLaneAliasesResponse.json(); assert.equal(softDirectLaneAliases.input.provenance.artifactId, 'SM-SOFT-LANES-1'); assert.equal(softDirectLaneAliases.input.optionCount, 4); assert.equal(softDirectLaneAliases.ranked[0].id, 'soft-continue-proof'); assert.equal(softDirectLaneAliases.ranked[0].lane.id, 'do'); assert.equal(softDirectLaneAliases.ranked.find(item => item.id === 'soft-evidence-copy').lane.id, 'test'); assert.equal(softDirectLaneAliases.ranked.find(item => item.id === 'soft-evidence-copy').lane.source, 'hint'); assert.equal(softDirectLaneAliases.ranked.find(item => item.id === 'soft-later-export').lane.id, 'defer'); assert.equal(softDirectLaneAliases.ranked.find(item => item.id === 'soft-saved-workspace').lane.id, 'park'); assert.equal(softDirectLaneAliases.handoff.itemTrace.find(item => item.id === 'soft-saved-workspace').sourceSection, 'rankReady.setAside'); assert.equal(softDirectLaneAliases.handoff.readiness.status, 'ready'); assert.deepEqual(softDirectLaneAliases.handoff.warnings, []); const threadsFallbackResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reference_code: 'SM-THREADS-1', working_name: 'Thread-only Concept Map', opening_reflection: 'Scattermind produced action threads but the Build Order lens did not use labels.', lenses: { risk: 'Avoid saved workspaces, accounts, and dashboards before the thread proof works.', channel: 'These notes discuss sequence, but they do not contain explicit Build first / Test manually labels.', }, threads_to_hold: [ 'Manual thread proof: turn one Concept Map into a source-traced build order preview for a tired user.', 'Validate copyable handoff by asking one user whether the copied brief tells them what to do next.', 'Defer export polish until the first proof says the handoff is understandable.', 'Probably noise: saved workspace dashboard with accounts and collaboration before proof.', ], mode: 'mvp', }), }); assert.equal(threadsFallbackResponse.status, 200); const threadsFallback = await threadsFallbackResponse.json(); assert.equal(threadsFallback.input.provenance.artifactId, 'SM-THREADS-1'); assert.equal(threadsFallback.input.optionCount, 4); assert.equal(threadsFallback.ranked[0].id, 'action-thread-1'); assert.equal(threadsFallback.ranked[0].provenance.sourceSection, 'threadsToHold'); assert.match(threadsFallback.ranked[0].factors.evidenceNeeded, /smallest real-world signal|Manual thread proof/i); assert.equal(threadsFallback.ranked.find(item => item.id === 'action-thread-3').lane.id, 'defer'); assert.equal(threadsFallback.ranked.find(item => item.id === 'action-thread-4').lane.id, 'park'); assert.equal(threadsFallback.handoff.readiness.status, 'ready'); assert.deepEqual(threadsFallback.handoff.warnings, []); const pastedThreadOnlyResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idea: `Scattermind export:\n\n\`\`\`json\n${JSON.stringify({ sourceSummary: 'A source-summary-only Concept Map paste with action threads and no explicit reference code.', actionThreads: [ 'Start with a manual source-summary proof for one tired user.', 'Validate whether the copied handoff tells the user what to do next.', 'Hold for later: polished export styling after comprehension proof.', 'Set aside: account dashboard with saved workspaces before proof.', ], })}\n\`\`\``, context: 'Avoid account dashboards and saved workspaces before manual proof.', mode: 'mvp', }), }); assert.equal(pastedThreadOnlyResponse.status, 200); const pastedThreadOnly = await pastedThreadOnlyResponse.json(); assert.equal(pastedThreadOnly.input.embeddedPayloadSource, 'idea'); assert.match(pastedThreadOnly.input.provenance.sourceSummary, /source-summary-only Concept Map/); assert.equal(pastedThreadOnly.input.optionCount, 4); assert.equal(pastedThreadOnly.ranked[0].id, 'action-thread-1'); assert.equal(pastedThreadOnly.ranked.find(item => item.id === 'action-thread-4').lane.id, 'park'); assert.equal(pastedThreadOnly.handoff.readiness.status, 'ready'); assert.deepEqual(pastedThreadOnly.handoff.warnings, []); const questionsFallbackResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reference_code: 'SM-QUESTIONS-1', working_name: 'Question-only Concept Map', ideaText: 'Scattermind produced questions rather than a labelled build order; Ranker should turn those into evidence actions, not fake features.', context: 'Tired solo operator. Avoid dashboards and saved workspaces before evidence.', conceptMap: { questions_to_sit_with: [ 'Can one tired user act on the first continuation move without opening a workspace?', { question: 'Would a copyable handoff preserve enough source context to trust the order?', validationSteps: ['Paste the handoff into notes and ask one user what they would do next.'] }, 'Should billing wait until one defended build-order handoff creates real follow-up?' ], }, mode: 'validation', }), }); assert.equal(questionsFallbackResponse.status, 200); const questionsFallback = await questionsFallbackResponse.json(); assert.equal(questionsFallback.input.provenance.artifactId, 'SM-QUESTIONS-1'); assert.equal(questionsFallback.input.optionCount, 3); assert.equal(questionsFallback.ranked[0].id, 'question-2'); assert.equal(questionsFallback.ranked[0].lane.id, 'do'); assert.equal(questionsFallback.ranked[0].provenance.sourceSection, 'concept-map.questionsToSitWith'); assert.match(questionsFallback.ranked[0].title, /^Answer:/); assert.match(questionsFallback.ranked.find(item => item.id === 'question-1').factors.evidenceNeeded, /without opening a workspace/); assert.equal(questionsFallback.ranked.find(item => item.id === 'question-1').provenance.sourceSection, 'concept-map.questionsToSitWith'); assert.equal(questionsFallback.handoff.readiness.status, 'ready'); assert.deepEqual(questionsFallback.handoff.warnings, []); const freeSnapshotResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ working_name: 'Free Snapshot Bridge', restated_idea: 'A free Scattermind Snapshot clarified a rough service idea, but it has not produced a paid Build Order yet.', lenses: { shape: { title: 'Product Shape', content: 'Start with a manual promise test for one service buyer. Do not build accounts, saved workspaces, or a dashboard before someone reacts to the offer.', }, }, questions_to_sit_with: ['Will one target buyer ask for the manual promise after seeing the short explanation?'], reference_code: 'SM-FREE-SNAPSHOT-1', tags: ['manual proof', 'buyer signal'], mode: 'mvp', }), }); assert.equal(freeSnapshotResponse.status, 200); const freeSnapshot = await freeSnapshotResponse.json(); assert.equal(freeSnapshot.input.provenance.artifactId, 'SM-FREE-SNAPSHOT-1'); assert.equal(freeSnapshot.input.provenance.snapshotTitle, 'Free Snapshot Bridge'); assert.match(freeSnapshot.input.provenance.sourceSummary, /rough service idea/); assert.equal(freeSnapshot.input.optionCount, 2); assert.equal(freeSnapshot.ranked[0].id, 'snapshot-manual-proof'); assert.equal(freeSnapshot.ranked[0].provenance.sourceSection, 'snapshot.lenses.shape'); assert.match(freeSnapshot.ranked[0].factors.evidenceNeeded, /target buyer/); assert.equal(freeSnapshot.ranked.find(item => item.id === 'question-1').lane.id, 'test'); assert.equal(freeSnapshot.handoff.readiness.status, 'ready'); assert.deepEqual(freeSnapshot.handoff.warnings, []); const storedScattermindRowResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ referenceCode: 'SM-STORED-1', ideaText: 'I paid for a Scattermind Concept Map and now want the actual stored row ranked without hand-copying lenses.', context: 'Solo operator. Manual proof first. Avoid account dashboards and saved workspaces before one user acts.', mode: 'mvp', fullReadingJson: JSON.stringify({ working_name: 'Stored Row Bridge', opening_reflection: 'The paid Concept Map says the continuation engine should produce one active next move, not a generic dashboard.', lenses: { risk: { title: 'What Can Mislead You', content: 'Avoid account dashboards and saved workspaces before one user acts. Do not build billing or collaboration yet.' }, channel: { title: 'Build Order', content: 'Build first: Stored-row build-order preview - rank the paid Concept Map directly from its saved fullReadingJson. Test manually: Copyable stored-row handoff - paste the decision brief into notes and ask one tired user what to do next. Defer: Result visual polish after the handoff proof. Probably noise: Account dashboard with saved workspaces, billing, and collaboration.' }, }, threads_to_hold: ['Manual proof remains the active slice.', 'Do not let this become a dashboard.'], questions_to_sit_with: ['Can the user act on the first move without opening a workspace?'], closing_note: 'Start with the stored-row build-order preview.', reference_code: 'SM-STORED-1', }), }), }); assert.equal(storedScattermindRowResponse.status, 200); const storedScattermindRow = await storedScattermindRowResponse.json(); assert.equal(storedScattermindRow.input.provenance.artifactId, 'SM-STORED-1'); assert.equal(storedScattermindRow.input.provenance.snapshotTitle, 'Stored Row Bridge'); assert.match(storedScattermindRow.input.provenance.originalPrompt, /actual stored row ranked/); assert.equal(storedScattermindRow.input.optionCount, 4); assert.equal(storedScattermindRow.ranked[0].id, 'build-order-1'); assert.equal(storedScattermindRow.ranked[0].provenance.sourceTitle, 'Build Order'); assert.match(storedScattermindRow.ranked[0].provenance.sourceQuote, /Stored-row build-order preview/); assert.ok(storedScattermindRow.input.decisionContext.nonGoals.includes('Avoid account dashboards and saved workspaces before one user acts')); assert.equal(storedScattermindRow.ranked.find(item => item.id === 'build-order-4').lane.id, 'park'); assert.equal(storedScattermindRow.handoff.readiness.status, 'ready'); assert.deepEqual(storedScattermindRow.handoff.warnings, []); const candidateActionsAliasResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceName: 'Scattermind', artifactId: 'concept_map_candidate_actions_aliases', originalPrompt: 'Scattermind exported candidate_actions as the rank-ready action set after a Concept Map.', idea: 'Ranker should accept candidate action set naming without making Scattermind rename it into features.', context: { targetAudience: 'Tired non-AI-native solo builder', nonGoals: ['Avoid saved workspace dashboards before the first defended action works'], }, mode: 'mvp', conceptMap: { candidate_actions: [ { id: 'candidate-manual-preview', action: 'Candidate manual preview', why: 'Turn the Concept Map into one defended active build-order slice.', evidence_needed: 'Can one tired user explain why this candidate should be first?', suggested_lane: 'do-first', source_item_id: 'candidate-action-1', source_title: 'Rank-ready candidate actions', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'candidate-copyable-handoff', action: 'Candidate copyable handoff', why: 'Make the defended order portable after the active slice is clear.', evidence_needed: 'Does the copied handoff preserve the first action and source?', suggested_lane: 'validate-next', source_item_id: 'candidate-action-2', source_title: 'Rank-ready candidate actions' }, { id: 'candidate-workspace-dashboard', action: 'Candidate saved workspace dashboard', why: 'Accounts, saved projects, collaboration, and dashboard history before proof.', evidence_needed: 'No bridge proof yet.', suggested_lane: 'park', source_item_id: 'candidate-action-3', source_title: 'Rank-ready candidate actions' }, ], }, }), }); assert.equal(candidateActionsAliasResponse.status, 200); const candidateActionsAlias = await candidateActionsAliasResponse.json(); assert.equal(candidateActionsAlias.input.optionCount, 3); assert.equal(candidateActionsAlias.ranked[0].id, 'candidate-manual-preview'); assert.equal(candidateActionsAlias.ranked[0].provenance.sourceSection, 'concept-map.candidateActions'); assert.equal(candidateActionsAlias.ranked[0].provenance.sourceId, 'candidate-action-1'); assert.equal(candidateActionsAlias.ranked[0].provenance.sourceTitle, 'Rank-ready candidate actions'); assert.ok(['test', 'defer'].includes(candidateActionsAlias.ranked.find(item => item.id === 'candidate-copyable-handoff').lane.id)); assert.equal(candidateActionsAlias.ranked.find(item => item.id === 'candidate-workspace-dashboard').lane.id, 'park'); assert.equal(candidateActionsAlias.handoff.readiness.status, 'ready'); assert.deepEqual(candidateActionsAlias.handoff.warnings, []); const rankReadyActionsEnvelopeResponse = await fetch(`${base}/api/rank-feedback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ schema: 'scattermind-ranker-bridge-v1', rank_ready: { sourceName: 'Scattermind', reference_code: 'SM-RANK-READY-ACTIONS-1', working_name: 'Rank-ready action envelope', ideaText: 'Scattermind wrapped a candidate action set under rank_ready with rank_ready_actions.', context: { targetAudience: 'Overwhelmed solo maker', avoid: ['Avoid auth dashboards before action proof'], }, rank_ready_actions: [ { id: 'rank-ready-action-proof', action: 'Rank-ready action proof', why: 'Accept the bridge naming directly and defend the first action.', evidence_needed: 'Can the action envelope produce a source-traced Do first?', suggested_lane: 'do-first', source_item_id: 'rank-ready-action-1', source_section: 'rank_ready.rank_ready_actions', ranker_hints: { value: 9, effort: 2, confidence: 8, urgency: 8, risk: 2 } }, { id: 'rank-ready-action-copy', action: 'Rank-ready action copy brief', why: 'Preserve the defended order outside the app.', evidence_needed: 'Does copyable text keep the active action clear?', suggested_lane: 'validate-next', source_item_id: 'rank-ready-action-2', source_section: 'rank_ready.rank_ready_actions' }, { id: 'rank-ready-action-dashboard', action: 'Rank-ready action dashboard', why: 'Auth dashboard and saved workspaces for every idea.', evidence_needed: 'No proof yet.', suggested_lane: 'park', source_item_id: 'rank-ready-action-3', source_section: 'rank_ready.rank_ready_actions' }, ], }, }), }); assert.equal(rankReadyActionsEnvelopeResponse.status, 200); const rankReadyActionsEnvelope = await rankReadyActionsEnvelopeResponse.json(); assert.equal(rankReadyActionsEnvelope.input.provenance.artifactId, 'SM-RANK-READY-ACTIONS-1'); assert.equal(rankReadyActionsEnvelope.input.provenance.snapshotTitle, 'Rank-ready action envelope'); assert.equal(rankReadyActionsEnvelope.input.optionCount, 3); assert.equal(rankReadyActionsEnvelope.ranked[0].id, 'rank-ready-action-proof'); assert.equal(rankReadyActionsEnvelope.ranked[0].provenance.sourceSection, 'rank_ready.rank_ready_actions'); assert.ok(['test', 'defer'].includes(rankReadyActionsEnvelope.ranked.find(item => item.id === 'rank-ready-action-copy').lane.id)); assert.equal(rankReadyActionsEnvelope.ranked.find(item => item.id === 'rank-ready-action-dashboard').lane.id, 'park'); assert.equal(rankReadyActionsEnvelope.handoff.readiness.status, 'ready'); assert.deepEqual(rankReadyActionsEnvelope.handoff.warnings, []); 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'); }