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.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.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.equal(data.handoff.source.hasOriginalPrompt, 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.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)); 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 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 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 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')); 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'); 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, duplicateIds: duplicateIds.ranked.map(item => item.id), provenance: data.input.provenance, buildOrder: data.buildOrder }, null, 2)); } finally { server.kill('SIGTERM'); }