feat: add focused handoff shortcuts

This commit is contained in:
OpenClaw Bot
2026-05-11 12:14:19 +02:00
parent 8218a3417e
commit 204e5ee64a
4 changed files with 83 additions and 14 deletions
+3
View File
@@ -3,6 +3,9 @@
BuildPulse is a calm planning cockpit for AI-assisted product building.
It helps capture features, park distracting ideas, log progress as Pulse events, and export clean project context for AI coding agents such as Claude Code, Codex, OpenCode, OpenClaw, or future autonomous agents.
Current release line:
- v0.3.1 — faster focused-handoff prep from feature and status detail surfaces
Personal runtime target:
- `build.friborg.uk`
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "buildpulse",
"private": true,
"version": "0.3.0",
"version": "0.3.1",
"type": "module",
"scripts": {
"api": "node --env-file=../.env server/index.mjs",
+35 -6
View File
@@ -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,8 +2048,18 @@ function App() {
<h3>{selectedStatusCard.title}</h3>
<p>{selectedStatusCard.operatorNote}</p>
</div>
<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>
<h4>Proof it exists</h4>
+43 -6
View File
@@ -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',