vault backup: 2025-12-26 02:09:22
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
This commit is contained in:
45
.github/copilot-instructions.md
vendored
Normal file
45
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
## Architecture
|
||||
- Notes live in [content](content) and ship to [public](public) via Quartz under [quartz](quartz); Django lives in [stroma](stroma) and hosts the quiz and ingest services.
|
||||
- Static Quartz pages are configured through [quartz.config.ts](quartz.config.ts) and layouts in [quartz.layout.ts](quartz.layout.ts), while Django templates sit in [stroma/templates](stroma/templates) with HTMX-like partials in [stroma/templates/partials](stroma/templates/partials).
|
||||
- Data flows: Obsidian markdown → question importer ([stroma/quiz/utils/importer.py](stroma/quiz/utils/importer.py#L1-L220)) → relational models ([stroma/quiz/models](stroma/quiz/models)) → quiz/session views → rendered partials front-end.
|
||||
|
||||
## Quartz Site Workflow
|
||||
- Use Node 22+ and npm 10.9+ as enforced in [package.json](package.json#L1-L60); run `npm install` once, then `npm run docs` to build+serve Quartz against the `content` dir.
|
||||
- The CLI is exposed via `npm run quartz` / `npx quartz ...` and reads custom config/theme in [quartz.config.ts](quartz.config.ts) plus layout definition in [quartz.layout.ts](quartz.layout.ts).
|
||||
- [content](content) follows Obsidian conventions (Swedish folder names, embedded PDFs/CSV) and Quartz ignores private/templates per the `ignorePatterns` value.
|
||||
- When editing markdown, keep Obsidian-flavored syntax and frontmatter tags because the quiz importer keys off tags like `frågetyp/mcq`.
|
||||
|
||||
## Django Quiz Service
|
||||
- The project root is [stroma](stroma); run it with `uv run python manage.py runserver` (Python 3.13, deps in [stroma/pyproject.toml](stroma/pyproject.toml)).
|
||||
- Core models: `QuizSession`, `QuizResult`, `QuizUser`, `Question`, `Tag`, `Exam`, etc. in [stroma/quiz/models](stroma/quiz/models); sessions filter questions via [stroma/quiz/views/get_session_questions_view.py](stroma/quiz/views/get_session_questions_view.py#L1-L35).
|
||||
- Primary views live in [stroma/quiz/views](stroma/quiz/views) and always expect `request.quiz_user`; e.g. [stroma/quiz/views/get_next_question_view.py](stroma/quiz/views/get_next_question_view.py#L1-L40) renders partials consumed by the `quiz_mode` page.
|
||||
- URL routing: [stroma/quiz/urls.py](stroma/quiz/urls.py) registers quiz endpoints under `/quiz/`, and [stroma/quiz/quiz_urls.py](stroma/quiz/quiz_urls.py#L1-L25) defines per-view paths (`session/<id>/question`, `/next/`, `/submit/`, etc.).
|
||||
|
||||
## Question Import Pipeline
|
||||
- [stroma/quiz/utils/importer.py](stroma/quiz/utils/importer.py) parses Obsidian markdown, infers question type via `tags`, and stores options/matching_data plus tag slugs; the importer respects file mtimes and tracks stats.
|
||||
- [stroma/quiz/utils/watcher.py](stroma/quiz/utils/watcher.py) plus [stroma/quiz/apps.py](stroma/quiz/apps.py#L1-L20) spin up a background Watchdog thread on startup (unless running management commands/tests) targeting `settings.QUESTION_WATCH_PATH` from [stroma/settings.py](stroma/settings.py#L1-L70).
|
||||
- Management commands `uv run python manage.py import_questions [--folder ... --force]` and `populate_exams` live in [stroma/quiz/management/commands](stroma/quiz/management/commands) for bulk ingest/backfilling.
|
||||
- The importer expects spoiler blocks for answers and tags like `frågetyp/mcq`; missing answers mark the file as TODO and skip DB writes, so keep metadata consistent.
|
||||
|
||||
## File Uploads & Assets
|
||||
- The `file` app exposes `/file/upload/` + `/file/upload/api/` via [stroma/file/urls.py](stroma/file/urls.py); UI renders from [stroma/file/views/upload_files_page_view.py](stroma/file/views/upload_files_page_view.py#L1-L7).
|
||||
- Upload handling in [stroma/file/views/upload_files_api_view.py](stroma/file/views/upload_files_api_view.py#L1-L130) mirrors the client’s folder hierarchy, infers MIME types, stores text content when possible, and persists binaries under `uploads/`.
|
||||
- Metadata/state for uploaded artifacts sit in [stroma/file/models/file_model.py](stroma/file/models/file_model.py#L1-L40) and are owned by `quiz.QuizUser`.
|
||||
|
||||
## Session & Request Patterns
|
||||
- [stroma/quiz/middleware.py](stroma/quiz/middleware.py#L1-L21) auto-creates `QuizUser` records tied to Django session keys and attaches `request.quiz_user`; every view assumes this, so never bypass the middleware.
|
||||
- `QuizResult` enforces one row per user+question via `unique_together` ([stroma/quiz/models/quiz_result_model.py](stroma/quiz/models/quiz_result_model.py#L1-L27)) and normalization logic in [submit_answer_view](stroma/quiz/views/submit_answer_view.py#L1-L60); reuse `update_or_create` when recording answers.
|
||||
- Navigational/partial views such as [quiz_question_view](stroma/quiz/views/quiz_question_view.py#L1-L60) and [navigate_question_view](stroma/quiz/views/navigate_question_view.py#L1-L60) rely on consistent ordering from `get_session_questions`; maintain that helper when altering filtering behavior.
|
||||
|
||||
## Testing & Tooling
|
||||
- Python deps/tests are run through `uv` (`uv sync`, then `uv run pytest`) per [stroma/AGENT.md](stroma/AGENT.md) and versions pinned in [stroma/pyproject.toml](stroma/pyproject.toml#L1-L20).
|
||||
- Pytest config in [stroma/pytest.ini](stroma/pytest.ini#L1-L20) enables `--reuse-db` and short tracebacks; [stroma/conftest.py](stroma/conftest.py#L1-L70) switches to in-memory SQLite and provides markdown fixtures for parser tests.
|
||||
- Comprehensive integration coverage exists in [stroma/quiz/tests/test_views.py](stroma/quiz/tests/test_views.py#L1-L210); extend these when touching quiz flows (session creation, submissions, difficulty ratings).
|
||||
- SQLite WAL is default (see [stroma/settings.py](stroma/settings.py#L30-L65)); when debugging concurrency, clear `db.sqlite3-wal/shm` files before reruns.
|
||||
|
||||
## Coding Conventions
|
||||
- Follow [stroma/AGENT.md](stroma/AGENT.md): Obsidian-flavored Markdown, no extra docstrings/comments unless asked, favor early returns, narrow `try/except`, and keep regexes as upper-case `_RE` constants with inline comments.
|
||||
- Use type hints everywhere, prefer function-based Django views, and leverage django-stubs/pytest-django for typing/tests.
|
||||
- When working in markdown ingestion, maintain tag-driven semantics (`frågetyp/*`, completion stats) and keep regex patterns centralized in parser modules.
|
||||
- Tests should live beside implementations (e.g., `quiz/utils/tests`) and use parametrized `pytest` subtests when iterating over inputs.
|
||||
- Keep new dependencies declared in `pyproject.toml` (Python) or `package.json` (Quartz) and prefer latest stable versions unless compatibility dictates otherwise.
|
||||
Reference in New Issue
Block a user