Pilot 001: Operativ checklista — inte dokument, arbetsverktyg

- Fältfas: område, varför, infrastruktur, förväntade objekt, tid, problem
- Teknisk fas: session, mission, artifacts, upload, metadata, explorer, viewer
- Beslutsfas: rätt observation, evidens, beslut, varför inte
- Utvärdering: tid, osäkerhet, automation, värde, nästa steg
- Golden Mission-knapp för att markera #0001

Mål: Kan vi gå från verklighet till verifierat Decision Case utan
manuella genvägar?

Stoppregel: Ingen ny arkitektur förrän Pilot 001 genomfört.

Next: Starta Pilot 001 — film, upload, verifiera
This commit is contained in:
Bernt
2026-07-02 16:34:49 +00:00
parent e2e3d00936
commit 4edc1d89a7
2 changed files with 207 additions and 0 deletions
+3
View File
@@ -4,6 +4,7 @@ import ArtifactViewer from './pages/ArtifactViewer';
import MissionUpload from './pages/MissionUpload'; import MissionUpload from './pages/MissionUpload';
import FieldConsole from './pages/FieldConsole'; import FieldConsole from './pages/FieldConsole';
import HealthDashboard from './pages/HealthDashboard'; import HealthDashboard from './pages/HealthDashboard';
import PilotChecklist from './pages/PilotChecklist';
function App() { function App() {
return ( return (
@@ -15,6 +16,7 @@ function App() {
<Link to="/upload">Mission Upload</Link> <Link to="/upload">Mission Upload</Link>
<Link to="/console">Field Console</Link> <Link to="/console">Field Console</Link>
<Link to="/health">Health</Link> <Link to="/health">Health</Link>
<Link to="/pilot">Pilot 001</Link>
</nav> </nav>
</header> </header>
@@ -24,6 +26,7 @@ function App() {
<Route path="/artifact/:id" element={<ArtifactViewer />} /> <Route path="/artifact/:id" element={<ArtifactViewer />} />
<Route path="/console" element={<FieldConsole />} /> <Route path="/console" element={<FieldConsole />} />
<Route path="/health" element={<HealthDashboard />} /> <Route path="/health" element={<HealthDashboard />} />
<Route path="/pilot" element={<PilotChecklist />} />
</Routes> </Routes>
</div> </div>
); );
+204
View File
@@ -0,0 +1,204 @@
/**
* Pilot Checklist
*
* Operativ checklista för fältarbete.
* Inte ett dokument — ett arbetsverktyg.
*
* Pilot 001 Mål:
* Kan vi gå från verklighet till verifierat Decision Case utan manuella genvägar?
*/
import { useState } from 'react';
interface ChecklistItem {
id: string;
label: string;
done: boolean;
notes: string;
}
const INITIAL_FIELD_ITEMS: ChecklistItem[] = [
{ id: 'area', label: 'Område besökt', done: false, notes: '' },
{ id: 'why', label: 'Varför valdes området?', done: false, notes: '' },
{ id: 'infra', label: 'Typ av infrastruktur observerad', done: false, notes: '' },
{ id: 'expected', label: 'Förväntade objekt', done: false, notes: '' },
{ id: 'duration', label: 'Tid för datainsamling', done: false, notes: '' },
{ id: 'bad', label: 'Vad fungerade dåligt?', done: false, notes: '' },
{ id: 'missing', label: 'Vad saknades i appen?', done: false, notes: '' },
];
const INITIAL_TECH_ITEMS: ChecklistItem[] = [
{ id: 'session', label: 'Field Session skapad', done: false, notes: '' },
{ id: 'mission', label: 'Mission skapad', done: false, notes: '' },
{ id: 'artifacts', label: 'Artifacts registrerade', done: false, notes: '' },
{ id: 'upload', label: 'Upload fungerade', done: false, notes: '' },
{ id: 'metadata', label: 'Metadata extraherad', done: false, notes: '' },
{ id: 'explorer', label: 'Dataset Explorer visar mission', done: false, notes: '' },
{ id: 'viewer', label: 'Artifact Viewer visar detaljer', done: false, notes: '' },
];
const INITIAL_DECISION_ITEMS: ChecklistItem[] = [
{ id: 'observation', label: 'Systemet gav rätt observation', done: false, notes: '' },
{ id: 'evidence', label: 'Tillräcklig evidens fanns', done: false, notes: '' },
{ id: 'decision', label: 'Beslut kunde fattas', done: false, notes: '' },
{ id: 'why-not', label: 'Om inte — varför?', done: false, notes: '' },
];
const INITIAL_REVIEW_ITEMS: ChecklistItem[] = [
{ id: 'time', label: 'Vad tog längst tid?', done: false, notes: '' },
{ id: 'uncertain', label: 'Var blev vi osäkra?', done: false, notes: '' },
{ id: 'auto', label: 'Vilket moment borde automatiseras?', done: false, notes: '' },
{ id: 'value', label: 'Vilket steg skapade mest värde?', done: false, notes: '' },
{ id: 'next', label: 'Vad bygger vi härnäst?', done: false, notes: '' },
];
function PilotChecklist() {
const [fieldItems, setFieldItems] = useState(INITIAL_FIELD_ITEMS);
const [techItems, setTechItems] = useState(INITIAL_TECH_ITEMS);
const [decisionItems, setDecisionItems] = useState(INITIAL_DECISION_ITEMS);
const [reviewItems, setReviewItems] = useState(INITIAL_REVIEW_ITEMS);
const toggleItem = (items: ChecklistItem[], setItems: React.Dispatch<React.SetStateAction<ChecklistItem[]>>, id: string) => {
setItems(items.map(item =>
item.id === id ? { ...item, done: !item.done } : item
));
};
const updateNote = (items: ChecklistItem[], setItems: React.Dispatch<React.SetStateAction<ChecklistItem[]>>, id: string, notes: string) => {
setItems(items.map(item =>
item.id === id ? { ...item, notes } : item
));
};
const progress = (items: ChecklistItem[]) =>
Math.round((items.filter(i => i.done).length / items.length) * 100);
return (
<div>
<h2>Pilot 001 Checklist</h2>
<p style={{ color: '#666', marginBottom: 20 }}>
Mål: Kan vi från verklighet till verifierat Decision Case utan manuella genvägar?
</p>
<Section
title="Fältfas"
progress={progress(fieldItems)}
items={fieldItems}
onToggle={id => toggleItem(fieldItems, setFieldItems, id)}
onNote={(id, notes) => updateNote(fieldItems, setFieldItems, id, notes)}
/>
<Section
title="Teknisk fas"
progress={progress(techItems)}
items={techItems}
onToggle={id => toggleItem(techItems, setTechItems, id)}
onNote={(id, notes) => updateNote(techItems, setTechItems, id, notes)}
/>
<Section
title="Beslutsfas"
progress={progress(decisionItems)}
items={decisionItems}
onToggle={id => toggleItem(decisionItems, setDecisionItems, id)}
onNote={(id, notes) => updateNote(decisionItems, setDecisionItems, id, notes)}
/>
<Section
title="Utvärdering"
progress={progress(reviewItems)}
items={reviewItems}
onToggle={id => toggleItem(reviewItems, setReviewItems, id)}
onNote={(id, notes) => updateNote(reviewItems, setReviewItems, id, notes)}
/>
<div style={{ marginTop: 20, padding: 16, background: '#f0f0f0', borderRadius: 8 }}>
<h3>Golden Mission</h3>
<p>Markera första riktiga videon som Golden Mission #0001</p>
<button style={{
padding: '12px 24px',
background: '#ffd700',
border: 'none',
borderRadius: 8,
cursor: 'pointer',
fontWeight: 'bold',
}}>
Markera som Golden Mission
</button>
</div>
</div>
);
}
function Section({
title,
progress,
items,
onToggle,
onNote,
}: {
title: string;
progress: number;
items: ChecklistItem[];
onToggle: (id: string) => void;
onNote: (id: string, notes: string) => void;
}) {
return (
<div style={{ marginBottom: 24 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
<h3 style={{ margin: 0 }}>{title}</h3>
<span style={{
padding: '4px 12px',
background: progress === 100 ? '#32cd32' : '#1e90ff',
color: 'white',
borderRadius: 12,
fontSize: 12,
fontWeight: 'bold',
}}>
{progress}%
</span>
</div>
<div style={{ display: 'grid', gap: 8 }}>
{items.map(item => (
<div key={item.id} style={{
border: '1px solid #ccc',
padding: 12,
borderRadius: 8,
display: 'grid',
gap: 8,
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<input
type="checkbox"
checked={item.done}
onChange={() => onToggle(item.id)}
style={{ width: 20, height: 20 }}
/>
<span style={{
textDecoration: item.done ? 'line-through' : 'none',
color: item.done ? '#999' : '#333',
}}>
{item.label}
</span>
</div>
<input
type="text"
placeholder="Anteckningar..."
value={item.notes}
onChange={e => onNote(item.id, e.target.value)}
style={{
padding: 8,
border: '1px solid #ddd',
borderRadius: 4,
fontSize: 14,
}}
/>
</div>
))}
</div>
</div>
);
}
export default PilotChecklist;