- Integrate diagnostic and evaluation MCQ scoring in quiz sessions
- Extend round-trip CSV grammar with `done:<ex>:<earned>/<total>` and `RESET`
- Fix completed count aggregation in repositories to include 'done' state
- Update progress report CSV export to output composite scores per lesson
- Add comprehensive test coverage for scoring, CSV round-trip, and exports
- Mount SlideCarousel secara dinamis di LessonContentView (#slide-mount-point)
- Fix infinite reactivity loop (effect_update_depth_exceeded) dengan menggunakan plain variable bukan $state untuk handle slideComponent
- Tambah auto-rendering (math, code, flowchart, circuit) saat slide berubah/expand di SlideCarousel
- Defensive try-catch unmount/mount dan eksplisit type ReturnType<typeof mount>
- Update sidebar feature template di /teacher/content (Layout, Set Soal bundle, Inline)
Migration 0005 gagal karena UPDATE state='in_progress' dijalankan
sebelum constraint lama di-drop. Constraint lama (dari 0001) hanya
mengizinkan 'not_started','completed','scored' sehingga 'in_progress'
ditolak PostgreSQL (CheckViolation).
Fix: pindahkan DROP/CREATE constraint ke sebelum blok UPDATE backfill.
- CLN-01: Verifikasi dan konsolidasi polyfill worker_threads.markAsUncloneable ke helper nodeCompat.ts
- CLN-01: Dokumentasi mekanisme require-time (node-polyfill.cjs) vs import-time (nodeCompat.ts)
- CLN-02: Hapus dependency dompurify dan @types/dompurify yang tidak terpakai dari package.json
- Verifikasi seluruh test suite (13 test files, 165 tests) tetap 100% lulus
- Mengganti sanitizer manual dengan isomorphic-dompurify dan hook whitelist/blocklist (BF-01 & BF-02)
- Memperbaiki parsing penjelasan flashcard non-MCQ agar mencari blockquote di seluruh body (BF-03)
- Menambahkan node-polyfill.cjs dan konfigurasi NODE_OPTIONS untuk mengatasi incompatibilitas worker_threads.markAsUncloneable pada Node 20 runtime (SSR blank screen fix)
- Menambahkan unit test keamanan embed (BF-04) dan parity tests dengan fixture backend (BF-05)
- Mendokumentasikan deduplikasi quiz tab pada detectActiveTabs (BF-06)
- QuizTab: ganti use:renderMath (jalan sekali pas mount) dengan $effect
yang jalan ulang autoRenderMath tiap konten kuis berubah — cover opsi
MCQ aktif, review live, dan review hasil-load async (setelah refresh).
- QuizPreviewReadonly (content editor guru): tambah $effect autoRenderMath
agar LaTeX di soal/opsi/penjelasan ke-render di pratinjau kunci jawaban.
autoRenderMath idempoten sehingga aman dijalankan berulang tanpa dobel render.
- Perbaiki pemanggilan deleteEntry di +page.svelte baris 531: argumen
force=true tidak lagi diteruskan dengan benar setelah signature
fungsi berubah (confirmCritical ditambah di tengah)
- Koreksi komentar dengan karakter Mandarin di content_editor.py baris 488
- Tambah test unit contentEditor.test.ts dengan 5 kasus:
- deleteEntry force delete
- deleteEntry confirm_critical untuk file kritis
- deleteEntry default parameter
- renameEntry standar
- renameEntry confirm_critical
Fixes: hapus folder dengan isi tidak lagi gagal 409.
All tests: 119 passed.
- playground +page: jadikan main.container flex-column + .playground-page flex:1
agar memenuhi ruang sisa setelah navbar (sebelumnya height:100% resolve ke
tinggi intrinsik karena parent display:block)
- pg-content: tambah flex-direction:column supaya flex:1 grow tinggi bukan lebar
- override :global .flowchart-container & .circuit-wrapper jadi height:100%;flex:1;
min-height:0 (hilangkan min-height:400px / height:550px fix) agar melar
- Navbar: tambah link Playground di dropdown burger tepat di bawah Tema Gelap
- terverifikasi Playwright desktop(1280x800) & mobile(390x780): semua tab 98-100%
- Tambah PROTECTED_BASENAMES (home.md, sub-home.md) dengan konfirmasi
kedua saat rename/delete agar tidak merusak navigasi siswa (tidak
bisa di-undo). Diteruskan ke renameEntry/deleteEntry di contentEditor.ts.
- Hapus fitur featureSidebarNarrow + CSS terkait (tidak dipakai).
- Footer & backend: penyesuaian rute/test content editor.
- Tambah FEATURE_TEMPLATES 'expected-wiring' (grup Penilaian) untuk
menyisipkan blok ---EXPECTED_WIRING--- yang dipakai velxio-evaluator
grading wiring (sudah diekstrak backend lesson_service.py).
- Perbaiki iframe Velxio tab Arduino tidak dinamis: tambah height:100%
pada .velxio-tab-content agar mengisi tinggi area kosong di desktop & mobile.
- Navbar: item 'Edit Content' (/teacher/content) & 'Progress' (/teacher/progress)
muncul hanya saat akun guru login, ditaruh di atas divider login/logout
- Pindahkan route /progress -> /teacher/progress (git mv) agar konsisten dg /teacher/content
- Hapus link Progress di Footer (sudah ada di navbar)
- Editor content: tombol Fitur (toggle sidebar) dipindah ke header samping Simpan/Publish,
Simpan/Publish diubah jadi icon, hapus tombol panah floating di tepi & di header sidebar,
tombol dock/undock & minimize dipindah ke pojok kanan (mode desktop)
- Bump APP_VERSION 28 -> 29
- Reset previewActiveTabs/previewSlides saat pindah ke asset & saat hapus
file aktif, agar tab dinamis (C/Python/Circuit/Arduino/Flowchart) tidak
menetap setelah berpindah konteks.
- Ganti Pillow Image.verify() dengan Image.load() di validasi upload asset.
verify() false-positive CRC pada chunk IDAT PNG valid -> backend 500.
load() cukup membuktikan file adalah gambar yang bisa di-decode.
Add dynamic chrome tabs based on previewActiveTabs from markdown parsing.
When teacher writes ---INITIAL_CODE--- or ---INITIAL_PYTHON--- blocks,
the corresponding C/Python tab appears with read-only code preview.
- Widen activeTab type to string for dynamic tab IDs
- Extract code blocks client-side from raw markdown body
- Render chrome tabs dynamically from allTabs derived state
- Auto-switch away from invalid tabs when preview updates
- Replace inline SVGs with Unicode icons from WorkspaceHeader (⊞ ▽ △ ◀)
- Use shared .panel-btn / .panel-actions / .btn-float-toggle CSS classes
- Match .resize-handle and .panel-header styling from lesson page
- Make CodeEditor dynamically fill workspace at any height (flex + height:100%)
- Override .cm-editor max-height in content-editor to remove fixed 60vh cap
- Floating/dockable editor panel with drag & resize handles
- Mobile view modes: hidden → 50% → 100% toggle cycle
- Mobile tree-first: show file tree when no file selected, back button to return
- Asset file preview with image display and copy-path button
- Touch support for drag and resize on mobile
- Fix missing closing div in asset preview section
Tambahkan logika ambang minimum skor (opsional) di daftar prasyarat.
Tanpa ambang, status scored berapa pun (termasuk 0/x) memenuhi syarat
(backward compatible). Dengan ambang `min: N%`, earned/total harus
melebihi ambang untuk membuka kunci materi berikutnya.
Perubahan:
- Parser bullet prasyarat mendukung suffix `min: N%` (contoh: min: 75%)
- is_prerequisite_met: completed → selalu terpenuhi; scored → terpenuhi
kecuali di bawah ambang; not_started → belum terpenuhi
- routes/lessons.py: 3 titik kunci sekarang pakai get_missing_prerequisites
- latex_test.md: tambahkan prereq quiz_test min: 75% (demo nyata)
- examples/content disinkronkan dengan content
- Tambah test_prerequisite_logic.py (28 unit test) + 3 integration test
- routes/docs.py: pakai current_app, bukan create_app() per request — tidak
lagi memicu DB sync ulang di setiap hit /docs/api-reference (dead code
route_modules/rule_map dihapus)
- frontend: entry statis API Reference di sidebar /docs, fetch lazy
/api/docs/api-reference, render method badge + auth + docstring
- test: 4 test yatim di test_teacher_bootstrap diberi marker unit;
Makefile test-stats kini menampilkan count per marker + orphan (harus 0)
- docs_service: hapus dead code _read_md_cached, sederhanakan cache-check
_parse_frontmatter (satu getmtime, kondisi jelas)
- lesson_service: gabung pemanggilan bleach.clean dobel jadi satu dengan
css_sanitizer opsional — hilangkan NoCssSanitizerWarning (7x)
- conftest: fixture autouse _isolate_database lewati isolasi untuk test unit
supaya make test-unit tetap jalan tanpa DB walau DATABASE_URL diset
Verifikasi: unit 114 passed, full suite 239 passed (0 warnings) dengan
Postgres test, svelte-check 0 error, vitest 114 passed, docs-validate ok.
- Flask docs routes changed from /api/docs to /docs (no /api prefix)
because hooks.server.ts proxies /api/* by stripping /api, so /api/docs
reached Flask as /docs (404). Other routes (lessons, help) also lack /api.
- Frontend load functions now fetch /docs and /docs/<slug> (not /api/docs)
- Fixes 500 on /docs SSR (proxy ECONNREFUSED / 404 from stripped route)
- Task 1: pindahkan .quiz-navigator & .quiz-controls dari QuizTab ke
QuizQuestionView; refactor props jadi mgr: LessonManager; CSS ke lesson.css.
Navigator+kontrol kuis selalu terlihat di mobile walau workspace hidden.
- Task 2: get_all_students_progress tidak filter role guru; field role per row;
badge 'Guru', bulk-action & empty-state & ringkasan hanya hitung siswa.
- Task 3: endpoint POST /students/add (reuse StudentRoundTripRow +
find_student_import_conflicts + run_student_import); validate_single_student_input;
AddStudentDialog + addStudent(); import/export/bulk-delete CSV lama tetap ada.
- Fix (Opsi A): breakdown eval/diag hanya hitung MCQ (flashcard netral) —
selaraskan dengan skor resmi FE; perbaiki tampilan eval:4/6 yg membingungkan.
Tambah field type ke QuizAnswerPayload.
Test: backend 239 passed (termasuk test baru teacher-in-report, add-student,
breakdown-excludes-flashcards); svelte-check 0 error; build sukses.
version.ts 27->28.
- QUIZ-01: beforeunload hanya kirim beacon (tanpa finalisasi state) sehingga
Cancel dialog membatalkan reload dan quiz lanjut; beforeNavigate tidak lagi
memfinalisasi untuk tipe 'leave' (full-page unload/reload); review
disembunyikan untuk page_unload (display policy anti-eksploitasi)
- QUIZ-02: opsi MCQ tampil 2-kolom grid (single-col untuk <=2 pilihan,
fallback 1 kolom di mobile sempit)
- QUIZ-03: hapus info "soal X dari Y / X dijawab" + progress bar dari
workspace dan question view
- QUIZ-04: opsi tinggi workspace mobile hide/30%/50%/70%/full dengan
stepUp/stepDown untuk swipe & tombol resize
- QUIZ-05: workspace flashcard hanya 2 tombol "Sudah Mengerti"/"Tidak
Mengerti" (tracking understood), indikator di summary review
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
lesson_specs() hanya memindai home.md root sehingga lesson di
bab/<folder>/sub-home.md tidak pernah masuk tabel lessons. Akibatnya kolom
materi sub-bab hilang saat guru import/export siswa CSV.
- services/lesson_service.py: tambah find_all_sub_home_folders() (enumerate
level-1 folder di CONTENT_DIR berisi sub-home.md)
- services/lesson_registry.py: lesson_specs() gabungkan union root + sub-bab,
dedupe slug (root priority) — satu lesson entitas
- services/tests/test_lesson_registry.py: test unit + DB integration
Verifikasi: 3 passed, 2 skipped (unit); test_sync_includes_sub_bab_lessons
passed (DB); 58 passed total termasuk test_repositories + student_management
tanpa regresi.
The /bab/<folder> endpoint returned raw get_sub_home_data() output, so
lessons had no completed/locked fields and green checkmarks never
appeared. api_bab now reads the student token, injects progress via
get_ordered_lessons_with_learning_objectives (scoped to the folder's
sub-home.md), and computes lock status from prerequisites — matching
/lessons. The bab page load also forwards the student token, and tests
cover progress injection and prerequisite locking.
Lengkapi rencana sub-home (fitur bab sudah ada sejak 2f689af) dengan
perilaku sidebar/navigasi yang akurat per sub-folder:
- get_lessons()/get_ordered_lessons_with_learning_objectives() menerima
source_path opsional sehingga daftar materi dapat diambil dari
sub-home.md alih-alih home.md root
- api_lesson: ordered_lessons + prev/next di-scope ke sub-home.md bila
folder memilikinya, fallback ke daftar global home.md
- get_sub_home_data kini mtime-cached (bukan lru_cache) sehingga edit
sub-home.md langsung terlihat tanpa restart; edit juga meng-invalidate
find_lesson_file agar materi baru terdeteksi
Testing & docs:
- test_sub_home.py (unit): _read_md_cached mtime, find_sub_home_for_lesson,
get_sub_home_data refresh, ordered_lessons via source_path
- test_sub_home_api.py (integration): GET /bab/<folder> + scoped
ordered_lessons di /lesson/<slug>.json
- docs/13-content-sub-home.md (baru), README + docs/02-backend-flask.md
diperbarui dengan catatan fallback
- elemes.sh: perintah `test` + verifikasi tes sub-home di runclearbuild
Append &hideMenu=true to the circuitjs.html iframe src used by
renderCircuitEmbeds so lesson content embeds render clean without
the toolbar and menu bar. The embed path in CircuitEditor.svelte
is untouched, so the editor keeps its full toolbar.
Verified:
- Bundle contains embed URL (with hideMenu=true) and editor URL
(without) as separate variants
- svelte-check: 0 errors
- /lesson/rangkaian_dasar returns 200 on the running stack
- add @types/node for hooks.server process/env types
- fix katex auto-render import path (contrib/auto-render)
- declare global Web Bluetooth API types in ble-deployer
- guard simApi null in CircuitEditor autosave interval
- default-type imports for CodeEditor/CircuitEditor
- make lesson slug getter non-nullable
- add expected_flowchart to LessonContent type
- key lesson workspace by slug; drop phantom onReset prop
- guard CodeTab render when lesson data is null