feat: add focused handoff shortcuts
This commit is contained in:
+36
-7
@@ -1203,15 +1203,31 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
const copySessionPrompt = async () => {
|
||||
const copyFocusedHandoff = async (featureId?: string, target = promptTarget) => {
|
||||
const resolvedFeatureId = featureId ?? selectedFeature?.id ?? (promptFeatureId || groupedFeatures.now[0]?.id)
|
||||
const prompt = createAgentSessionPrompt(appState, {
|
||||
featureId: resolvedFeatureId || undefined,
|
||||
target,
|
||||
})
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(sessionPrompt)
|
||||
setStatusMessage('AI session prompt copied to clipboard.')
|
||||
await navigator.clipboard.writeText(prompt)
|
||||
if (resolvedFeatureId) {
|
||||
setPromptFeatureId(resolvedFeatureId)
|
||||
}
|
||||
setPromptTarget(target)
|
||||
|
||||
const feature = resolvedFeatureId ? appState.features.find((entry) => entry.id === resolvedFeatureId) : null
|
||||
setStatusMessage(feature ? `Focused AI handoff for “${feature.title}” copied.` : 'Focused AI handoff copied.')
|
||||
} catch {
|
||||
setStatusMessage('Clipboard copy failed. Browser said no.')
|
||||
}
|
||||
}
|
||||
|
||||
const copySessionPrompt = async () => {
|
||||
await copyFocusedHandoff(promptFeatureId || undefined, promptTarget)
|
||||
}
|
||||
|
||||
const handleImport = async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0]
|
||||
if (!file) return
|
||||
@@ -1307,7 +1323,7 @@ function App() {
|
||||
tab: 'export' as TabKey,
|
||||
operatorNote: 'Use this when another agent or coding session needs clean context without archaeology.',
|
||||
evidence: ['JSON export preserves full app state.', 'JSONL export carries pulse history.', 'Markdown package includes agent-facing project, feature, parking, pulse, and context files.'],
|
||||
next: 'Add a “copy focused handoff” button directly on each capability detail.',
|
||||
next: 'Add target-specific prompt presets so OpenClaw, Codex, and Claude get sharper default briefs.',
|
||||
},
|
||||
{
|
||||
title: 'Appwrite Sync',
|
||||
@@ -1339,7 +1355,7 @@ function App() {
|
||||
<div className="app-shell">
|
||||
<header className="mobile-shell-header card">
|
||||
<div>
|
||||
<p className="eyebrow">BuildPulse v0.3.0</p>
|
||||
<p className="eyebrow">BuildPulse v0.3.1</p>
|
||||
<h1>{appState.project.name}</h1>
|
||||
<p className="hero-goal compact-goal">
|
||||
<strong>Current goal:</strong> {appState.project.current_goal || 'Classify new ideas before they become work.'}
|
||||
@@ -1667,6 +1683,9 @@ function App() {
|
||||
<button type="button" className="ghost small" onClick={() => openFeatureHandoff(selectedFeature.id)}>
|
||||
Prepare AI Handoff
|
||||
</button>
|
||||
<button type="button" className="ghost small" onClick={() => void copyFocusedHandoff(selectedFeature.id, 'OpenClaw')}>
|
||||
Copy AI Handoff
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1939,7 +1958,7 @@ function App() {
|
||||
<section className="card functionality-hero">
|
||||
<div>
|
||||
<p className="eyebrow">Secondary status</p>
|
||||
<h3>{appState.project.name} is now a local-first v0.3 cockpit with Appwrite sync and release-planning structure.</h3>
|
||||
<h3>{appState.project.name} is now a local-first v0.3 cockpit with Appwrite sync, release-planning structure, and faster handoff prep.</h3>
|
||||
<p>
|
||||
The planning loop works from browser storage first, then syncs to Appwrite for the deployed Unraid runtime. If sync degrades, the cockpit should still stay usable locally.
|
||||
</p>
|
||||
@@ -2029,7 +2048,17 @@ function App() {
|
||||
<h3>{selectedStatusCard.title}</h3>
|
||||
<p>{selectedStatusCard.operatorNote}</p>
|
||||
</div>
|
||||
<span className={`pill functionality-${selectedStatusCard.status}`}>{selectedStatusCard.status}</span>
|
||||
<div className="button-inline-row">
|
||||
{selectedStatusCard.title === 'AI Handoff + Export' && (
|
||||
<button type="button" className="ghost small" onClick={() => void copyFocusedHandoff(undefined, 'OpenClaw')}>
|
||||
Copy Focused Handoff
|
||||
</button>
|
||||
)}
|
||||
<button type="button" className="ghost small" onClick={() => setActiveTab(selectedStatusCard.tab)}>
|
||||
{selectedStatusCard.action}
|
||||
</button>
|
||||
<span className={`pill functionality-${selectedStatusCard.status}`}>{selectedStatusCard.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="functionality-detail-grid">
|
||||
<article>
|
||||
|
||||
@@ -10,7 +10,7 @@ export const createSeedState = (): AppState => ({
|
||||
one_line_pitch: 'A calm planning cockpit for AI-assisted product building.',
|
||||
description:
|
||||
'BuildPulse helps capture features, park distracting ideas, log progress as Pulse events, and export clean context for AI coding agents.',
|
||||
current_goal: 'Ship v0.3 with Phases, Releases, and clear release-readiness signals.',
|
||||
current_goal: 'Sharpen v0.4 handoff workflows so coding agents get the right context fast.',
|
||||
notes: 'First dogfood project: BuildPulse manages BuildPulse.',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
@@ -40,9 +40,9 @@ export const createSeedState = (): AppState => ({
|
||||
id: 'phase_structured_release_planning',
|
||||
title: 'Phase 3: Structured Release Planning',
|
||||
goal: 'Make releases concrete: what is required, what is forbidden, and how close the build is to ready.',
|
||||
status: 'active',
|
||||
status: 'done',
|
||||
order: 3,
|
||||
notes: 'This is the v0.3 step.',
|
||||
notes: 'v0.3 shipped with phases, releases, and readiness signals.',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
},
|
||||
@@ -50,9 +50,9 @@ export const createSeedState = (): AppState => ({
|
||||
id: 'phase_session_handoff',
|
||||
title: 'Phase 4: Session Handoff',
|
||||
goal: 'Give agents cleaner, more targeted context packages for implementation sessions.',
|
||||
status: 'upcoming',
|
||||
status: 'active',
|
||||
order: 4,
|
||||
notes: 'Planned v0.4 direction.',
|
||||
notes: 'Current v0.4 step: faster, more focused handoff workflows for coding sessions.',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
},
|
||||
@@ -118,13 +118,50 @@ export const createSeedState = (): AppState => ({
|
||||
'Local/cloud model router',
|
||||
'Session prompt generator',
|
||||
],
|
||||
status: 'shipped',
|
||||
notes: 'Shipped. Release planning structure is live; still no live integrations.',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
},
|
||||
{
|
||||
id: 'release_v040_focused_handoffs',
|
||||
phase_id: 'phase_session_handoff',
|
||||
name: 'v0.4 — Focused Session Handoffs',
|
||||
goal: 'Cut the friction between choosing a feature and giving a coding agent a sharp, minimal brief.',
|
||||
definition_of_done: [
|
||||
'Feature detail includes a one-click copy handoff action.',
|
||||
'Status detail can copy a focused handoff without detouring through export archaeology.',
|
||||
'Prompt generation still respects release, phase, parking-lot, and recent-pulse guardrails.',
|
||||
],
|
||||
required_feature_ids: ['export_screen', 'feature_focused_handoff_shortcuts'],
|
||||
optional_feature_ids: ['pulse_log_screen'],
|
||||
forbidden_feature_titles: ['Live OpenClaw/Hermes Agent Status', 'WebSocket agent telemetry', 'GitHub / Gitea sync'],
|
||||
status: 'in_progress',
|
||||
notes: 'Keep this on planning structure only. No live integrations yet.',
|
||||
notes: 'First concrete v0.4 slice before deeper prompt presets or session templates.',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
},
|
||||
],
|
||||
features: [
|
||||
{
|
||||
id: 'feature_focused_handoff_shortcuts',
|
||||
title: 'Focused handoff shortcuts',
|
||||
description: 'Let operators copy a sharp AI handoff directly from feature and status detail surfaces.',
|
||||
column: 'now',
|
||||
priority: 'must',
|
||||
status: 'building',
|
||||
acceptance_criteria: [
|
||||
'Feature detail includes a one-click copy handoff action.',
|
||||
'Status detail can copy a focused handoff without navigating the whole Export screen.',
|
||||
'Copied prompt still respects the selected feature or first active Now item.',
|
||||
],
|
||||
scope_notes: 'This is the first concrete v0.4 step: less archaeology before a coding session starts.',
|
||||
phase_id: 'phase_session_handoff',
|
||||
release_id: 'release_v040_focused_handoffs',
|
||||
release_role: 'required',
|
||||
created_at: seedDate,
|
||||
updated_at: seedDate,
|
||||
},
|
||||
{
|
||||
id: 'feature_plan_screen',
|
||||
title: 'Feature Plan screen',
|
||||
|
||||
Reference in New Issue
Block a user