diff --git a/.fleet/design-review.json b/.fleet/design-review.json index 60edb999..34361780 100644 --- a/.fleet/design-review.json +++ b/.fleet/design-review.json @@ -2,7 +2,7 @@ "$schema": "fleet.design-review.v1", "version": 1, "project": "swe-interview-prep", - "target": "Four-surface Learning OS: Dashboard, Learn, Practice, and Wars with complete catalogue preservation", + "target": "Complete Fanout-inspired learning surfaces", "mode": "preserve", "register": "product", "context": { @@ -10,85 +10,91 @@ "design": "DESIGN.md" }, "direction": { - "references": [], - "probes": [], + "references": ["https://fanout.sh/", "https://learn-inference.com/"], + "probes": [ + "complete source path", + "focused resumable study", + "searchable notation", + "decision evidence", + "daily-priority integrity" + ], "selected": "existing-design", "approval": "not-required", - "before": "artifacts/design/software-wars/after-wars-1440.png" + "before": "artifacts/design/daily-learning-dashboard-1440.png" }, "evidence": { "screenshots": [ { "width": 390, - "path": "artifacts/design/final-dashboard-390.png" + "path": "artifacts/design/fanout-learn-390.png" }, { - "width": 390, - "path": "artifacts/design/final-learn-390.png" + "width": 768, + "path": "artifacts/design/fanout-learn-768.png" }, { - "width": 390, - "path": "artifacts/design/final-practice-390.png" + "width": 1440, + "path": "artifacts/design/fanout-learn-1440.png" }, { "width": 390, - "path": "artifacts/design/final-wars-390.png" + "path": "artifacts/design/fanout-inference-390.png" }, { "width": 768, - "path": "artifacts/design/final-dashboard-768.png" + "path": "artifacts/design/fanout-inference-768.png" }, { - "width": 768, - "path": "artifacts/design/final-practice-768.png" + "width": 1440, + "path": "artifacts/design/fanout-inference-1440.png" }, { - "width": 1440, - "path": "artifacts/design/final-dashboard-1440.png" + "width": 390, + "path": "artifacts/design/fanout-focused-study-390.png" }, { - "width": 1440, - "path": "artifacts/design/final-learn-1440.png" + "width": 768, + "path": "artifacts/design/fanout-focused-study-768.png" }, { "width": 1440, - "path": "artifacts/design/final-practice-1440.png" + "path": "artifacts/design/fanout-focused-study-1440.png" }, { - "width": 1440, - "path": "artifacts/design/final-practice-selector-1440.png" + "width": 390, + "path": "artifacts/design/fanout-model-routing-390.png" }, { - "width": 1440, - "path": "artifacts/design/final-wars-1440.png" + "width": 768, + "path": "artifacts/design/fanout-model-routing-768.png" }, { - "width": 390, - "path": "artifacts/design/software-wars/final-tradeoff-playground-390.png" + "width": 1440, + "path": "artifacts/design/fanout-model-routing-1440.png" }, { "width": 390, - "path": "artifacts/design/software-wars/final-tradeoff-diagram-390.png" + "path": "artifacts/design/fanout-notation-390.png" }, { "width": 768, - "path": "artifacts/design/software-wars/final-tradeoff-playground-768.png" + "path": "artifacts/design/fanout-notation-768.png" }, { "width": 1440, - "path": "artifacts/design/software-wars/final-tradeoff-playground-1440.png" + "path": "artifacts/design/fanout-notation-1440.png" } ], "projectCheck": { - "command": "vitest run; tsc --noEmit; biome check .; docs validation; generated-curriculum + production Vite build; Playwright smoke/mobile/Wars; strict OpenSpec validation", - "status": "pass" + "command": "pnpm quality", + "status": "passed" }, "critique": { - "score": 36, + "score": 37, "maximum": 40 }, "audit": { - "score": 17, + "score": 16, "maximum": 20 }, "unresolved": { @@ -97,13 +103,11 @@ }, "detector": { "posture": "advisory", - "findings": [ - "The final scoped detector ran exactly once and found one advisory legacy color literal in CodeEditor; it was aligned to the documented rose-danger token before handoff." - ] + "findings": [] } }, "ownerFeedback": { - "decision": "keep", - "note": "Owner reviewed the four-surface direction and responded: looks good, keep going. Dashboard resumes work; Learn is high-level and searchable; Practice is the existing Playground with all 298 canonical problems; Wars presents the one-minute and thirty-minute formats. Complete concept, roadmap, problem, public-curriculum, progress, and legacy routes remain visible and portable." + "decision": "pending", + "note": "" } } diff --git a/.impeccable/critique/2026-08-19T20-34-28Z__src-pages-today-tsx.md b/.impeccable/critique/2026-08-19T20-34-28Z__src-pages-today-tsx.md new file mode 100644 index 00000000..1a0a5c3f --- /dev/null +++ b/.impeccable/critique/2026-08-19T20-34-28Z__src-pages-today-tsx.md @@ -0,0 +1,54 @@ +--- +target: Evidence-driven daily learning and decision labs +total_score: 33 +max_score: 40 +na_heuristics: +p0_count: 0 +p1_count: 0 +timestamp: 2026-08-19T20-34-28Z +slug: src-pages-today-tsx +--- +Method: dual-agent critique (A: design_assessment · B: detector_assessment) + +# Evidence-driven daily learning critique + +The result is product-specific in behavior: a learner predicts, reveals deterministic evidence, records a decision receipt, and must still pass a causal explain-back before mastery changes. The visual language deliberately preserves the existing Learning OS rather than introducing a new brand system. + +## Nielsen heuristic score + +| Heuristic | Score | +| --- | ---: | +| Visibility of system status | 4 | +| Match between system and real world | 4 | +| User control and freedom | 3 | +| Consistency and standards | 4 | +| Error prevention | 3 | +| Recognition rather than recall | 4 | +| Flexibility and efficiency | 2 | +| Aesthetic and minimalist design | 3 | +| Error recovery | 3 | +| Help and documentation | 3 | +| Total | 33/40 | + +## Findings and resolution + +- P1: The evidence ladder initially called a typed but editable prediction frozen. It now completes only after reveal, and focused UI coverage verifies the transition. +- P1: A generic prediction example contradicted two lab prompts. Every decision lab now supplies a task-specific example. +- P1: Ten inference inputs formed an undifferentiated wall. They are now grouped by hardware budget, model shape, workload, and reserve, with the governing formula and assumptions available inline. +- P1: Small instructional text failed contrast guidance, the primary textarea lacked an accessible name, and the lab nested a main landmark. Contrast tokens, labels, focus rings, and landmark structure were corrected. +- P1: Editing a revealed input could silently erase an attempt. Revealed inputs now lock and an explicit new-attempt control retains the configured values while resetting staged evidence. +- Capture issue: the first desktop Labs screenshot fired before its lazy route rendered. A page-specific clean recapture proves the surface is populated at 1440px. + +No P0 or P1 findings remain. The detector ran once and returned no implementation-integrity findings. + +## Persona check + +- Power users get one direct daily action and an explicit restart path, but presets and receipt duplication remain future efficiency opportunities. +- Screen-reader and low-vision users now receive named fields, valid landmarks, stronger contrast, focus rings, required-field guidance, alerts, and live evidence state. +- Distracted mobile users get a single-column flow and explicit attempt boundaries; draft persistence before receipt creation remains a possible future improvement. + +## Questions carried forward + +- Should the Labs index eventually surface the exact lab recommended by today's priority? +- Would reusable presets materially improve repeated capacity experiments without weakening prediction-first behavior? +- Should unfinished local lab drafts survive navigation, or is a receipt the correct first durable boundary? diff --git a/PRODUCT.md b/PRODUCT.md index 8e0d1758..3a8510f0 100644 --- a/PRODUCT.md +++ b/PRODUCT.md @@ -54,6 +54,16 @@ account-scoped in the browser. public curriculum. - Every ranked Blitz question must have one explicit canonical Learn concept, authoritative sources, and authored reasoning for every answer option. +- Dashboard answers “what should I learn today?” with one deterministic + recovery, retention, or progression priority and an explicit evidence + contract before showing optional history or catalogue context. +- Decision labs, formulas, and paper contracts may produce local evidence, but + only the existing authenticated Feynman-to-FSRS path may grant mastery. +- Learn Inference is represented as a 42-section companion path that links to + the canonical book; the product stores original summaries and retrieval + prompts, not copied source bodies. +- Focused study and decision-lab drafts are account-scoped, version-aware + continuity state. Completing a draft is evidence, not mastery. - Blitz ratings and Tradeoff ratings are separate; ranked state, deadlines, answers, and match outcomes remain server-owned. - Production remains a Vite/React application on Cloudflare Pages with Pages diff --git a/PROJECT_STATUS.md b/PROJECT_STATUS.md index 6aef810d..6b17af1d 100644 --- a/PROJECT_STATUS.md +++ b/PROJECT_STATUS.md @@ -65,6 +65,7 @@ External: LeetCode API (import), multi-provider LLM APIs | Phase | Milestone | |-------|-----------| +| Fanout-inspired learning surfaces (local, 2026-08-20) | Added the complete 42-section Learn Inference companion path, searchable formula/notation reference, accessible concept topography, eight-source rotating paper programme, focused resumable study, three additional decision labs, scenario presets, and version-aware local drafts. Dashboard remains concept-first: failed practice and due retrieval still outrank progression and evidence-format selection. The size gate has since moved to per-chunk gzipped budgets on the first-load graph, which this expansion stays within. Local verification is recorded in GitHub issue #86; deployment remains separate. | | First-paint stylesheet stability (2026-08-22) | Removed the build-only asynchronous stylesheet rewrite so production CSS loads through Vite's normal blocking link. The pinned shell reset remains as a stable React handoff instead of compensating for intentionally delayed application styles. Corrected the size gate to bound the four scripts in the generated first-load graph rather than summing click-loaded curriculum documents as initial JavaScript. | | Fleet code-health baseline (2026-08-14) | Added one CI-enforced quality contract covering whole-source coverage, unused code, complexity, exact duplication, import cycles, severe advisories, suppression markers, docs, build, bundle size, and repository hygiene. Removed an orphan declaration, unused simulation helpers and public exports, and unused direct tooling dependencies; safe package updates reduced high advisories from 29 to six accepted transitive advisories. Remaining measured debt is explicit and can only move downward. | | Harness and classic system-design expansion (2026-08-13) | Added a seven-build Harness Engineering roadmap with seven practice-backed atomic concepts and two measured synthesis projects. Expanded the structured Tradeoff catalog from 20 to 33 cases with unique IDs, proximity, nearby presence, routing, queues, metrics, ad clicks, hotel reservations, email, object storage, leaderboards, wallets, and exchange matching. The generated public curriculum now contains 19 tracks, 26 roadmaps, and 259 concept pages; all 473 tests, typecheck, docs validation, source reachability, and the production build pass. | diff --git a/artifacts/design/daily-learning-capacity-planning-1440.png b/artifacts/design/daily-learning-capacity-planning-1440.png new file mode 100644 index 00000000..2bf64983 Binary files /dev/null and b/artifacts/design/daily-learning-capacity-planning-1440.png differ diff --git a/artifacts/design/daily-learning-capacity-planning-390.png b/artifacts/design/daily-learning-capacity-planning-390.png new file mode 100644 index 00000000..eef90af9 Binary files /dev/null and b/artifacts/design/daily-learning-capacity-planning-390.png differ diff --git a/artifacts/design/daily-learning-capacity-planning-768.png b/artifacts/design/daily-learning-capacity-planning-768.png new file mode 100644 index 00000000..4e948575 Binary files /dev/null and b/artifacts/design/daily-learning-capacity-planning-768.png differ diff --git a/artifacts/design/daily-learning-dashboard-1440.png b/artifacts/design/daily-learning-dashboard-1440.png new file mode 100644 index 00000000..bac36b10 Binary files /dev/null and b/artifacts/design/daily-learning-dashboard-1440.png differ diff --git a/artifacts/design/daily-learning-dashboard-390.png b/artifacts/design/daily-learning-dashboard-390.png new file mode 100644 index 00000000..f31876c8 Binary files /dev/null and b/artifacts/design/daily-learning-dashboard-390.png differ diff --git a/artifacts/design/daily-learning-dashboard-768.png b/artifacts/design/daily-learning-dashboard-768.png new file mode 100644 index 00000000..4bed0485 Binary files /dev/null and b/artifacts/design/daily-learning-dashboard-768.png differ diff --git a/artifacts/design/daily-learning-evaluation-confidence-1440.png b/artifacts/design/daily-learning-evaluation-confidence-1440.png new file mode 100644 index 00000000..6ba4edb3 Binary files /dev/null and b/artifacts/design/daily-learning-evaluation-confidence-1440.png differ diff --git a/artifacts/design/daily-learning-evaluation-confidence-390.png b/artifacts/design/daily-learning-evaluation-confidence-390.png new file mode 100644 index 00000000..d3d4a67c Binary files /dev/null and b/artifacts/design/daily-learning-evaluation-confidence-390.png differ diff --git a/artifacts/design/daily-learning-evaluation-confidence-768.png b/artifacts/design/daily-learning-evaluation-confidence-768.png new file mode 100644 index 00000000..015bf54f Binary files /dev/null and b/artifacts/design/daily-learning-evaluation-confidence-768.png differ diff --git a/artifacts/design/daily-learning-inference-capacity-1440.png b/artifacts/design/daily-learning-inference-capacity-1440.png new file mode 100644 index 00000000..35709e79 Binary files /dev/null and b/artifacts/design/daily-learning-inference-capacity-1440.png differ diff --git a/artifacts/design/daily-learning-inference-capacity-390.png b/artifacts/design/daily-learning-inference-capacity-390.png new file mode 100644 index 00000000..1dba0490 Binary files /dev/null and b/artifacts/design/daily-learning-inference-capacity-390.png differ diff --git a/artifacts/design/daily-learning-inference-capacity-768.png b/artifacts/design/daily-learning-inference-capacity-768.png new file mode 100644 index 00000000..8369d67f Binary files /dev/null and b/artifacts/design/daily-learning-inference-capacity-768.png differ diff --git a/artifacts/design/daily-learning-labs-1440.png b/artifacts/design/daily-learning-labs-1440.png new file mode 100644 index 00000000..621d5a73 Binary files /dev/null and b/artifacts/design/daily-learning-labs-1440.png differ diff --git a/artifacts/design/daily-learning-labs-390.png b/artifacts/design/daily-learning-labs-390.png new file mode 100644 index 00000000..47143f23 Binary files /dev/null and b/artifacts/design/daily-learning-labs-390.png differ diff --git a/artifacts/design/daily-learning-labs-768.png b/artifacts/design/daily-learning-labs-768.png new file mode 100644 index 00000000..080d8d66 Binary files /dev/null and b/artifacts/design/daily-learning-labs-768.png differ diff --git a/artifacts/design/fanout-focused-study-1440.png b/artifacts/design/fanout-focused-study-1440.png new file mode 100644 index 00000000..c19a11a4 Binary files /dev/null and b/artifacts/design/fanout-focused-study-1440.png differ diff --git a/artifacts/design/fanout-focused-study-390.png b/artifacts/design/fanout-focused-study-390.png new file mode 100644 index 00000000..e45c611c Binary files /dev/null and b/artifacts/design/fanout-focused-study-390.png differ diff --git a/artifacts/design/fanout-focused-study-768.png b/artifacts/design/fanout-focused-study-768.png new file mode 100644 index 00000000..72edb5bc Binary files /dev/null and b/artifacts/design/fanout-focused-study-768.png differ diff --git a/artifacts/design/fanout-inference-1440.png b/artifacts/design/fanout-inference-1440.png new file mode 100644 index 00000000..8517e0fe Binary files /dev/null and b/artifacts/design/fanout-inference-1440.png differ diff --git a/artifacts/design/fanout-inference-390.png b/artifacts/design/fanout-inference-390.png new file mode 100644 index 00000000..42f8d45d Binary files /dev/null and b/artifacts/design/fanout-inference-390.png differ diff --git a/artifacts/design/fanout-inference-768.png b/artifacts/design/fanout-inference-768.png new file mode 100644 index 00000000..c475531f Binary files /dev/null and b/artifacts/design/fanout-inference-768.png differ diff --git a/artifacts/design/fanout-learn-1440.png b/artifacts/design/fanout-learn-1440.png new file mode 100644 index 00000000..e4a50301 Binary files /dev/null and b/artifacts/design/fanout-learn-1440.png differ diff --git a/artifacts/design/fanout-learn-390.png b/artifacts/design/fanout-learn-390.png new file mode 100644 index 00000000..29d6e89f Binary files /dev/null and b/artifacts/design/fanout-learn-390.png differ diff --git a/artifacts/design/fanout-learn-768.png b/artifacts/design/fanout-learn-768.png new file mode 100644 index 00000000..8f6f5961 Binary files /dev/null and b/artifacts/design/fanout-learn-768.png differ diff --git a/artifacts/design/fanout-model-routing-1440.png b/artifacts/design/fanout-model-routing-1440.png new file mode 100644 index 00000000..07e51b15 Binary files /dev/null and b/artifacts/design/fanout-model-routing-1440.png differ diff --git a/artifacts/design/fanout-model-routing-390.png b/artifacts/design/fanout-model-routing-390.png new file mode 100644 index 00000000..057ddc5e Binary files /dev/null and b/artifacts/design/fanout-model-routing-390.png differ diff --git a/artifacts/design/fanout-model-routing-768.png b/artifacts/design/fanout-model-routing-768.png new file mode 100644 index 00000000..380d6f83 Binary files /dev/null and b/artifacts/design/fanout-model-routing-768.png differ diff --git a/artifacts/design/fanout-notation-1440.png b/artifacts/design/fanout-notation-1440.png new file mode 100644 index 00000000..84fe50d7 Binary files /dev/null and b/artifacts/design/fanout-notation-1440.png differ diff --git a/artifacts/design/fanout-notation-390.png b/artifacts/design/fanout-notation-390.png new file mode 100644 index 00000000..4fcbdd35 Binary files /dev/null and b/artifacts/design/fanout-notation-390.png differ diff --git a/artifacts/design/fanout-notation-768.png b/artifacts/design/fanout-notation-768.png new file mode 100644 index 00000000..c0b0ad68 Binary files /dev/null and b/artifacts/design/fanout-notation-768.png differ diff --git a/artifacts/design/reviews/evidence-driven-daily-learning.json b/artifacts/design/reviews/evidence-driven-daily-learning.json new file mode 100644 index 00000000..17cd5f34 --- /dev/null +++ b/artifacts/design/reviews/evidence-driven-daily-learning.json @@ -0,0 +1,60 @@ +{ + "$schema": "fleet.design-review.v1", + "version": 1, + "project": "swe-interview-prep", + "target": "Evidence-driven daily learning and decision labs", + "mode": "preserve", + "register": "product", + "context": { + "product": "PRODUCT.md", + "design": "DESIGN.md" + }, + "direction": { + "references": [ + "artifacts/design/distilled-today-1440.png", + "artifacts/design/systems-lab-after-1440.png" + ], + "probes": [], + "selected": "existing-design", + "approval": "not-required", + "before": "artifacts/design/distilled-today-1440.png" + }, + "evidence": { + "screenshots": [ + { "width": 390, "path": "artifacts/design/daily-learning-dashboard-390.png" }, + { "width": 768, "path": "artifacts/design/daily-learning-dashboard-768.png" }, + { "width": 1440, "path": "artifacts/design/daily-learning-dashboard-1440.png" }, + { "width": 390, "path": "artifacts/design/daily-learning-labs-390.png" }, + { "width": 768, "path": "artifacts/design/daily-learning-labs-768.png" }, + { "width": 1440, "path": "artifacts/design/daily-learning-labs-1440.png" }, + { "width": 390, "path": "artifacts/design/daily-learning-inference-capacity-390.png" }, + { "width": 768, "path": "artifacts/design/daily-learning-inference-capacity-768.png" }, + { "width": 1440, "path": "artifacts/design/daily-learning-inference-capacity-1440.png" }, + { "width": 390, "path": "artifacts/design/daily-learning-capacity-planning-390.png" }, + { "width": 768, "path": "artifacts/design/daily-learning-capacity-planning-768.png" }, + { "width": 1440, "path": "artifacts/design/daily-learning-capacity-planning-1440.png" }, + { "width": 390, "path": "artifacts/design/daily-learning-evaluation-confidence-390.png" }, + { "width": 768, "path": "artifacts/design/daily-learning-evaluation-confidence-768.png" }, + { "width": 1440, "path": "artifacts/design/daily-learning-evaluation-confidence-1440.png" } + ], + "projectCheck": { + "command": "vitest run; tsc --noEmit; biome check .; docs validation; generated-curriculum + production Vite build; size limit; repository hygiene; responsive Playwright captures", + "status": "pass" + }, + "critique": { "score": 33, "maximum": 40 }, + "audit": { "score": 17, "maximum": 20 }, + "unresolved": { "p0": 0, "p1": 0 }, + "detector": { + "posture": "advisory", + "findings": [ + "The scoped detector ran exactly once and returned no implementation-integrity findings.", + "The accessibility audit found contrast, textarea naming, and nested-main issues; all were fixed before handoff.", + "The final independent critique found zero unresolved P0 or P1 issues after responsive recapture." + ] + } + }, + "ownerFeedback": { + "decision": "keep", + "note": "Owner reviewed the evidence-driven daily-learning direction and responded: keep going. Preserve the deterministic daily priority, evidence-gated labs, formula support, and source-led learning contracts." + } +} diff --git a/artifacts/design/reviews/four-surface-learning-os.json b/artifacts/design/reviews/four-surface-learning-os.json new file mode 100644 index 00000000..744fd6da --- /dev/null +++ b/artifacts/design/reviews/four-surface-learning-os.json @@ -0,0 +1,55 @@ +{ + "$schema": "fleet.design-review.v1", + "version": 1, + "project": "swe-interview-prep", + "target": "Four-surface Learning OS: Dashboard, Learn, Practice, and Wars with complete catalogue preservation", + "mode": "preserve", + "register": "product", + "context": { + "product": "PRODUCT.md", + "design": "DESIGN.md" + }, + "direction": { + "references": [], + "probes": [], + "selected": "existing-design", + "approval": "not-required", + "before": "artifacts/design/software-wars/after-wars-1440.png" + }, + "evidence": { + "screenshots": [ + { "width": 390, "path": "artifacts/design/final-dashboard-390.png" }, + { "width": 390, "path": "artifacts/design/final-learn-390.png" }, + { "width": 390, "path": "artifacts/design/final-practice-390.png" }, + { "width": 390, "path": "artifacts/design/final-wars-390.png" }, + { "width": 768, "path": "artifacts/design/final-dashboard-768.png" }, + { "width": 768, "path": "artifacts/design/final-practice-768.png" }, + { "width": 1440, "path": "artifacts/design/final-dashboard-1440.png" }, + { "width": 1440, "path": "artifacts/design/final-learn-1440.png" }, + { "width": 1440, "path": "artifacts/design/final-practice-1440.png" }, + { "width": 1440, "path": "artifacts/design/final-practice-selector-1440.png" }, + { "width": 1440, "path": "artifacts/design/final-wars-1440.png" }, + { "width": 390, "path": "artifacts/design/software-wars/final-tradeoff-playground-390.png" }, + { "width": 390, "path": "artifacts/design/software-wars/final-tradeoff-diagram-390.png" }, + { "width": 768, "path": "artifacts/design/software-wars/final-tradeoff-playground-768.png" }, + { "width": 1440, "path": "artifacts/design/software-wars/final-tradeoff-playground-1440.png" } + ], + "projectCheck": { + "command": "vitest run; tsc --noEmit; biome check .; docs validation; generated-curriculum + production Vite build; Playwright smoke/mobile/Wars; strict OpenSpec validation", + "status": "pass" + }, + "critique": { "score": 36, "maximum": 40 }, + "audit": { "score": 17, "maximum": 20 }, + "unresolved": { "p0": 0, "p1": 0 }, + "detector": { + "posture": "advisory", + "findings": [ + "The final scoped detector ran exactly once and found one advisory legacy color literal in CodeEditor; it was aligned to the documented rose-danger token before handoff." + ] + } + }, + "ownerFeedback": { + "decision": "keep", + "note": "Owner reviewed the four-surface direction and responded: looks good, keep going. Dashboard resumes work; Learn is high-level and searchable; Practice is the existing Playground with all 298 canonical problems; Wars presents the one-minute and thirty-minute formats. Complete concept, roadmap, problem, public-curriculum, progress, and legacy routes remain visible and portable." + } +} diff --git a/docs/architecture/data-flow.md b/docs/architecture/data-flow.md index 59401f91..48777825 100644 --- a/docs/architecture/data-flow.md +++ b/docs/architecture/data-flow.md @@ -104,6 +104,32 @@ into `src/pages/LearningDoc.tsx`. 5. BuildLab surfaces a "next weakest concept" card → the loop closes: drill → explain → mastery update → next weakest concept. +## Daily priority and decision evidence + +1. The existing session planner chooses one reachable concept using ordered + intervention classes: repeated failed practice, due low-confidence mastery, + then roadmap progression. Time is injectable so unchanged state is + deterministic. +2. A pure projection chooses the strongest evidence action for that concept + and exposes the objective, “why today” rationale, time budget, completion + predicate, and what completion unlocks. +3. Formula views, paper opens, calculations, frozen predictions, retrievals, + receipts, pending explanations, and verified explanations remain distinct + evidence states. Versioned decision receipts and paper attempts are stored + in an account namespace in localStorage. +4. Local evidence changes refresh Dashboard immediately. A receipt or paper + attempt remains mastery-pending until the authenticated Feynman action + accepts the explanation; only then can the existing concept-mastery API + update FSRS. +5. Known-unavailable external sources cannot become the primary assignment; + the projection falls back to a local concept, drill, or decision lab. +6. A stable UTC-day rotation selects among available concept-linked paper + contracts, but it runs only after recovery and retention selection and + after any unverified concept-linked decision lab. +7. Mutable decision-lab and focused-study drafts live in a separate + account-scoped continuity store. Definition-version mismatches are ignored; + issuing an immutable receipt clears the corresponding mutable draft. + ## Systems Lab attempt flow 1. `/labs/:labId` loads a versioned definition from the SPA bundle and diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 8c481108..e58ffacb 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -13,6 +13,9 @@ React SPA (Vite build → dist/) ├── Monaco + Go code execution (client-side WASM from R2, API-proxy fallback) ├── Excalidraw diagrams ├── Systems Lab ──► pure virtual-time reducer + checked-in evidence graphs + ├── Decision labs ──► pure calculators + immutable local decision receipts + ├── Focused study ──► version-aware, account-scoped local continuity drafts + ├── Daily priority ──► profile + FSRS + practice + local evidence ├── Socratic AI (useAI) ──► /api/chat (dev bridge) / OpenAI-compatible endpoint ├── Progress + FSRS hooks ──► /api/learning, /api/progress ──► D1 ├── Learning library + sources ──► owner-only /api/learning actions ──► D1 + remote repos @@ -64,6 +67,11 @@ intentionally does not restate it. `learning-os.ts`. Mutable user state is hybrid: localStorage for guests, D1 for signed-in users (`useUserStore`). Signing in merges localStorage into the DB. +- **Learning evidence vs continuity.** Append-only decision receipts and paper + attempts live in the versioned learning-evidence store. Overwritable + decision-lab and focused-study drafts live in a separate account-scoped + continuity store; a lab definition mismatch is ignored and issuing a + receipt clears only the corresponding draft. - **Deterministic Systems Lab.** Versioned definitions under `src/data/systems-labs/` describe actors, controls, reachable transitions, truth planes, decisive evidence, and bounded broken-to-repaired diff --git a/docs/knowledge/learnings.md b/docs/knowledge/learnings.md index ddd526a1..a4f7a761 100644 --- a/docs/knowledge/learnings.md +++ b/docs/knowledge/learnings.md @@ -4,6 +4,28 @@ Reusable lessons that are not obvious from the code. Add new entries at the top with a date. One lesson per bullet; link to the code or ADR that exemplifies it. +## 2026-08 — Choose the concept before the learning format + +New papers and calculators are tempting because they are novel, but novelty is +not a learning priority. Choose recovery, retention, or progression from +learner state first; only then select the best fitting evidence action for the +winning concept. This keeps a fresh source from displacing failed practice or +an overdue review, and makes “why today?” inspectable. + +The daily paper choice may rotate deterministically for variety, but only +inside that concept-first boundary. Mutable continuity and durable evidence +also need different stores: a draft may be overwritten while typing and +ignored when a definition version changes, while a decision receipt or paper +attempt is append-only. Keeping them separate avoids turning resume behavior +into accidental mastery history. + +## 2026-08 — Calculations become learning only through decisions and explanation + +A numeric result is useful evidence, not mastery. Freeze a prediction before +reveal, preserve assumptions and derived values in an immutable receipt, then +require a mitigation, counterfactual, verification metric, and causal +explain-back. Keep opened, calculated, retrieved, pending, and verified states +separate so UI completion cannot fabricate FSRS progress. ## 2026-08 — A truthiness filter can make absence unreportable `weakConcepts()` filtered on `mastery[c.id] && …`, so a concept never opened diff --git a/docs/product/overview.md b/docs/product/overview.md index 1ee5a756..4c1611d0 100644 --- a/docs/product/overview.md +++ b/docs/product/overview.md @@ -32,6 +32,12 @@ Feynman Gate) is the build/drill workspace. Systems Lab adds a second kind of artifact: a repaired infrastructure configuration plus a frozen prediction, actor-owned evidence, and a causal explain-back. +Dashboard turns the same principle into one daily decision. Failed practice +recovery outranks overdue retention, which outranks roadmap progression. The +winning concept is paired with an explicit evidence contract: retrieval, +drill, decision receipt, paper retrieval, artifact, or explain-back. Opening a +source or producing a calculation never counts as mastery. + ## Primary destinations The canonical navigation model in `src/data/site-navigation.ts` exposes four @@ -41,14 +47,17 @@ peer destination: | Tab | Role | | --- | --- | -| Dashboard | Resume recent work; see current and next learning/practice; discover available paths | +| Dashboard | Answer what to learn today with one evidence-backed priority; keep recent work and paths as supporting context | | Learn | Searchable high-level entry to concepts and learning paths | | Practice | The Playground workspace with a selector over the complete problem inventory | | Wars | One-minute MCQ battles and thirty-minute solo or matched engineering battles | Dashboard resumes the learner's current loop. Learn stays deliberately high-level, but its search and browse-all destinations cover every canonical -concept and roadmap. Practice opens directly into the Playground and keeps the +concept and roadmap. Its contextual tools expose the complete 42-section Learn +Inference companion path, searchable formula and notation reference, +prerequisite/related/unlock knowledge topography, rotating paper programme, +and focused resumable study. Practice opens directly into the Playground and keeps the complete problem catalogue one interaction away. Wars makes the duration choice explicit before exposing ratings, history, leaderboards, and operational detail. Active battles and workspaces use a focused shell that @@ -56,7 +65,9 @@ keeps account access and an exit while suppressing unrelated chrome. Detail pages (`/concepts/:id`, `/roadmaps/:id`, `/projects/:id`, `/drills/:id`) remain reachable through contextual hubs and Browse. `/mock`, `/playground`, -`/build`, `/labs`, `/progress`, and `/wars` remain real pages with stable deep +`/build`, `/labs`, `/labs/decision/:labId`, `/learn/inference`, +`/learn/notation`, `/learn/papers`, `/learn/map/:conceptId`, +`/study/:focusKind/:focusId`, `/progress`, and `/wars` remain real pages with stable deep links. Legacy routes redirect so external links keep working: `/today` → `/dashboard`; `/roadmaps` → `/learn`; `/concepts` → `/learn/all`; `/drills` → `/practice/all`; `/reviews`, `/review` → `/practice/all?tab=reviews`; `/projects` diff --git a/docs/product/surfaces.md b/docs/product/surfaces.md index 60715ffe..02179582 100644 --- a/docs/product/surfaces.md +++ b/docs/product/surfaces.md @@ -10,9 +10,14 @@ disagrees with code, code wins. | Route | Surface | | --- | --- | | `/` | Redirects to `/dashboard` | -| `/dashboard` | Resume hub: recent destinations, current/next learning and practice, paths, and supporting progress | +| `/dashboard` | One deterministic daily learning priority with its rationale, time budget, evidence contract, and supporting session map | | `/today` | Legacy redirect to `/dashboard` | | `/learn`, `/learn/all` | Searchable high-level learning entry plus the complete concept catalogue | +| `/learn/inference` | Complete 42-section companion path through the canonical Learn Inference book | +| `/learn/notation` | Searchable formula, bound, unit, and notation reference | +| `/learn/map/:conceptId` | Accessible prerequisite, related-concept, and downstream-unlock topography | +| `/learn/papers` | Deterministic rotating primary-source programme and retrieval contracts | +| `/study/:focusKind/:focusId` | Account-scoped resumable Learn → Retrieve → Apply → Explain session | | `/explore` | Concept/roadmap explorer | | `/sweep`, `/sweep?domain=` | Breadth triage — rate every concept Known/Fuzzy/New; ROI ranking + domain muting. Reachable from `/learn`, deliberately not in `SITE_NAV_ITEMS`. Model and deferred work: [`breadth-sweep.md`](breadth-sweep.md); open follow-up lives in [GitHub Issues](https://github.com/Significant-Hobbies/swe-interview-prep/issues) | | `/practice` | Playground workspace with a selector over the complete canonical problem inventory | @@ -26,7 +31,8 @@ disagrees with code, code wins. | `/wars/results/:slug` | Sanitized public match result | | `/progress`, `/progress/all` | Mastery rollups + notes | | `/build`, `/drills/:id` | BuildLab (hands-on build/drill workspace) | -| `/labs`, `/labs/:labId` | Systems Lab catalog + configuration workshop + deterministic scenario runner | +| `/labs`, `/labs/:labId` | Lab catalog + configuration workshop + deterministic Systems Lab scenario runner | +| `/labs/decision/:labId` | Six local decision labs: inference capacity, capacity planning, evaluation confidence, model routing, RAG readiness, and inference benchmarking | | `/library`, `/library/:repoSlug` | Embedded GitHub learning-library reader | | `/sources`, `/sources/:id` | Unified learning-sources index | | `/session/:date`, `/session/:date/:sessionId` | Adaptive learning session | @@ -55,7 +61,7 @@ search-only, hidden, or coupled to a particular presentation. Stable detail links, browse-all routes, generated catalogues, and public curriculum output are part of the product contract. -Active `/practice`, `/playground`, `/drills/:id`, `/labs/:labId`, `/wars/blitz*`, and +Active `/practice`, `/playground`, `/drills/:id`, `/labs/:labId`, `/study/*`, `/wars/blitz*`, and `/wars/tradeoff*` routes use the focused shell. It retains product identity, settings/account access, keyboard navigation, and a visible exit, while hiding the digest, setup/storage strips, and feedback trigger until the learner exits @@ -72,7 +78,11 @@ progress worth losing. Guest state is localStorage-only and namespaced per account, so signing in adopts a guest pass rather than discarding it. -Systems Lab attempts are also account-scoped in localStorage. A guest may +Systems Lab attempts are also account-scoped in localStorage. Decision receipts +and paper attempts use a separate versioned, account-scoped local evidence +store; resumable study sessions and mutable decision-lab drafts use a separate +continuity store and never rewrite immutable receipts. None adds a D1 table or +mastery API. A guest may repair the bounded infrastructure configuration, predict, run, inspect evidence, retry, and draft an explanation. The attempt stays labeled mastery-pending until the configuration passes and an authenticated Feynman diff --git a/docs/product/systems-lab.md b/docs/product/systems-lab.md index 59e88964..114ee6bf 100644 --- a/docs/product/systems-lab.md +++ b/docs/product/systems-lab.md @@ -4,6 +4,19 @@ Scope: the deterministic, client-only systems learning surface at `/labs`. This page documents the product boundary and authoring contract; checked-in definitions remain the executable source of truth. +`/labs` also indexes six smaller decision labs. They deliberately do not use +the actor-transition engine: inference capacity, workload capacity, Wilson +confidence, two-model routing, RAG readiness, and inference benchmark +normalization are pure arithmetic over declared inputs. Their shared flow is +Inputs → Frozen prediction → Reveal → Decision → Counterfactual → Receipt → +Explain. Receipts are immutable, versioned, account-scoped local evidence and +remain mastery-pending until the existing authenticated Feynman path accepts a +causal explanation. + +Mutable work is kept separate: the shared shell auto-saves a version-matched, +account-scoped draft and may load declared scenario presets. A saved receipt +clears that draft; it never edits or replaces prior receipts. + ## Learning loop Each attempt follows one evidence-gated sequence: @@ -51,6 +64,16 @@ This boundary is intentional: External links at the end of each lab are optional primary-source reading. Opening one is outside simulation execution. +Decision labs share the same safety posture. They have no cloud credentials or +runtime service dependency and make no claim to predict real latency. The +inference calculator separates weights, raw KV cache, declared reserve, and +headroom while naming excluded runtime overhead. The evaluation calculator +uses 95% Wilson intervals and reports insufficient evidence when its declared +conservative comparison rule cannot support a direction. Routing uses +synthetic profiles rather than live provider claims; RAG readiness accepts +aggregate counts rather than documents; benchmarking normalizes learner-entered +client totals and compares no vendors. + ## Fidelity and source contracts Every published lab declares a fidelity level: diff --git a/public/curriculum/concepts/inference-engines.html b/public/curriculum/concepts/inference-engines.html index cbfd5aca..bc5f6009 100644 --- a/public/curriculum/concepts/inference-engines.html +++ b/public/curriculum/concepts/inference-engines.html @@ -77,7 +77,7 @@

Proof of understanding

Learn from primary sources

- +
diff --git a/public/curriculum/concepts/inference-engines.md b/public/curriculum/concepts/inference-engines.md index 7e2b19ea..1a6e9297 100644 --- a/public/curriculum/concepts/inference-engines.md +++ b/public/curriculum/concepts/inference-engines.md @@ -19,6 +19,8 @@ An inference engine is a runtime: it schedules requests, owns model and KV memor - [Efficient Memory Management for Large Language Model Serving with PagedAttention](https://arxiv.org/abs/2309.06180) (paper) - [Fast and Expressive LLM Inference with RadixAttention and SGLang (LMSYS)](https://lmsys.org/blog/2024-01-17-sglang/) (article) - [vLLM Documentation](https://docs.vllm.ai/) (doc) +- [Learn Inference — interactive guide to inference engineering](https://learn-inference.com/) (book) +- [Inference Engineering (Philip Kiely, Baseten)](https://www.baseten.co/inference-engineering/) (book) ## Practice diff --git a/scripts/s-tier-catalog.mjs b/scripts/s-tier-catalog.mjs index eeeabd98..f3dd92c3 100644 --- a/scripts/s-tier-catalog.mjs +++ b/scripts/s-tier-catalog.mjs @@ -2532,6 +2532,17 @@ for (const conceptId of ['message-queues', 'cap-theorem', 'consensus', 'event-st CONCEPT_MEDIA[conceptId] = { ...(CONCEPT_MEDIA[conceptId] ?? {}), book: { ...DDIA } }; } +// The interactive guide makes the serving stack approachable while linking to +// its underlying book; the concept's other sources remain the primary papers +// and first-party runtime documentation. +CONCEPT_MEDIA['inference-engines'] = { + ...(CONCEPT_MEDIA['inference-engines'] ?? {}), + book: L( + 'Learn Inference — interactive guide to inference engineering', + 'https://learn-inference.com/' + ), +}; + for (const [conceptId, links] of Object.entries({ normalization: [ L( diff --git a/scripts/source-tier.mjs b/scripts/source-tier.mjs index 5fb6b123..dec01a50 100644 --- a/scripts/source-tier.mjs +++ b/scripts/source-tier.mjs @@ -54,7 +54,7 @@ const S_TIER_RESEARCH = /research\.google|usenix\.org|acm\.org|sigmod\.org|openreview\.net|doi\.org|lamport\.azurewebsites\.net|rfc-editor\.org|microsoft\.com\/en-us\/research|allthingsdistributed\.com|pdos\.csail\.mit\.edu|plg\.uwaterloo\.ca|cs\.utexas\.edu|cs\.princeton\.edu|cs\.umb\.edu|hal\.science|dl\.acm\.org|papers\.ssrn\.com|static\.aminer\.org/i; const S_TIER_CANON_BOOK = - /nlp\.stanford\.edu\/IR-book|dataintensive\.net|databass\.dev|deeplearningbook\.org|jeffe\.cs\.illinois\.edu|mitpress\.mit\.edu|ocw\.mit\.edu|statlearning\.com|web\.stanford\.edu\/~boyd\/cvxbook|inference\.org\.uk\/itprnn|projects\.iq\.harvard\.edu\/stat110|cs336\.stanford\.edu|cs231n\.github\.io|karpathy\.ai|web\.stanford\.edu\/~jurafsky\/slp3|pages\.cs\.wisc\.edu\/~remzi\/OSTEP|sre\.google\/sre-book|craftinginterpreters\.com|svpg\.com|rework\.withgoogle\.com|domainlanguage\.com|jcip\.net|seeing-theory\.brown\.edu|otexts\.com|xcelab\.net|algorithm-design-manual\.com|pearson\.com|alisawuffles\.notion\.site|15445\.courses\.cs\.cmu\.edu|web\.stanford\.edu\/class|pdos\.csail\.mit\.edu/i; + /nlp\.stanford\.edu\/IR-book|dataintensive\.net|databass\.dev|deeplearningbook\.org|jeffe\.cs\.illinois\.edu|mitpress\.mit\.edu|ocw\.mit\.edu|statlearning\.com|web\.stanford\.edu\/~boyd\/cvxbook|inference\.org\.uk\/itprnn|learn-inference\.com|baseten\.co\/inference-engineering|projects\.iq\.harvard\.edu\/stat110|cs336\.stanford\.edu|cs231n\.github\.io|karpathy\.ai|web\.stanford\.edu\/~jurafsky\/slp3|pages\.cs\.wisc\.edu\/~remzi\/OSTEP|sre\.google\/sre-book|craftinginterpreters\.com|svpg\.com|rework\.withgoogle\.com|domainlanguage\.com|jcip\.net|seeing-theory\.brown\.edu|otexts\.com|xcelab\.net|algorithm-design-manual\.com|pearson\.com|alisawuffles\.notion\.site|15445\.courses\.cs\.cmu\.edu|web\.stanford\.edu\/class|pdos\.csail\.mit\.edu/i; /** Canonical educational / research destinations valid for any slot. */ const S_TIER_CANON_ANY = diff --git a/src/App.tsx b/src/App.tsx index b878c082..6238bd25 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -40,6 +40,11 @@ const Onboarding = lazy(() => import('./pages/Onboarding')); const PublicRoadmap = lazy(() => import('./pages/PublicRoadmap')); const Learn = lazy(() => import('./pages/Learn')); const LearnAll = lazy(() => import('./pages/LearnAll')); +const InferencePath = lazy(() => import('./pages/InferencePath')); +const NotationReference = lazy(() => import('./pages/NotationReference')); +const KnowledgeMap = lazy(() => import('./pages/KnowledgeMap')); +const PaperProgramme = lazy(() => import('./pages/PaperProgramme')); +const FocusedStudy = lazy(() => import('./pages/FocusedStudy')); const Explore = lazy(() => import('./pages/Explore')); const Sweep = lazy(() => import('./pages/Sweep')); const PracticeAll = lazy(() => import('./pages/PracticeAll')); @@ -63,6 +68,7 @@ const Changelog = lazy(() => import('./pages/Changelog')); const Login = lazy(() => import('./pages/Login')); const SystemsLabs = lazy(() => import('./pages/SystemsLabs')); const SystemsLabRunner = lazy(() => import('./pages/SystemsLabRunner')); +const DecisionLab = lazy(() => import('./pages/DecisionLab')); const SoftwareWars = lazy(() => import('./pages/SoftwareWars')); const BlitzWar = lazy(() => import('./pages/BlitzWar')); const TradeoffWar = lazy(() => import('./pages/TradeoffWar')); @@ -115,6 +121,11 @@ function AppRoutes() { } /> } /> } /> + } /> + } /> + } /> + } /> + } /> } /> } /> } /> @@ -128,6 +139,7 @@ function AppRoutes() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/components/DecisionLabShell.tsx b/src/components/DecisionLabShell.tsx new file mode 100644 index 00000000..b114f23a --- /dev/null +++ b/src/components/DecisionLabShell.tsx @@ -0,0 +1,560 @@ +import { ArrowLeft, CheckCircle2, Gauge, RotateCcw, ShieldCheck } from 'lucide-react'; +import { useEffect, useMemo, useState } from 'react'; +import { Link } from 'react-router-dom'; + +import { useLearningEvidence } from '../hooks/useLearningEvidence'; +import { + appendDecisionReceipt, + type DecisionLabId, + type DecisionReceiptV1, +} from '../lib/learningEvidence'; +import { createDecisionReceipt } from '../lib/decisionLabs'; +import { isPassingFeynmanGrade } from '../lib/feynmanRating'; +import { + clearDecisionLabDraft, + loadDecisionLabDraft, + saveDecisionLabDraft, +} from '../lib/learningContinuity'; +import FeynmanGate from './FeynmanGate'; +import { FormulaExplainer } from './FormulaExplainer'; +import { FORMULA_BY_ID } from '../data/formulas'; + +interface DecisionLabField { + id: string; + label: string; + unit: string; + initial: number; + min?: number; + step?: number; + group: string; +} + +export interface DecisionLabDefinition { + id: DecisionLabId; + version: number; + title: string; + summary: string; + estimatedMinutes: number; + conceptIds: string[]; + fields: DecisionLabField[]; + predictionPrompt: string; + predictionExample: string; + formulaIds: string[]; + presets?: Array<{ + id: string; + label: string; + description: string; + values: Record; + }>; + calculate: (values: Record) => Record; +} + +export function DecisionLabShell({ definition }: { definition: DecisionLabDefinition }) { + const { accountScope, decisionReceipts } = useLearningEvidence(); + const savedDraft = useMemo( + () => loadDecisionLabDraft(accountScope, definition.id, definition.version), + [accountScope, definition.id, definition.version] + ); + const [values, setValues] = useState>( + () => + savedDraft?.values ?? + Object.fromEntries(definition.fields.map((field) => [field.id, field.initial])) + ); + const [prediction, setPrediction] = useState(savedDraft?.prediction ?? ''); + const [derived, setDerived] = useState | null>( + savedDraft?.derived ?? null + ); + const [conclusion, setConclusion] = useState(savedDraft?.conclusion ?? ''); + const [mitigation, setMitigation] = useState(savedDraft?.mitigation ?? ''); + const [counterfactual, setCounterfactual] = useState(savedDraft?.counterfactual ?? ''); + const [verificationMetric, setVerificationMetric] = useState( + savedDraft?.verificationMetric ?? '' + ); + const [receipt, setReceipt] = useState(null); + const [error, setError] = useState(''); + const [feynmanOpen, setFeynmanOpen] = useState(false); + + const priorReceipts = useMemo( + () => decisionReceipts.filter((candidate) => candidate.labId === definition.id), + [decisionReceipts, definition.id] + ); + + useEffect(() => { + if (receipt) { + clearDecisionLabDraft(accountScope, definition.id); + return; + } + saveDecisionLabDraft(accountScope, { + schemaVersion: 1, + labId: definition.id, + definitionVersion: definition.version, + values, + prediction, + derived, + conclusion, + mitigation, + counterfactual, + verificationMetric, + updatedAt: new Date().toISOString(), + }); + }, [ + accountScope, + conclusion, + counterfactual, + definition.id, + definition.version, + derived, + mitigation, + prediction, + receipt, + values, + verificationMetric, + ]); + + function resetAttempt(nextValues = values) { + setValues(nextValues); + setPrediction(''); + setDerived(null); + setConclusion(''); + setMitigation(''); + setCounterfactual(''); + setVerificationMetric(''); + setReceipt(null); + setError(''); + } + + function changeValue(fieldId: string, raw: string) { + const next = { ...values, [fieldId]: Number(raw) }; + if (derived || receipt) resetAttempt(next); + else setValues(next); + } + + function reveal() { + if (prediction.trim().length < 10) { + setError('Write a concrete prediction before revealing the calculation.'); + return; + } + try { + setDerived(definition.calculate(values)); + setError(''); + } catch (caught) { + setError(caught instanceof Error ? caught.message : 'The declared inputs are invalid.'); + } + } + + function saveReceipt() { + if (!derived) return; + try { + const next = createDecisionReceipt({ + accountScope, + labId: definition.id, + definitionVersion: definition.version, + conceptIds: definition.conceptIds, + inputs: values, + derived, + prediction, + conclusion, + mitigation, + counterfactual, + verificationMetric, + }); + appendDecisionReceipt(next); + setReceipt(next); + setError(''); + } catch (caught) { + setError(caught instanceof Error ? caught.message : 'The decision receipt is incomplete.'); + } + } + + function markVerified(grade: number) { + if (!receipt || !isPassingFeynmanGrade(grade)) return; + const createdAt = new Date().toISOString(); + appendDecisionReceipt({ + ...receipt, + id: `${receipt.id}:verified:${createdAt}`, + evidenceState: 'verified', + masteryStatus: 'applied', + conclusion: `${receipt.conclusion} Feynman grade: ${grade}.`, + createdAt, + }); + setFeynmanOpen(false); + } + + const receiptReady = + derived && + conclusion.trim() && + mitigation.trim() && + counterfactual.trim() && + verificationMetric.trim(); + const fieldGroups = useMemo( + () => + Array.from(new Set(definition.fields.map((field) => field.group))).map((group) => ({ + group, + fields: definition.fields.filter((field) => field.group === group), + })), + [definition.fields] + ); + + return ( +
+ + Labs + + +
+
+ Decision lab + + v{definition.version} + + {definition.estimatedMinutes} min +
+

+ {definition.title} +

+

{definition.summary}

+
+ +
    + + + + item.evidenceState === 'verified')} + label="Explanation" + /> +
+ +
+
+
+
+

+ Declared inputs +

+ + {savedDraft ? 'Draft restored · ' : ''}Inputs lock after reveal + +
+ {definition.presets && definition.presets.length > 0 && ( + + )} +
+ {fieldGroups.map(({ group, fields }) => ( +
+ + {group} + +
+ {fields.map((field) => ( + + ))} +
+
+ ))} +
+
+ +
+

+ Decision aids +

+

+ Keep the governing relationship and its exclusions visible before you predict. +

+
+ {definition.formulaIds.map((formulaId) => ( + + ))} +
+
+ +
+

+ Freeze your prediction +

+

+ {definition.predictionPrompt} +

+