feat: add one-click feature handoff flow
This commit is contained in:
@@ -33,6 +33,7 @@ BuildPulse v0.1 includes:
|
|||||||
- Pulse Log screen
|
- Pulse Log screen
|
||||||
- Export screen
|
- Export screen
|
||||||
- AI session prompt export for coding-agent handoff
|
- AI session prompt export for coding-agent handoff
|
||||||
|
- One-click handoff prep from a selected feature
|
||||||
- Appwrite-backed persistence on the Unraid server
|
- Appwrite-backed persistence on the Unraid server
|
||||||
- Local cache fallback for resilience during backend hiccups
|
- Local cache fallback for resilience during backend hiccups
|
||||||
- Pulse-shaped event records
|
- Pulse-shaped event records
|
||||||
|
|||||||
@@ -192,6 +192,19 @@ Expected:
|
|||||||
- Contains recent pulses.
|
- Contains recent pulses.
|
||||||
- Is useful as an AI coder handoff.
|
- Is useful as an AI coder handoff.
|
||||||
|
|
||||||
|
### Test 5.5: Prepare AI handoff from selected feature
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open Feature Plan.
|
||||||
|
2. Select a feature.
|
||||||
|
3. Click `Prepare AI Handoff`.
|
||||||
|
4. Confirm Export view opens with the selected feature loaded into `AI_SESSION_PROMPT.md`.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Export view opens immediately.
|
||||||
|
- Prompt focus feature matches the selected feature.
|
||||||
|
- Prompt includes current goal, acceptance criteria, parking-lot guardrails, and recent relevant pulses.
|
||||||
|
|
||||||
## Manual Test Group 6 — Mobile Usability
|
## Manual Test Group 6 — Mobile Usability
|
||||||
|
|
||||||
### Test 6.1: Phone layout
|
### Test 6.1: Phone layout
|
||||||
|
|||||||
+28
@@ -279,6 +279,15 @@ function App() {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openFeatureHandoff = (featureId: string) => {
|
||||||
|
setPromptFeatureId(featureId)
|
||||||
|
setPromptTarget('OpenClaw')
|
||||||
|
setActiveTab('export')
|
||||||
|
|
||||||
|
const feature = appState.features.find((entry) => entry.id === featureId)
|
||||||
|
setStatusMessage(feature ? `Prepared AI handoff for “${feature.title}”.` : 'Prepared AI handoff prompt.')
|
||||||
|
}
|
||||||
|
|
||||||
const beginParkingEdit = (item: ParkingLotItem) => {
|
const beginParkingEdit = (item: ParkingLotItem) => {
|
||||||
setSelectedParkingId(item.id)
|
setSelectedParkingId(item.id)
|
||||||
setParkingDraft({
|
setParkingDraft({
|
||||||
@@ -601,6 +610,20 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{selectedFeature && (
|
||||||
|
<section className="card quick-actions">
|
||||||
|
<div>
|
||||||
|
<strong>{selectedFeature.title}</strong>
|
||||||
|
<p>Selected and ready. Shape it here, then kick a clean brief to your agent.</p>
|
||||||
|
</div>
|
||||||
|
<div className="button-inline-row">
|
||||||
|
<button type="button" onClick={() => openFeatureHandoff(selectedFeature.id)}>
|
||||||
|
Prepare AI Handoff
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="board-grid">
|
<div className="board-grid">
|
||||||
{FEATURE_COLUMNS.map((column) => (
|
{FEATURE_COLUMNS.map((column) => (
|
||||||
<article key={column} className="column card">
|
<article key={column} className="column card">
|
||||||
@@ -708,9 +731,14 @@ function App() {
|
|||||||
<button type="button" onClick={saveFeature}>{selectedFeature ? 'Save Changes' : 'Add Feature'}</button>
|
<button type="button" onClick={saveFeature}>{selectedFeature ? 'Save Changes' : 'Add Feature'}</button>
|
||||||
<button type="button" className="ghost" onClick={resetFeatureDraft}>Clear</button>
|
<button type="button" className="ghost" onClick={resetFeatureDraft}>Clear</button>
|
||||||
{selectedFeature && (
|
{selectedFeature && (
|
||||||
|
<>
|
||||||
|
<button type="button" className="ghost" onClick={() => openFeatureHandoff(selectedFeature.id)}>
|
||||||
|
Prepare AI Handoff
|
||||||
|
</button>
|
||||||
<button type="button" className="danger" onClick={() => deleteFeature(selectedFeature.id)}>
|
<button type="button" className="danger" onClick={() => deleteFeature(selectedFeature.id)}>
|
||||||
Delete Feature
|
Delete Feature
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Reference in New Issue
Block a user