Add shared card schemas layouts and renderer

This commit is contained in:
mpabi
2026-07-15 08:41:20 +02:00
commit 65299458ed
19 changed files with 7786 additions and 0 deletions
+586
View File
@@ -0,0 +1,586 @@
{
"$schema": "../../../schemas/card-source.schema.json",
"schema": "esc-card-source.v1",
"card": {
"id": "demo-01",
"series": "demo",
"number": "01",
"count": "02",
"slug": "pierwszy-krok",
"title": "DEMO-01: Jedno źródło, dwa formaty",
"topic": "Generowanie TeX i HTML z mapą efektów nauczania",
"project": "System kart pracy",
"subject": "Zajęcia projektowe",
"level": "przykład techniczny",
"dominant": "informatyka i kompetencje techniczne",
"revision_date": "15.07.2026",
"status": "Przykład",
"version": "v0.1",
"uuid": "00000000-0000-4000-8000-000000000001",
"author": "Zespół edukacyjny",
"year": "2026"
},
"generated": {
"tex": "build/tex/main.tex",
"html": "build/html/index.html",
"html_css": "build/html/style.css"
},
"template": "templates/karta-5b.json",
"front_page_break": false,
"metric_fill_fields": [
{
"label": "Uczeń",
"kind": "fill_in_line"
},
{
"label": "Klasa · data",
"kind": "fill_in_line"
}
],
"side_margin_tree_layout": {
"columns": [
{
"id": "zawodowe",
"label": "TECH",
"side": "left",
"tree": "WE -> EK -> KW",
"description": "Efekty techniczne po lewej stronie."
},
{
"id": "ogolne",
"label": "OG",
"side": "right",
"tree": "WE -> EN -> KW",
"description": "Efekty ogólne po prawej stronie."
}
]
},
"learning_effects": {
"DEMO.EN01": {
"bloom_level": "Zastosowanie",
"label": "Generowanie",
"text": "Uczeń generuje TeX i HTML z jednego pliku JSON.",
"assessment_criteria": [
"DEMO.KW01"
]
},
"DEMO.EK01": {
"bloom_level": "Analiza",
"label": "Spójność",
"text": "Uczeń rozpoznaje wspólny model danych i layoutu.",
"assessment_criteria": [
"DEMO.KW01"
]
}
},
"assessment_criteria": {
"DEMO.KW01": {
"text": "Generator kończy pracę kodem 0, a oba wyjścia zawierają tytuł, kroki i drzewka marginesowe.",
"learning_effects": [
"DEMO.EN01",
"DEMO.EK01"
]
}
},
"educational_requirements": {
"DEMO.WE01": {
"text": "Wygenerowanie spójnej karty pracy z jednego źródła.",
"label": "Jedno źródło",
"learning_effects": [
"DEMO.EN01",
"DEMO.EK01"
],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Każdy efekt ma co najmniej jedno mierzalne kryterium.",
"ogolne": [
{
"effect_ref": "DEMO.EN01",
"display": "EN IP WO 01.01.01",
"source": "IP",
"official": "01.01",
"local": "01",
"text": "Uczeń generuje TeX i HTML z jednego pliku JSON.",
"kind": "WO",
"tree_id": "DEMO.WE01.OG.IP.01.01.01",
"kw": [
{
"criterion_ref": "DEMO.KW01",
"display": "KW IP WS 01.01.01",
"source": "IP",
"kind": "WS",
"official": "01.01",
"local": "01",
"text": "Oba artefakty zawierają te same metadane i kroki."
}
]
}
],
"zawodowe": [
{
"effect_ref": "DEMO.EK01",
"display": "EK INF04 01.01.01",
"source": "I4",
"official": "01.01",
"local": "01",
"text": "Uczeń rozpoznaje wspólny model danych i layoutu.",
"kind": "EK",
"tree_id": "DEMO.WE01.TECH.I4.01.01.01",
"kw": [
{
"criterion_ref": "DEMO.KW01",
"display": "KW INF04 01.01.01.01",
"source": "I4",
"kind": "KW",
"official": "01.01.01",
"local": "01",
"text": "Uczeń wskazuje źródło treści, layout i oba artefakty."
}
]
}
]
}
}
},
"sections": [
{
"title": "Uruchomienie generatora",
"content_kind": "prose",
"content_tex": "Jedno źródło JSON jest renderowane do dwóch formatów.",
"educational_requirement_refs": [
"DEMO.WE01"
],
"learning_effect_refs": [
"DEMO.EN01",
"DEMO.EK01"
],
"assessment_criterion_refs": [
"DEMO.KW01"
],
"area_tree_refs": [
"DEMO.WE01.OG.IP.01.01.01",
"DEMO.WE01.TECH.I4.01.01.01"
],
"steps": [
{
"id": "K1",
"title": "Otwórz card_source.json i odczytaj metadane.",
"tree_refs": [
"DEMO.WE01.OG.IP.01.01.01",
"DEMO.WE01.TECH.I4.01.01.01"
],
"educational_requirement_refs": [
"DEMO.WE01"
],
"learning_effect_refs": [
"DEMO.EN01",
"DEMO.EK01"
],
"assessment_criterion_refs": [
"DEMO.KW01"
]
},
{
"id": "K2",
"title": "Uruchom generator i sprawdź oba wyjścia.",
"tree_refs": [
"DEMO.WE01.OG.IP.01.01.01",
"DEMO.WE01.TECH.I4.01.01.01"
],
"educational_requirement_refs": [
"DEMO.WE01"
],
"learning_effect_refs": [
"DEMO.EN01",
"DEMO.EK01"
],
"assessment_criterion_refs": [
"DEMO.KW01"
]
}
]
}
],
"tasks": {
"task01": {
"prompt_tex": "Wygeneruj TeX i HTML oraz porównaj tytuł i identyfikatory efektów.",
"criterion": "Oba pliki istnieją i pochodzą z tego samego źródła.",
"educational_requirement_refs": [
"DEMO.WE01"
],
"learning_effect_refs": [
"DEMO.EN01",
"DEMO.EK01"
],
"assessment_criterion_ref": "DEMO.KW01",
"links": {
"equations": [],
"figures": []
}
}
},
"tasks_order": [
"task01"
],
"mission": "Wygeneruj kartę pracy do TeX i HTML z jednego źródła, a następnie potwierdź, że oba formaty pokazują tę samą mapę efektów i te same kroki.",
"objectives": [
"Rozpoznasz rozdzielenie treści, layoutu i manifestu serii.",
"Wygenerujesz TeX i HTML jednym poleceniem.",
"Powiążesz krok z wymaganiem, efektem i kryterium."
],
"objective_refs": [
{
"tech": "01",
"og": "01"
},
{
"tech": "01",
"og": "01"
},
{
"tech": "01",
"og": "01"
}
],
"agenda": [
{
"time": "0--5 min",
"work": "Odczyt źródła i drzewek edukacyjnych."
},
{
"time": "5--10 min",
"work": "Generowanie TeX i HTML."
},
{
"time": "10--15 min",
"work": "Porównanie rezultatów i zapis PASS."
}
],
"hw_gate": {
"title": "Bramka wejścia",
"criteria": [
{
"check": "Python 3 jest dostępny.",
"evidence": "python3 --version"
},
{
"check": "Źródło JSON jest poprawne składniowo.",
"evidence": "python3 -m json.tool json/card_source.json"
}
]
},
"tech_stack": {
"software": [
{
"name": "Python",
"use": "walidacja i generowanie"
},
{
"name": "LaTeX",
"use": "skład PDF"
},
{
"name": "HTML/CSS",
"use": "wersja ekranowa i druk z przeglądarki"
}
],
"hardware": [
{
"name": "Komputer",
"use": "uruchomienie przykładu"
}
]
},
"theory_refs": {
"intro": "Treść i layout są osobnymi warstwami. Identyfikatory WE, EN/EK i KW tworzą graf powiązań, który renderer umieszcza na marginesach.",
"known_refs": [],
"new_concepts": [
{
"term": "źródło prawdy",
"definition": "Plik, z którego odtwarzamy wszystkie artefakty bez ręcznych poprawek."
},
{
"term": "layout",
"definition": "Kontrakt geometrii, komponentów i emiterów niezależny od treści karty."
}
]
},
"math_block": {
"title": "Kontrola liczby wyjść",
"tasks": [
{
"prompt": "Policz formaty generowane z jednego źródła.",
"equation_tex": "N_{wyjsc} = N_{TeX} + N_{HTML} = 1 + 1 = 2",
"answer_hint": "Dwa formaty, jedno źródło."
}
]
},
"parts": {
"a": {
"title": "CZĘŚĆ A -- model",
"body": "Sprawdź identyfikatory i zależności przed generowaniem."
},
"b": {
"title": "CZĘŚĆ B -- weryfikacja",
"body": "Porównaj TeX, HTML i wynik PDF."
}
},
"model_block": {
"title": "Model danych",
"notebook": "nie dotyczy",
"output_constants": "json/card_source.json",
"steps": [
"Odczytaj metadane karty.",
"Przejdź po relacji WE -> EN/EK -> KW.",
"Sprawdź tree_refs dla każdego kroku."
],
"constants": [
{
"name": "SOURCE_COUNT",
"value": "1"
},
{
"name": "OUTPUT_COUNT",
"value": "2"
}
]
},
"code_block": {
"title": "Do wykonania: render przykładu",
"context": "Pracujemy wyłącznie na plikach przykładowych w tym repozytorium.",
"blocks": [
{
"title": "Bloczek 1 -- GENERATOR",
"slug": "generator",
"goal": "Wytworzyć oba formaty i sprawdzić ich spójność.",
"context": "Kroki są zapisywane w JSON i emitowane do interaktywnego HTML.",
"web_steps": [
"Uruchom make render-example.",
"Otwórz build/html/index.html.",
"Sprawdź build/tex/main.tex.",
"Potwierdź obecność TECH, OG i kroku K2."
],
"web_commands": [
{
"label": "Render",
"command": "make render-example"
},
{
"label": "Kontrola",
"command": "make check"
}
],
"web_files": [
"json/card_source.json",
"build/tex/main.tex",
"build/html/index.html"
],
"web_evidence": [
"Polecenie kończy się kodem 0.",
"Oba wyjścia zawierają tytuł karty."
],
"web_safety": [
"Nie edytuj ręcznie plików w build/."
],
"columns": [
{
"title": "Artefakty",
"items": [
"build/tex/main.tex",
"build/html/index.html",
"build/html/style.css"
]
},
{
"title": "Procedura",
"items": [
"render",
"kontrola marginesów",
"kontrola kroków"
]
},
{
"title": "Uczeń oddaje",
"items": [
"wynik PASS",
"krótkie porównanie obu formatów"
]
}
],
"pass_condition": "TeX i HTML istnieją oraz zawierają te same metadane."
}
]
},
"container_test": {
"title": "Test bez sprzętu",
"commands": [
"make render-example",
"make check"
],
"pass_condition": "Wszystkie kontrole kończą się kodem 0."
},
"bom": [
{
"item": "Python 3",
"check": "Interpreter dostępny."
},
{
"item": "latexmk",
"check": "Wymagany tylko dla PDF."
}
],
"safety_rules": [
{
"title": "Jedno źródło",
"body": "Nie poprawiaj osobno TeX i HTML; popraw card_source.json lub layout."
},
{
"title": "Stabilne identyfikatory",
"body": "Nie zmieniaj tree_id po opublikowaniu karty bez migracji odwołań."
}
],
"reference_settings": [
{
"test": "layout",
"dps": "karta-5b",
"xy": "TeX + HTML"
}
],
"figures": [],
"connection_section": {
"title": "Przepływ danych: JSON -> renderer -> TeX/HTML",
"intro": "Źródło treści i layout są wczytywane osobno, a następnie przekazywane do dwóch emiterów.",
"pin_table": [
{
"rp2350": "card_source.json",
"isolator_a": "walidacja",
"isolator_b": "emiter",
"xy": "main.tex / index.html"
}
],
"parameters": [
"Treść jest niezależna od geometrii.",
"Oba emitery korzystają z przygotowanego modelu danych."
],
"warnings": [
"Ręczna zmiana artefaktu znika przy kolejnym generowaniu."
],
"source_note": "Repozytorium card-layouts jest źródłem generatora, schematów i layoutów."
},
"hardware_procedure": [
{
"step": "1",
"action": "Uruchom make render-example.",
"condition": "Generator zwraca kod 0."
},
{
"step": "2",
"action": "Otwórz HTML i sprawdź marginesy TECH/OG oraz kroki.",
"condition": "Widoczne są oba drzewka i lista kroków."
},
{
"step": "3",
"action": "Złóż PDF poleceniem make pdf-example.",
"condition": "Powstaje main.pdf bez błędu LaTeX."
}
],
"observation_table": {
"title": "Karta kontroli artefaktów",
"columns": [
"Artefakt",
"Oczekiwany element",
"Wynik"
],
"rows": [
{
"cells": [
"HTML",
"tytuł, TECH, OG, kroki",
""
]
},
{
"cells": [
"TeX/PDF",
"tytuł, TECH, OG, procedura",
""
]
}
]
},
"troubleshooting": [
{
"symptom": "Brak layoutu",
"hypothesis": "Błędna ścieżka template.",
"action": "Sprawdź pole template i katalog templates/.",
"result": ""
},
{
"symptom": "Błąd tree_ref",
"hypothesis": "Krok wskazuje nieistniejące drzewko.",
"action": "Porównaj tree_refs z educational_requirements.*.learning_tree.",
"result": ""
}
],
"analysis_tasks": [
"Wyjaśnij, dlaczego treść i layout są osobnymi plikami.",
"Wskaż relację między DEMO.WE01, DEMO.EN01 i DEMO.KW01.",
"Porównaj elementy obecne w TeX i HTML."
],
"team_decision": {
"title": "Decyzja zespołu",
"questions": [
"Który layout wybieramy?",
"Jakie były alternatywy?",
"Jak potwierdziliśmy oba formaty?",
"Który commit dokumentuje decyzję?"
]
},
"git_gate": {
"title": "Brama wyjścia",
"criteria": [
{
"criterion": "JSON przechodzi walidację generatora.",
"evidence": "make check"
},
{
"criterion": "TeX i HTML zostały wygenerowane.",
"evidence": "examples/card/build/"
},
{
"criterion": "PDF składa się bez błędu.",
"evidence": "main.pdf"
}
]
},
"session_record": {
"title": "Rekord pracy",
"files": [
{
"path": "README.md",
"purpose": "opis wyniku i poleceń"
}
],
"timeline_sources": [
"git log --oneline",
"wynik make check"
]
},
"ai_rules": {
"allowed": [
"wyjaśnienie błędu walidacji",
"review spójności identyfikatorów"
],
"forbidden": [
"fabrykowanie wyniku PASS",
"ręczna poprawa wygenerowanego pliku zamiast źródła"
],
"student_owns": [
"treść kroków",
"mapowanie efektów",
"wynik kontroli"
],
"log_path": "ai-log.md"
},
"references": []
}