Add Rank AI-ready prompt copy button

This commit is contained in:
OpenClaw Bot
2026-05-23 22:24:08 +02:00
parent 934a29b8d2
commit d204a76802
3 changed files with 44 additions and 3 deletions
+39
View File
@@ -62,6 +62,27 @@ const sampleBacklog = {
{ title: 'AI explains why an idea moved', description: 'Every ranking should show a reason, risk, and what evidence would change the decision.', labels: ['Trust', 'AI'], impact: 9, effort: 6, confidence: 6, urgency: 8 }
]
};
const aiReadyPrompt = `You are preparing features for Rank / Prioritix, a prioritization workbench that imports Prioritix Feature Set v1 JSON. Convert my messy backlog, notes, stakeholder requests, or product ideas into valid JSON only — no markdown, no commentary.
Return this exact shape:
{
"format": "prioritix-feature-set-v1",
"name": "Short project or backlog name",
"features": [
{
"title": "Clear feature title",
"description": "Plain-language reason this feature matters and what outcome it supports.",
"labels": ["Category", "Optional second category"],
"impact": 1-10,
"effort": 1-10,
"confidence": 1-10,
"urgency": 1-10,
"notes": "Risks, assumptions, dependencies, or evidence that would change the ranking."
}
]
}
Scoring guidance: impact means user/business value, effort means delivery difficulty, confidence means how sure the evidence is, urgency means time sensitivity. Use the full 1-10 range honestly. Split vague bundles into separate features. Merge duplicates. Label polish as polish, bets as validation/research, and must-have product work as core. If evidence is weak, lower confidence rather than pretending. Keep titles short enough to scan on a card.`;
function loadSampleBacklog(){
const input = $('#featureSetInput');
if(!input) return;
@@ -69,6 +90,23 @@ function loadSampleBacklog(){
document.querySelector('#feature-sets')?.scrollIntoView({ behavior:'smooth', block:'start' });
toast('Sample backlog loaded. Import it or replace it with your own chaos.');
}
async function copyAiPrompt(){
const status = $('#aiPromptStatus');
try {
await navigator.clipboard.writeText(aiReadyPrompt);
if(status) status.textContent = 'Copied. Paste it into any AI, then paste the returned JSON back here.';
toast('AI-ready prompt copied');
} catch {
const input = $('#featureSetInput');
if(input){
input.value = aiReadyPrompt;
input.focus();
input.select();
}
if(status) status.textContent = 'Clipboard blocked — the prompt is selected in the text area for manual copy.';
toast('Clipboard blocked. Prompt selected for manual copy.');
}
}
const $ = (sel, root=document) => root.querySelector(sel);
const $$ = (sel, root=document) => Array.from(root.querySelectorAll(sel));
@@ -188,6 +226,7 @@ function openDetail(id){ const idea=state.ideas.find(i=>i.id===id); if(!idea) re
function closeDetail(){ detail.classList.remove('open'); detail.setAttribute('aria-hidden','true'); state.selected=null; }
async function archiveIdea(id=state.selected){ if(!id) return; const previous=state.ideas.find(i=>i.id===id); try{ await api(`/api/ideas/${id}`,{method:'PATCH',body:{archived:true,status:'remove'}}); state.ideas = state.ideas.filter(i=>i.id!==id); closeDetail(); render(); toast('Removed', previous ? () => undoIdea({...previous, archived:false}) : null); } catch(error){ toast(error.message); } }
$('#sampleBacklog')?.addEventListener('click', loadSampleBacklog);
$('#copyAiPrompt')?.addEventListener('click', copyAiPrompt);
$('#featureSetFile')?.addEventListener('change', async e => {
const file = e.currentTarget.files?.[0];
if(!file) return;