Add route guardrails to Ranker handoff

This commit is contained in:
OpenClaw Bot
2026-05-27 19:09:29 +02:00
parent 39287ea2e3
commit bff9b1e7c3
3 changed files with 77 additions and 2 deletions
+35 -1
View File
@@ -1728,7 +1728,41 @@ try {
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));
const gameRouteGuardrailResponse = await fetch(`${base}/api/rank-feedback`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sourceName: 'Scattermind',
referenceCode: 'SM-GAME-ROUTE-1',
ideaText: 'A vehicle bullet-heaven survival game where the first proof is whether driving feel and enemy pressure are fun in a tiny arena.',
mode: 'mvp',
fullReadingJson: JSON.stringify({
working_name: 'Vehicle Hell Prototype',
opening_reflection: 'This is a game concept. The useful continuation is a playable prototype, not product-account machinery.',
lenses: {
shape: { title: 'Recommended Direction', content: 'Start with a five-minute playable arena: steering, enemy pressure, one weapon, one upgrade. The first proof is feel, not menus.' },
channel: { title: 'Build Order', content: 'Build first: Five-minute playable driving arena - one car, one enemy pattern, one weapon, and one win/loss loop. Test manually: Playtest the steering feel with 3 players. Defer: Progression upgrades after the core loop feels good. Build first: Player account dashboard with saved builds, collaboration, onboarding, and subscription tiers.' },
question: { title: 'Proof Steps', content: 'Ask players to play for five minutes and say when movement stops feeling fun.' },
},
threads_to_hold: ['Success signal: players replay once without being asked.', 'Failure signal: steering fights bullet-heaven readability.'],
questions_to_sit_with: ['Does the driving feel make dodging more fun or just harder?'],
closing_note: 'Ship the five-minute playable arena first.',
reference_code: 'SM-GAME-ROUTE-1',
}),
}),
});
assert.equal(gameRouteGuardrailResponse.status, 200);
const gameRouteGuardrail = await gameRouteGuardrailResponse.json();
assert.equal(gameRouteGuardrail.input.decisionContext.ideaRoute, 'game');
assert.ok(gameRouteGuardrail.input.decisionContext.nonGoals.some(item => /accounts, dashboards, workspaces/i.test(item)), 'game route should add anti-SaaS guardrails even if Scattermind did not spell them out as avoid text');
assert.equal(gameRouteGuardrail.ranked[0].id, 'build-order-1');
assert.equal(gameRouteGuardrail.ranked.find(item => /Player account dashboard/i.test(item.title)).lane.source, 'source-non-goal');
assert.equal(gameRouteGuardrail.handoff.decisionContext.ideaRoute, 'game');
assert.match(gameRouteGuardrail.handoff.copyableText, /Idea route: game/);
assert.equal(gameRouteGuardrail.handoff.readiness.status, 'ready');
assert.deepEqual(gameRouteGuardrail.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, gameRouteGuardrailTop: gameRouteGuardrail.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');
}