Accept rank-ready candidate action aliases

This commit is contained in:
OpenClaw Bot
2026-05-27 16:53:58 +02:00
parent 8bea868fb2
commit 0271bfcbf6
3 changed files with 82 additions and 1 deletions
+69 -1
View File
@@ -1414,7 +1414,75 @@ try {
assert.equal(storedScattermindRow.handoff.readiness.status, 'ready');
assert.deepEqual(storedScattermindRow.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, duplicateIds: duplicateIds.ranked.map(item => item.id), readiness: data.handoff.readiness.status, provenance: data.input.provenance, buildOrder: data.buildOrder }, null, 2));
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, []);
console.log(JSON.stringify({ ok: true, top: data.ranked[0].id, hintedTop: hinted.ranked[0].id, actionTop: actions.ranked[0].id, nestedConceptTop: nestedConcept.ranked[0].id, nonGoalTop: nonGoal.ranked[0].id, structuredContextTop: structuredContext.ranked[0].id, lensOnlyTop: lensOnly.ranked[0].id, scattermindPaidShapeTop: scattermindPaidShape.ranked[0].id, mergedContextTop: mergedContext.ranked[0].id, embeddedJsonTop: embeddedJson.ranked[0].id, fencedJsonTop: fencedJson.ranked[0].id, embeddedSnapshotTop: embeddedSnapshot.ranked[0].id, sourceExcerptTop: sourceExcerpt.ranked[0].id, snakeCaseBridgeTop: snakeCaseBridge.ranked[0].id, nextStepsAliasTop: nextStepsAlias.ranked[0].id, summaryGuardrailTop: summaryGuardrail.ranked[0].id, bridgeEnvelopeTop: bridgeEnvelope.ranked[0].id, directEnvelopeSectionsTop: directEnvelopeSections.ranked[0].id, softDirectLaneAliasesTop: softDirectLaneAliases.ranked[0].id, threadsFallbackTop: threadsFallback.ranked[0].id, questionsFallbackTop: questionsFallback.ranked[0].id, freeSnapshotTop: freeSnapshot.ranked[0].id, storedScattermindRowTop: storedScattermindRow.ranked[0].id, candidateActionsAliasTop: candidateActionsAlias.ranked[0].id, rankReadyActionsEnvelopeTop: rankReadyActionsEnvelope.ranked[0].id, duplicateIds: duplicateIds.ranked.map(item => item.id), readiness: data.handoff.readiness.status, provenance: data.input.provenance, buildOrder: data.buildOrder }, null, 2));
} finally {
server.kill('SIGTERM');
}