From efb77d0bab69fb7898df0ddff6c20fc3c510e0e8 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Sat, 9 May 2026 20:26:22 +0200 Subject: [PATCH] feat: clean v0.1 scope navigation --- src/App.tsx | 103 +++++++++++++++++++++++++-------------------- src/index.css | 36 ++++++++++++++++ src/store/types.ts | 2 +- 3 files changed, 95 insertions(+), 46 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9f0bef5..d196a9a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -82,7 +82,7 @@ function App() { const [syncStatus, setSyncStatus] = useState<'connecting' | 'synced' | 'pending' | 'syncing' | 'degraded'>('connecting') const [lastSyncedAt, setLastSyncedAt] = useState(null) const [syncAction, setSyncAction] = useState<'idle' | 'refreshing' | 'pushing'>('idle') - const [selectedFunctionalityTitle, setSelectedFunctionalityTitle] = useState('Project Cockpit') + const [selectedStatusCardTitle, setSelectedStatusCardTitle] = useState('Project Cockpit') const hasHydratedRemote = useRef(false) const initialLocalStateRef = useRef(appState) @@ -613,7 +613,7 @@ function App() { const currentFeatureCount = groupedFeatures.now.length const recentPulsePreview = [...appState.pulses].sort((a, b) => b.timestamp.localeCompare(a.timestamp)).slice(0, 3) const completedFeatureCount = groupedFeatures.done.length - const functionalityCards = [ + const statusCards = [ { title: 'Project Cockpit', status: 'live', @@ -621,7 +621,7 @@ function App() { signal: appState.project.current_goal ? 'Goal set' : 'Needs current goal', metric: appState.project.name, action: 'Edit summary', - tab: 'functionalities' as TabKey, + tab: 'status' as TabKey, operatorNote: 'Use this when the project starts drifting and the cockpit needs a clean north star again.', evidence: ['Project summary fields are editable inline.', 'Hero stats reflect live feature, parking, and pulse counts.', 'Current goal is always visible in the page header.'], next: 'Add an inline “goal changed” pulse when the current goal is edited.', @@ -677,17 +677,17 @@ function App() { { title: 'Appwrite Sync', status: backendMode === 'appwrite' && syncStatus === 'synced' ? 'live' : syncStatus === 'degraded' ? 'degraded' : 'syncing', - description: 'State persists through the Appwrite runtime document, with explicit refresh and force-sync controls for operator recovery.', + description: 'Infrastructure sync persists the local cockpit state to the Appwrite runtime document without becoming the product center.', signal: backendMode === 'appwrite' ? `Sync status: ${syncStatus}` : 'Local cache fallback active', metric: backendMode === 'appwrite' ? 'Appwrite' : 'cache', action: 'Refresh state', - tab: 'functionalities' as TabKey, - operatorNote: 'Use this when browser state and backend truth need to be reconciled deliberately.', + tab: 'status' as TabKey, + operatorNote: 'Use this only for operator recovery when browser state and backend truth need to be reconciled deliberately.', evidence: ['Public health endpoint reports backend=appwrite.', 'Refresh from backend pulls the Appwrite document into local state.', 'Force sync now pushes the current cockpit state back to Appwrite.'], next: 'Expose last successful pull/push direction as sync provenance.', }, ] - const selectedFunctionality = functionalityCards.find((card) => card.title === selectedFunctionalityTitle) ?? functionalityCards[0] + const selectedStatusCard = statusCards.find((card) => card.title === selectedStatusCardTitle) ?? statusCards[0] const backendLabel = backendMode === 'appwrite' ? 'Appwrite backend · Unraid server' : backendMode === 'connecting' ? 'Connecting to Appwrite…' : 'Local cache fallback' const syncLabel = @@ -743,24 +743,15 @@ function App() { -
-
- - {backendLabel} - - - {syncLabel} - +
+ +
@@ -801,9 +792,6 @@ function App() {
- @@ -818,12 +806,12 @@ function App() {
- {activeTab === 'functionalities' && ( + {activeTab === 'status' && (
-

Functionalities

-

The living map of what BuildPulse actually does right now — no brochure fog, no phantom roadmap theatre.

+

System Status

+

Secondary infrastructure view: what exists, what is parked, and whether sync is healthy. The product center stays Feature Plan, Parking Lot, Pulse Log, and Export.

NPM live @@ -834,17 +822,16 @@ function App() {
-

Capability map

-

{appState.project.name} is a pulse-compatible feature cockpit.

+

Secondary status

+

{appState.project.name} is a local-first v0.1 cockpit with Appwrite sync support.

- It keeps the product thread visible: define the mission, shape features, park distractions, log movement, sync state, - and hand clean context to AI agents without turning the app into a bloated command bunker. + 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.

- Live functions - {functionalityCards.filter((card) => card.status === 'live' || card.status === 'active').length} + v0.1 screens + {statusCards.filter((card) => card.status === 'live' || card.status === 'active').length}
Operator recovery @@ -857,8 +844,34 @@ function App() {
+
+
+
+

Infrastructure / Dev

+

Appwrite sync controls

+

Available for recovery and verification, deliberately kept out of the primary product flow.

+
+
+
+ + {backendLabel} + + + {syncLabel} + +
+
+ + +
+
+
- {functionalityCards.map((card) => ( + {statusCards.map((card) => (
@@ -871,7 +884,7 @@ function App() {
{card.signal}
-
diff --git a/src/index.css b/src/index.css index dfd0fd8..ed093bf 100644 --- a/src/index.css +++ b/src/index.css @@ -1118,3 +1118,39 @@ body { max-width: 100%; } } + +.secondary-nav { + display: flex; + justify-content: space-between; + align-items: center; + gap: 0.85rem; + padding: 0.75rem 0.9rem; + border-style: dashed; +} + +.secondary-nav p { + margin: 0.2rem 0 0; + color: #9fb0c9; + font-size: 0.9rem; +} + +.active-secondary { + border-color: rgba(103, 232, 249, 0.55); + color: #e5fbff; + background: rgba(34, 211, 238, 0.12); +} + +.infrastructure-panel { + border-style: dashed; +} + +.infrastructure-panel .button-inline-row { + margin-top: 0.85rem; +} + +@media (max-width: 720px) { + .secondary-nav { + align-items: stretch; + flex-direction: column; + } +} diff --git a/src/store/types.ts b/src/store/types.ts index f1edf6c..ef19504 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -99,4 +99,4 @@ export interface AppState { settings: Settings } -export type TabKey = 'functionalities' | 'feature-plan' | 'parking-lot' | 'pulse-log' | 'export' +export type TabKey = 'status' | 'feature-plan' | 'parking-lot' | 'pulse-log' | 'export'