eduevidence 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +506 -0
- package/README.zh-CN.md +434 -0
- package/SKILL.md +195 -0
- package/bin/eduevidence.js +127 -0
- package/domains/education/manifest.json +183 -0
- package/domains/education/outcome_taxonomy.json +127 -0
- package/domains/manifest.json +26 -0
- package/domains/policy/frame.schema.json +234 -0
- package/domains/policy/manifest.json +10 -0
- package/domains/policy/methodology_checklist.json +109 -0
- package/domains/policy/outcome_taxonomy.json +53 -0
- package/domains/policy/references/causal-identification.md +45 -0
- package/domains/policy/references/cost-evidence.md +44 -0
- package/domains/policy/references/equity.md +42 -0
- package/domains/policy/references/evidence-hierarchy.md +41 -0
- package/domains/policy/references/implementation-evidence.md +47 -0
- package/eduevidence_cli.py +26 -0
- package/engine/__init__.py +11 -0
- package/engine/__pycache__/__init__.cpython-312.pyc +0 -0
- package/engine/__pycache__/analysis.cpython-312.pyc +0 -0
- package/engine/__pycache__/bias.cpython-312.pyc +0 -0
- package/engine/__pycache__/briefs.cpython-312.pyc +0 -0
- package/engine/__pycache__/capabilities.cpython-312.pyc +0 -0
- package/engine/__pycache__/citation_check.cpython-312.pyc +0 -0
- package/engine/__pycache__/contracts.cpython-312.pyc +0 -0
- package/engine/__pycache__/datasets.cpython-312.pyc +0 -0
- package/engine/__pycache__/events.cpython-312.pyc +0 -0
- package/engine/__pycache__/evidence_graph.cpython-312.pyc +0 -0
- package/engine/__pycache__/evidence_review.cpython-312.pyc +0 -0
- package/engine/__pycache__/evidencecore.cpython-312.pyc +0 -0
- package/engine/__pycache__/gap_lens.cpython-312.pyc +0 -0
- package/engine/__pycache__/gaps.cpython-312.pyc +0 -0
- package/engine/__pycache__/graph_store.cpython-312.pyc +0 -0
- package/engine/__pycache__/graph_validate.cpython-312.pyc +0 -0
- package/engine/__pycache__/ids.cpython-312.pyc +0 -0
- package/engine/__pycache__/library.cpython-312.pyc +0 -0
- package/engine/__pycache__/library_builtin.cpython-312.pyc +0 -0
- package/engine/__pycache__/living.cpython-312.pyc +0 -0
- package/engine/__pycache__/log.cpython-312.pyc +0 -0
- package/engine/__pycache__/meta_analysis.cpython-312.pyc +0 -0
- package/engine/__pycache__/meta_synthesis.cpython-312.pyc +0 -0
- package/engine/__pycache__/migration.cpython-312.pyc +0 -0
- package/engine/__pycache__/mode_router.cpython-312.pyc +0 -0
- package/engine/__pycache__/paths.cpython-312.pyc +0 -0
- package/engine/__pycache__/pilot.cpython-312.pyc +0 -0
- package/engine/__pycache__/planner.cpython-312.pyc +0 -0
- package/engine/__pycache__/project.cpython-312.pyc +0 -0
- package/engine/__pycache__/projections.cpython-312.pyc +0 -0
- package/engine/__pycache__/robustness.cpython-312.pyc +0 -0
- package/engine/__pycache__/run.cpython-312.pyc +0 -0
- package/engine/__pycache__/semantics.cpython-312.pyc +0 -0
- package/engine/__pycache__/study_design.cpython-312.pyc +0 -0
- package/engine/__pycache__/synthesis.cpython-312.pyc +0 -0
- package/engine/__pycache__/tribunal.cpython-312.pyc +0 -0
- package/engine/__pycache__/update.cpython-312.pyc +0 -0
- package/engine/__pycache__/versions.cpython-312.pyc +0 -0
- package/engine/analysis.py +308 -0
- package/engine/bias.py +178 -0
- package/engine/briefs.py +106 -0
- package/engine/capabilities.py +99 -0
- package/engine/citation_check.py +192 -0
- package/engine/contracts.py +117 -0
- package/engine/datasets.py +165 -0
- package/engine/events.py +67 -0
- package/engine/evidence_graph.py +571 -0
- package/engine/evidence_review.py +88 -0
- package/engine/evidencecore.py +182 -0
- package/engine/gap_lens.py +132 -0
- package/engine/gaps.py +169 -0
- package/engine/graph_store.py +335 -0
- package/engine/graph_validate.py +87 -0
- package/engine/ids.py +77 -0
- package/engine/library.py +268 -0
- package/engine/library_builtin.py +301 -0
- package/engine/living.py +671 -0
- package/engine/log.py +39 -0
- package/engine/meta_analysis.py +333 -0
- package/engine/meta_synthesis.py +111 -0
- package/engine/migration.py +397 -0
- package/engine/mode_router.py +72 -0
- package/engine/paths.py +15 -0
- package/engine/pilot.py +368 -0
- package/engine/planner.py +126 -0
- package/engine/project.py +118 -0
- package/engine/projections.py +240 -0
- package/engine/robustness.py +109 -0
- package/engine/run.py +85 -0
- package/engine/semantics.py +135 -0
- package/engine/study_design.py +87 -0
- package/engine/synthesis.py +187 -0
- package/engine/tribunal.py +408 -0
- package/engine/update.py +113 -0
- package/engine/versions.py +12 -0
- package/install.sh +510 -0
- package/integrations/__init__.py +1 -0
- package/integrations/__pycache__/__init__.cpython-312.pyc +0 -0
- package/integrations/__pycache__/agent_mcp.cpython-312.pyc +0 -0
- package/integrations/__pycache__/smart_web_fetch.cpython-312.pyc +0 -0
- package/integrations/agent_mcp.py +856 -0
- package/integrations/smart_web_fetch.py +59 -0
- package/package.json +50 -0
- package/pyproject.toml +55 -0
- package/references/applicability-policy.md +88 -0
- package/references/education-framing.md +132 -0
- package/references/effect_size_formulas.md +35 -0
- package/references/evaluation-design.md +111 -0
- package/references/evidence-quality.md +79 -0
- package/references/grade_framework.md +29 -0
- package/references/intervention-design.md +98 -0
- package/references/methodology-audit.md +103 -0
- package/references/outcome-taxonomy.md +106 -0
- package/references/retrieval-protocol.md +142 -0
- package/references/skeptic-protocol.md +93 -0
- package/references/social_science_pitfalls.md +48 -0
- package/references/source-validity.md +140 -0
- package/references/tribunal-policy.md +112 -0
- package/references/wwc_standards.md +29 -0
- package/retrieval/__init__.py +1 -0
- package/retrieval/__pycache__/__init__.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/corpus_store.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/dedupe.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/failures.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/fetch.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/search.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/source.cpython-312.pyc +0 -0
- package/retrieval/__pycache__/validate.cpython-312.pyc +0 -0
- package/retrieval/corpus_store.py +181 -0
- package/retrieval/dedupe.py +127 -0
- package/retrieval/failures.py +90 -0
- package/retrieval/fetch.py +435 -0
- package/retrieval/search.py +493 -0
- package/retrieval/source.py +160 -0
- package/retrieval/validate.py +257 -0
- package/schemas/agent-mcp-approval.schema.json +57 -0
- package/schemas/chart-spec.schema.json +88 -0
- package/schemas/cross-model-review.schema.json +28 -0
- package/schemas/education-frame.schema.json +106 -0
- package/schemas/evaluation.schema.json +35 -0
- package/schemas/evidence.schema.json +81 -0
- package/schemas/fetch-result.schema.json +119 -0
- package/schemas/intervention.schema.json +46 -0
- package/schemas/methodology.schema.json +102 -0
- package/schemas/report-result.schema.json +381 -0
- package/schemas/report-spec.schema.json +130 -0
- package/schemas/source.schema.json +311 -0
- package/schemas/v2/analysis-plan.schema.json +28 -0
- package/schemas/v2/analysis-run.schema.json +33 -0
- package/schemas/v2/claim.schema.json +26 -0
- package/schemas/v2/dataset-asset.schema.json +40 -0
- package/schemas/v2/decision-snapshot.schema.json +53 -0
- package/schemas/v2/evidence-link.schema.json +38 -0
- package/schemas/v2/finding.schema.json +47 -0
- package/schemas/v2/graph-revision.schema.json +30 -0
- package/schemas/v2/knowledge-gap.schema.json +40 -0
- package/schemas/v2/methodology-audit.schema.json +30 -0
- package/schemas/v2/outcome.schema.json +18 -0
- package/schemas/v2/project.schema.json +31 -0
- package/schemas/v2/research-intent.schema.json +24 -0
- package/schemas/v2/run.schema.json +43 -0
- package/schemas/v2/source.schema.json +24 -0
- package/schemas/v2/study-design.schema.json +67 -0
- package/schemas/v2/study.schema.json +37 -0
- package/schemas/v3/pilot-outcome.schema.json +132 -0
- package/schemas/v3/run-manifest.schema.json +193 -0
- package/schemas/v3/synthesis.schema.json +86 -0
- package/schemas/v4/drift-report.schema.json +66 -0
- package/schemas/v4/evidence-library.schema.json +42 -0
- package/schemas/v4/living-subscription.schema.json +55 -0
- package/schemas/v4/meta-analysis.schema.json +152 -0
- package/schemas/verdict.schema.json +56 -0
- package/scripts/__init__.py +0 -0
- package/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark_evaluator.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark_judge.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark_routing.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark_v2.cpython-312.pyc +0 -0
- package/scripts/__pycache__/benchmark_v3.cpython-312.pyc +0 -0
- package/scripts/__pycache__/build_result.cpython-312.pyc +0 -0
- package/scripts/__pycache__/claim_audit.cpython-312.pyc +0 -0
- package/scripts/__pycache__/complexity_gate.cpython-312.pyc +0 -0
- package/scripts/__pycache__/compute_confidence.cpython-312.pyc +0 -0
- package/scripts/__pycache__/dashboard_server.cpython-312.pyc +0 -0
- package/scripts/__pycache__/did_regression.cpython-312.pyc +0 -0
- package/scripts/__pycache__/effect_calculator.cpython-312.pyc +0 -0
- package/scripts/__pycache__/evidence_matrix.cpython-312.pyc +0 -0
- package/scripts/__pycache__/evidence_score.cpython-312.pyc +0 -0
- package/scripts/__pycache__/evidence_semantics.cpython-312.pyc +0 -0
- package/scripts/__pycache__/fetch_benchmark.cpython-312.pyc +0 -0
- package/scripts/__pycache__/lint_report_layout.cpython-312.pyc +0 -0
- package/scripts/__pycache__/orchestrator.cpython-312.pyc +0 -0
- package/scripts/__pycache__/pre_verdict_gate.cpython-312.pyc +0 -0
- package/scripts/__pycache__/recompute_demo_quality.cpython-312.pyc +0 -0
- package/scripts/__pycache__/render_report.cpython-312.pyc +0 -0
- package/scripts/__pycache__/render_report_html.cpython-312.pyc +0 -0
- package/scripts/__pycache__/run_workspace.cpython-312.pyc +0 -0
- package/scripts/__pycache__/skill_lint.cpython-312.pyc +0 -0
- package/scripts/__pycache__/startup_probe.cpython-312.pyc +0 -0
- package/scripts/__pycache__/sync_killer_demo_report.cpython-312.pyc +0 -0
- package/scripts/__pycache__/test_adversarial_empirical.cpython-312-pytest-9.0.2.pyc +0 -0
- package/scripts/__pycache__/test_adversarial_empirical.cpython-312-pytest-9.1.1.pyc +0 -0
- package/scripts/__pycache__/validate_schema.cpython-312.pyc +0 -0
- package/scripts/audit_dois.py +292 -0
- package/scripts/bake_pack.sh +37 -0
- package/scripts/benchmark.py +183 -0
- package/scripts/benchmark_evaluator.py +371 -0
- package/scripts/benchmark_judge.py +535 -0
- package/scripts/benchmark_routing.py +120 -0
- package/scripts/benchmark_v2.py +304 -0
- package/scripts/benchmark_v3.py +552 -0
- package/scripts/build_esl_artifacts.py +1921 -0
- package/scripts/build_evidence_library.py +307 -0
- package/scripts/build_killer_demo.py +295 -0
- package/scripts/build_result.py +311 -0
- package/scripts/check_version_consistency.py +96 -0
- package/scripts/citation_check.py +123 -0
- package/scripts/claim_audit.py +157 -0
- package/scripts/complexity_gate.py +180 -0
- package/scripts/compute_confidence.py +176 -0
- package/scripts/dashboard_server.py +536 -0
- package/scripts/did_regression.py +315 -0
- package/scripts/effect_calculator.py +99 -0
- package/scripts/enrich_projects_human_and_lieflat.py +315 -0
- package/scripts/evidence_matrix.py +129 -0
- package/scripts/evidence_score.py +234 -0
- package/scripts/evidence_semantics.py +87 -0
- package/scripts/fetch_benchmark.py +177 -0
- package/scripts/generate_metrics.py +99 -0
- package/scripts/generate_new_projects.py +686 -0
- package/scripts/generate_promo.py +192 -0
- package/scripts/lint_report_layout.py +182 -0
- package/scripts/orchestrator.py +1456 -0
- package/scripts/pre_verdict_gate.py +513 -0
- package/scripts/quickstart.py +121 -0
- package/scripts/rebake_all_5themes.py +88 -0
- package/scripts/recompute_demo_quality.py +205 -0
- package/scripts/render_report.py +270 -0
- package/scripts/render_report_html.py +356 -0
- package/scripts/retraction_watch.py +110 -0
- package/scripts/run_workspace.py +337 -0
- package/scripts/serve_web.py +54 -0
- package/scripts/skill_lint.py +150 -0
- package/scripts/startup_probe.py +265 -0
- package/scripts/sync_killer_demo_report.py +270 -0
- package/scripts/test_adversarial_empirical.py +541 -0
- package/scripts/validate_schema.py +256 -0
- package/skill/agents/education-planner.md +80 -0
- package/skill/agents/evaluation-designer.md +74 -0
- package/skill/agents/evidence-analyst.md +106 -0
- package/skill/agents/evidence-judge.md +111 -0
- package/skill/agents/evidence-retriever.md +80 -0
- package/skill/agents/intervention-designer.md +82 -0
- package/skill/agents/method-reviewer.md +104 -0
- package/skill/agents/skeptic.md +89 -0
- package/skill/sub-skills/aihot-trend-analysis/SKILL.md +31 -0
- package/skill/sub-skills/contradiction-analysis/SKILL.md +17 -0
- package/skill/sub-skills/data-analysis/SKILL.md +23 -0
- package/skill/sub-skills/ethics-review/SKILL.md +25 -0
- package/skill/sub-skills/evidence-extraction/SKILL.md +19 -0
- package/skill/sub-skills/evidence-review/SKILL.md +18 -0
- package/skill/sub-skills/gap-analysis/SKILL.md +25 -0
- package/skill/sub-skills/literature-review/SKILL.md +21 -0
- package/skill/sub-skills/methodology-audit/SKILL.md +20 -0
- package/skill/sub-skills/report-generation/SKILL.md +51 -0
- package/skill/sub-skills/research-planning/SKILL.md +21 -0
- package/skill/sub-skills/study-design/SKILL.md +16 -0
- package/skill/task-briefs/adjudicate.md +17 -0
- package/skill/task-briefs/audit.md +15 -0
- package/skill/task-briefs/challenge.md +15 -0
- package/skill/task-briefs/evaluate.md +13 -0
- package/skill/task-briefs/extract.md +16 -0
- package/skill/task-briefs/frame.md +17 -0
- package/skill/task-briefs/intervene.md +14 -0
- package/skill/task-briefs/present.md +16 -0
- package/skill/task-briefs/retrieve.md +15 -0
- package/visualization/eduevidence-report/assets/base.css +337 -0
- package/visualization/eduevidence-report/motion/motion.css +157 -0
- package/visualization/eduevidence-report/motion/motion.js +107 -0
- package/visualization/eduevidence-report/references/bilingual-style.md +7 -0
- package/visualization/eduevidence-report/references/component-catalog.md +145 -0
- package/visualization/eduevidence-report/references/evidence-expansion.md +65 -0
- package/visualization/eduevidence-report/references/full-report-outline.md +86 -0
- package/visualization/eduevidence-report/references/layout-constraints.md +63 -0
- package/visualization/eduevidence-report/references/lieflat-composition.md +79 -0
- package/visualization/eduevidence-report/references/motion-system.md +31 -0
- package/visualization/eduevidence-report/schemas/adapter-envelope.schema.json +22 -0
- package/visualization/eduevidence-report/schemas/visual-layout.schema.json +87 -0
- package/visualization/eduevidence-report/scripts/__pycache__/adapter_contract.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/build_artifact_manifest.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/build_charts.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/build_figures.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/build_infographics.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/build_report.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/charts_data.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/lieflat_engine.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/__pycache__/zh_labels.cpython-312.pyc +0 -0
- package/visualization/eduevidence-report/scripts/adapter_contract.py +72 -0
- package/visualization/eduevidence-report/scripts/build_artifact_manifest.py +70 -0
- package/visualization/eduevidence-report/scripts/build_charts.py +283 -0
- package/visualization/eduevidence-report/scripts/build_figures.py +515 -0
- package/visualization/eduevidence-report/scripts/build_infographics.py +268 -0
- package/visualization/eduevidence-report/scripts/build_report.py +3211 -0
- package/visualization/eduevidence-report/scripts/charts_data.py +617 -0
- package/visualization/eduevidence-report/scripts/check_mobile_layout.js +220 -0
- package/visualization/eduevidence-report/scripts/lieflat_engine.py +852 -0
- package/visualization/eduevidence-report/scripts/zh_labels.py +245 -0
- package/visualization/eduevidence-report/themes/academic.css +94 -0
- package/visualization/eduevidence-report/themes/claude.css +96 -0
- package/visualization/eduevidence-report/themes/datalab-dark.css +147 -0
- package/visualization/eduevidence-report/themes/datalab.css +151 -0
- package/visualization/eduevidence-report/themes/presentation.css +140 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Lieflat Composition — 注册表、契约与推荐组合
|
|
2
|
+
|
|
3
|
+
EduEvidence 的 Lieflat 画廊是**数据驱动的手作图表组合**:上游 AI 按数据形状自由选型(只能选注册表内图型),渲染器从 `result.json` 提取真实数据渲染成主题化内联 SVG。AI 不直接写数值——所有数字经 `scripts/charts_data.py` 提取器出数,完整性门 `lieflat_data_bound` 逐值核对溯源。
|
|
4
|
+
|
|
5
|
+
> 上游规范 = `visualization/lieflat-charts/`(Lupi 正本 + mono-tokens)。本文件只记录 EduEvidence 特有规则。
|
|
6
|
+
|
|
7
|
+
## 1. 注册表(type ↔ 目录编号 ↔ 数据形状 ↔ 提取器)
|
|
8
|
+
|
|
9
|
+
| `type` | 目录编号 | 数据形状 | 提取器(scripts/charts_data.py) |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `forest_plot` | FOREST-PLOT (publication figure) | 逐研究 Hedges' g + 95% CI(meta.forest 或 evidence.effect_size) | `meta.forest` |
|
|
12
|
+
| `dot_cascade` | L2 Dot Cascade | 逐研究效应量排序(g + N) | `evidence.ranked_effects` |
|
|
13
|
+
| `bubble_almanac` | L9 Bubble Almanac | 年份 × 结果维度,气泡面积 ∝ 研究数 | `evidence.year_x_dimension` |
|
|
14
|
+
| `jitter_strip` | G15 Jitter Strip | 分组逐条 g 分布(每点一篇研究) | `evidence.grouped_distribution` |
|
|
15
|
+
| `parallel_coordinates` | L20 Parallel Coordinates | 同一批研究跨 g / N / 质量 / 年份 | `evidence.multidim_top` |
|
|
16
|
+
| `hundred_field` | L14 Hundred Field | 100% 构成(单位 = 1 篇研究,总数 ≤100) | `evidence.study_type_composition` |
|
|
17
|
+
| `tick_donut` | F4 Tick Donut | 100% 构成(100 ticks ∝ 份额) | `evidence.wwc_composition` |
|
|
18
|
+
| `tick_rows` | F5 Tick Rows | 各结果正向/负向/零效应计数(每点 1 条证据) | `outcomes.direction_counts` |
|
|
19
|
+
| `rung_bars` | F1 Rung Bars | 各结果方向计数(每格 1 条证据,竖排) | `outcomes.direction_counts` |
|
|
20
|
+
| `paired_rungs` | F6 Paired Rungs | 每结果正负两列对比 | `outcomes.paired_counts` |
|
|
21
|
+
| `brand_spectrum` | L7 Brand Spectrum | 双极维度:位置 = (正向 − 负向)÷ 方向计数 | `outcomes.bipolar_axes` |
|
|
22
|
+
| `barcode_lollipop` | L3 Barcode Lollipop | 16 周 × 阶段归属(柱高 = 阶段序号,无逐日数据不伪造) | `intervention.phase_weeks` |
|
|
23
|
+
| `launch_fan` | L1 Launch Fan | 干预阶段与活动权重(权重 = 活动条数) | `intervention.activity_weights` |
|
|
24
|
+
| `dotty_matrix` | L8 Dotty Matrix | 阶段 × 网格 × 活动(每点 = 1 项活动,强度均匀) | `intervention.phase_groups` |
|
|
25
|
+
| `tick_gauge` | F11 Tick Gauge | 单值 0–100%(决策置信度) | `decision.confidence_score` |
|
|
26
|
+
| `ballot_tally` | L15 Ballot Tally | 各方法学检查项独立计票(每 tick = 1 条审计结论) | `methodology.flag_rates` |
|
|
27
|
+
| `matrix_heat` | L16 Matrix Heat | 年份 × 结果维度 × 计数 | `evidence.year_x_outcome_counts` |
|
|
28
|
+
|
|
29
|
+
未注册 `type` → 该条被丢弃并写入 `report_spec.json` 的 `visualization_decisions.lieflat_gallery.rejected`,**不静默回退**。M1/M2 地图与 B1–B3 交互大图不进入 EduEvidence 默认画廊。
|
|
30
|
+
|
|
31
|
+
## 2. `visual_layout` 条目契约
|
|
32
|
+
|
|
33
|
+
写入 `result.json` 与 `result.zh.json` 的 `visual_layout`(两份文件条目完全相同,双语文本内嵌于每条):
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"chart_id": "lieflat-dot-cascade.svg",
|
|
38
|
+
"type": "dot_cascade",
|
|
39
|
+
"catalog_ref": "L2 Dot Cascade",
|
|
40
|
+
"title_zh": "16 篇写作实证的效应量梯队级联",
|
|
41
|
+
"title_en": "Ranked effect-size cascade of 16 writing studies",
|
|
42
|
+
"subtitle_zh": "按 g 降序 · 圆点高度 ∝ |g| · 顶部数字 = g · 悬停读样本量",
|
|
43
|
+
"subtitle_en": "Sorted by g · dot height ∝ |g| · top number = g · hover for sample size",
|
|
44
|
+
"caption_zh": "梯队数值来自 evidence.effect_size.value 与 sample_size。",
|
|
45
|
+
"caption_en": "Cascade values from evidence.effect_size.value and sample_size.",
|
|
46
|
+
"source": "evidence.ranked_effects",
|
|
47
|
+
"params": {"limit": 12}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
规则:
|
|
52
|
+
|
|
53
|
+
- `chart_id` 唯一;缺省 = `lieflat-<type>.svg`;与学术图键(`outcome-comparison.svg` 等)冲突时自动加 `lieflat-` 前缀。
|
|
54
|
+
- `type` 必须在注册表内;`catalog_ref` 写错只告警并采用注册表值。
|
|
55
|
+
- `title/subtitle/caption` 双语齐备(旧式 `title/subtitle` 双语共用被兼容但告警)。
|
|
56
|
+
- `params` 白名单:`forest_plot{max_studies}`、`dot_cascade/jitter_strip/parallel_coordinates{limit}`、`launch_fan{max_items}`、`tick_rows/rung_bars/paired_rungs/brand_spectrum{outcomes:[…]}`。未知键或类型错误 → 条目被丢弃并记录原因。
|
|
57
|
+
- 标题写结论不写图型名;副标题把图例/单位说清(`·` 分隔);来源行由渲染器按 `SOURCE · CATALOG_REF` 全大写输出。
|
|
58
|
+
- 每图一个独立结论,总数 ≤6,形状不重复;schema 见 `schemas/visual-layout.schema.json`。
|
|
59
|
+
|
|
60
|
+
## 3. 数据不足抑制(Meaningful Visualization Gate 镜像)
|
|
61
|
+
|
|
62
|
+
- 类目 <3、无 CI、无 phase 周区间、无年份、无 audit_items 等 → 该图抑制,原因写入 `report_spec.json` 的 `lieflat_gallery.suppressed`,报告 Brief 中以 `lieflat-suppressed` 块解释「为什么不画」。
|
|
63
|
+
- `visual_layout` 缺失或全无效 → 确定性安全组合 `forest_plot + dot_cascade + bubble_almanac + tick_rows`(同样经提取器出数,数据不足仍逐图抑制),画廊不空。
|
|
64
|
+
- 大样本 → top-N 截断 + `<title>` 悬停读数;不加欺骗性交互。
|
|
65
|
+
- 暗色主题 → SVG 底色 = 主题 `card_bg`,对比度 ≥4.5:1;浅/暗同图同结构仅换色。
|
|
66
|
+
- 无 JS / reduced-motion / 打印 → 图表静态完整可见(motion 模板的 `data-lieflat` 规则覆盖)。
|
|
67
|
+
|
|
68
|
+
## 4. 三个示例项目的推荐组合样例
|
|
69
|
+
|
|
70
|
+
- **ai-coding-assistant-50(50 篇,数据最全)**:`parallel_coordinates`(L20 跨维度)+ `jitter_strip`(G15 分布)+ `hundred_field`(L14 设计构成)+ `tick_gauge`(F11 置信度)+ `ballot_tally`(L15 审计计票)+ `matrix_heat`(L16 年份×维度)——六种轮廓全不重复。
|
|
71
|
+
- **highschool-math-ai-tutor(16 篇)**:`forest_plot` + `brand_spectrum`(L7 提速 vs 留存)+ `barcode_lollipop`(L3 四阶段)+ `launch_fan`(L1 活动权重)+ `paired_rungs`(F6 正负对比)。
|
|
72
|
+
- **esl-academic-writing-ai(16 篇)**:`forest_plot` + `dot_cascade`(L2 梯队)+ `bubble_almanac`(L9 年历)+ `tick_rows`(F5 方向分布)+ `dotty_matrix`(L8 阶段点阵)。
|
|
73
|
+
|
|
74
|
+
## 5. 渲染层不变式
|
|
75
|
+
|
|
76
|
+
- 渲染器只吃提取器 bundle;`lieflat_engine.render_figure(type, bundle, theme, meta)` 未知 type 抛错。
|
|
77
|
+
- SVG 内无 `<style>`;动画 = `lf-pop/lf-fade/lf-draw` 类 + `--motion-delay` 内联变量(点阵 12ms、条形 100ms stagger),由 `motion/motion.css` 定义曲线(quarticOut 族)。
|
|
78
|
+
- 卡片四件套:结论式标题(700)+ 副标题(图例,`·` 分隔)+ 图 + 全大写加字距来源行;图注可选。
|
|
79
|
+
- SVG 最小字号 6.5px;数值字重 800;面积编码用 sqrt;计数轴整数刻度。
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Motion System
|
|
2
|
+
|
|
3
|
+
EduEvidence motion is a fixed presentation template, not per-report decoration.
|
|
4
|
+
|
|
5
|
+
Allowed roles:
|
|
6
|
+
|
|
7
|
+
- `section-enter` — one-shot section/chapter reveal.
|
|
8
|
+
- `stagger-enter` — evidence/tribunal/source groups reveal in reading order.
|
|
9
|
+
- `bar-grow` — meaningful comparison bars grow from zero once.
|
|
10
|
+
- `quality-grow` — inline quality meters grow once.
|
|
11
|
+
- `trace-reveal` — Claim → Evidence → Source chains reveal in order.
|
|
12
|
+
- `flow-reveal` — Evidence-to-Action nodes and arrows reveal in order.
|
|
13
|
+
- `detail-expand` — native `<details>` content receives a short opacity/translate reveal.
|
|
14
|
+
- `page-transition` — Visual Brief / Full Report switch uses a short page reveal.
|
|
15
|
+
- `toc-active` — active chapter changes color/border only.
|
|
16
|
+
- `chart-reveal` — `[data-lieflat]` gallery cards follow the Lieflat mono-tokens `obsReveal` contract. **This is a fixed template role; the five themes must not invent alternative chart animation logic.**
|
|
17
|
+
|
|
18
|
+
`chart-reveal` contract (implemented in `motion/motion.css` + `motion/motion.js`):
|
|
19
|
+
|
|
20
|
+
- Elements carry `lf-pop` / `lf-fade` / `lf-draw` classes plus an inline `--motion-delay` variable (dot matrices stagger 12 ms, bars 100 ms — the 8–15 ms / 80–130 ms token ranges).
|
|
21
|
+
- Curves are the mono-tokens family: `lf-pop` scale 0→1 with `cubic-bezier(.2,.7,.3,1.3)` 500 ms; `lf-fade` 900 ms ease; `lf-draw` dasharray 1 with `cubic-bezier(.4,0,.2,1)` 1 s.
|
|
22
|
+
- Reveal runs once when the card scrolls into view (IntersectionObserver, threshold .3), gated by the `.js-lf` root class; clicking the card replays the reveal after clearing that card's registered timers (no animation stacking).
|
|
23
|
+
- Without JS, or under `prefers-reduced-motion: reduce`, or in print, every element stays static and fully visible — motion never hides evidence.
|
|
24
|
+
|
|
25
|
+
Constraints:
|
|
26
|
+
|
|
27
|
+
- Motion never changes numbers, evidence direction, ordering, adjudication, or chart scale.
|
|
28
|
+
- Every reveal runs at most once per element (except explicit user-requested replay via click on `[data-lieflat]`).
|
|
29
|
+
- `prefers-reduced-motion: reduce` disables nonessential animation.
|
|
30
|
+
- Print disables all animation and exposes detail content.
|
|
31
|
+
- Five visual themes may alter layout and surfaces, but must not invent new motion behaviors.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://eduevidence.dev/schemas/v5/adapter-envelope.schema.json",
|
|
4
|
+
"title": "AdapterEnvelope",
|
|
5
|
+
"description": "Uniform envelope produced by the three zero-dependency visualization adapters (build_charts / build_infographics / build_figures). source_ref is a display alias only; source_sha256 is the provenance that pins the envelope to its exact result.json bytes.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"adapter", "contract_version", "source_ref", "source_sha256", "locale", "data"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"adapter": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"enum": ["charts", "infographics", "figures"]
|
|
15
|
+
},
|
|
16
|
+
"contract_version": { "type": "string", "const": "1.0" },
|
|
17
|
+
"source_ref": { "type": "string", "minLength": 1 },
|
|
18
|
+
"source_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
19
|
+
"locale": { "type": "string", "enum": ["zh", "en"] },
|
|
20
|
+
"data": { "type": "object" }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/37chengshan/eduevidence/visualization/eduevidence-report/schemas/visual-layout.schema.json",
|
|
4
|
+
"title": "VisualLayout",
|
|
5
|
+
"description": "AI-composed Lieflat gallery plan written by the upstream AI into result.json.visual_layout. Entries name a registered chart type, its catalog reference, bilingual copy, data source and renderer params — the AI never writes numbers; the renderer extracts every value from result.json via scripts/charts_data.py. Unregistered types are rejected (no silent fallback).",
|
|
6
|
+
"type": "array",
|
|
7
|
+
"minItems": 1,
|
|
8
|
+
"maxItems": 6,
|
|
9
|
+
"uniqueItems": true,
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"required": ["type"],
|
|
13
|
+
"oneOf": [
|
|
14
|
+
{
|
|
15
|
+
"description": "New bilingual contract (preferred).",
|
|
16
|
+
"required": ["title_zh", "title_en", "subtitle_zh", "subtitle_en"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"description": "Legacy contract (title/subtitle shared across languages; accepted with a warning).",
|
|
20
|
+
"required": ["title", "subtitle"]
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"type": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": [
|
|
27
|
+
"forest_plot",
|
|
28
|
+
"dot_cascade",
|
|
29
|
+
"bubble_almanac",
|
|
30
|
+
"jitter_strip",
|
|
31
|
+
"parallel_coordinates",
|
|
32
|
+
"hundred_field",
|
|
33
|
+
"tick_donut",
|
|
34
|
+
"tick_rows",
|
|
35
|
+
"rung_bars",
|
|
36
|
+
"paired_rungs",
|
|
37
|
+
"brand_spectrum",
|
|
38
|
+
"barcode_lollipop",
|
|
39
|
+
"launch_fan",
|
|
40
|
+
"dotty_matrix",
|
|
41
|
+
"tick_gauge",
|
|
42
|
+
"ballot_tally",
|
|
43
|
+
"matrix_heat"
|
|
44
|
+
],
|
|
45
|
+
"description": "Registered Lieflat chart type (the registry lives in scripts/lieflat_engine.py). Unknown types are dropped with a recorded reason."
|
|
46
|
+
},
|
|
47
|
+
"chart_id": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 1,
|
|
50
|
+
"description": "Stable id for the rendered figure; defaults to lieflat-<type>.svg. Academic figure keys are namespaced automatically."
|
|
51
|
+
},
|
|
52
|
+
"catalog_ref": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"description": "Catalog number + name (e.g. 'L2 Dot Cascade', 'G15 Jitter Strip'). Must match the registry value."
|
|
55
|
+
},
|
|
56
|
+
"source": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "Extractor source key in scripts/charts_data.py (e.g. 'evidence.ranked_effects'). Defaults to the registry source."
|
|
59
|
+
},
|
|
60
|
+
"title_zh": {"type": "string", "minLength": 1},
|
|
61
|
+
"title_en": {"type": "string", "minLength": 1},
|
|
62
|
+
"subtitle_zh": {"type": "string", "minLength": 1},
|
|
63
|
+
"subtitle_en": {"type": "string", "minLength": 1},
|
|
64
|
+
"caption_zh": {"type": "string"},
|
|
65
|
+
"caption_en": {"type": "string"},
|
|
66
|
+
"title": {"type": "string", "minLength": 1},
|
|
67
|
+
"subtitle": {"type": "string", "minLength": 1},
|
|
68
|
+
"params": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"description": "Renderer/extractor parameters. Allowed keys per type: forest_plot{max_studies}, dot_cascade{limit}, jitter_strip{limit}, parallel_coordinates{limit}, launch_fan{max_items}, tick_rows/rung_bars/paired_rungs/brand_spectrum{outcomes}. Unknown keys or wrong types reject the entry.",
|
|
71
|
+
"properties": {
|
|
72
|
+
"max_studies": {"type": "integer", "minimum": 1, "maximum": 30},
|
|
73
|
+
"limit": {"type": "integer", "minimum": 3, "maximum": 60},
|
|
74
|
+
"max_items": {"type": "integer", "minimum": 3, "maximum": 12},
|
|
75
|
+
"outcomes": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": {"type": "string"},
|
|
78
|
+
"minItems": 1,
|
|
79
|
+
"description": "Optional filter of outcome_type keys to include."
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"additionalProperties": false
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"additionalProperties": false
|
|
86
|
+
}
|
|
87
|
+
}
|
|
Binary file
|
package/visualization/eduevidence-report/scripts/__pycache__/build_artifact_manifest.cpython-312.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/visualization/eduevidence-report/scripts/__pycache__/build_infographics.cpython-312.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""adapter_contract.py — shared zero-dependency envelope helpers (P1 contract gate).
|
|
2
|
+
|
|
3
|
+
Every visualization adapter CLI (build_charts / build_infographics /
|
|
4
|
+
build_figures) writes the same envelope through write_adapter_output():
|
|
5
|
+
adapter, contract_version, source_ref, source_sha256, locale, data.
|
|
6
|
+
build_report.py imports the same core functions, so the CLI path and the
|
|
7
|
+
report path can never diverge.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
CONTRACT_VERSION = "1.0"
|
|
18
|
+
ADAPTERS = ("charts", "infographics", "figures")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def load_result(path: str) -> dict:
|
|
22
|
+
"""Load a result.json as a JSON object; fail closed with a clear message."""
|
|
23
|
+
p = Path(path)
|
|
24
|
+
if not p.exists():
|
|
25
|
+
print(f"ERROR: result file not found: {path}", file=sys.stderr)
|
|
26
|
+
sys.exit(2)
|
|
27
|
+
try:
|
|
28
|
+
data = json.loads(p.read_text(encoding="utf-8"))
|
|
29
|
+
except json.JSONDecodeError as exc:
|
|
30
|
+
print(f"ERROR: result file is not valid JSON: {path} ({exc})", file=sys.stderr)
|
|
31
|
+
sys.exit(2)
|
|
32
|
+
if not isinstance(data, dict):
|
|
33
|
+
print(f"ERROR: result file must contain a JSON object: {path}", file=sys.stderr)
|
|
34
|
+
sys.exit(2)
|
|
35
|
+
return data
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def result_sha256(path: str) -> str:
|
|
39
|
+
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def write_adapter_output(out: str, adapter: str, result_path: str, payload: dict,
|
|
43
|
+
locale: str = "zh") -> None:
|
|
44
|
+
"""Validate inputs and write the adapter envelope; never fabricate data."""
|
|
45
|
+
if adapter not in ADAPTERS:
|
|
46
|
+
print(f"ERROR: unknown adapter {adapter!r} (expected one of {ADAPTERS})",
|
|
47
|
+
file=sys.stderr)
|
|
48
|
+
sys.exit(2)
|
|
49
|
+
if locale not in ("zh", "en"):
|
|
50
|
+
print(f"ERROR: locale must be zh or en (got {locale!r})", file=sys.stderr)
|
|
51
|
+
sys.exit(2)
|
|
52
|
+
envelope = {
|
|
53
|
+
"adapter": adapter,
|
|
54
|
+
"contract_version": CONTRACT_VERSION,
|
|
55
|
+
"source_ref": Path(result_path).name,
|
|
56
|
+
"source_sha256": result_sha256(result_path),
|
|
57
|
+
"locale": locale,
|
|
58
|
+
"data": payload,
|
|
59
|
+
}
|
|
60
|
+
out_path = Path(out)
|
|
61
|
+
try:
|
|
62
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
except OSError as exc:
|
|
64
|
+
print(f"ERROR: cannot create output directory {out_path.parent}: {exc}",
|
|
65
|
+
file=sys.stderr)
|
|
66
|
+
sys.exit(2)
|
|
67
|
+
try:
|
|
68
|
+
out_path.write_text(json.dumps(envelope, ensure_ascii=False, indent=2),
|
|
69
|
+
encoding="utf-8")
|
|
70
|
+
except OSError as exc:
|
|
71
|
+
print(f"ERROR: cannot write output file {out_path}: {exc}", file=sys.stderr)
|
|
72
|
+
sys.exit(2)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""build_artifact_manifest.py — HTML-03 Artifact Manifest generator.
|
|
3
|
+
|
|
4
|
+
Validates that every HTML under --html-dir embeds the same result.json SHA-256
|
|
5
|
+
(matching the actual result files) and writes artifact_manifest.json:
|
|
6
|
+
|
|
7
|
+
examples/ai-coding-assistant/artifact_manifest.json
|
|
8
|
+
{
|
|
9
|
+
"result_sha256": "...", "result_zh_sha256": "...",
|
|
10
|
+
"renderer_version": "1.0.0", "git_commit": "...",
|
|
11
|
+
"evidence_count": 13, "source_count": 7,
|
|
12
|
+
"themes": ["claude", "academic", "datalab", "datalab-dark", "presentation"]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 visualization/eduevidence-report/scripts/build_artifact_manifest.py \
|
|
17
|
+
--result examples/ai-coding-assistant/result.json \
|
|
18
|
+
--result-zh examples/ai-coding-assistant/result.zh.json \
|
|
19
|
+
--html-dir examples/ai-coding-assistant/reports-5themes \
|
|
20
|
+
--out examples/ai-coding-assistant/artifact_manifest.json
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import subprocess
|
|
26
|
+
import sys
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
from build_report import RENDERER_VERSION, THEME_NAMES, write_artifact_manifest
|
|
30
|
+
|
|
31
|
+
REPO_ROOT = Path(__file__).resolve().parent.parent.parent.parent
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def git_commit() -> str:
|
|
35
|
+
try:
|
|
36
|
+
out = subprocess.run(["git", "rev-parse", "HEAD"], cwd=str(REPO_ROOT),
|
|
37
|
+
capture_output=True, text=True, timeout=10)
|
|
38
|
+
return out.stdout.strip() if out.returncode == 0 else ""
|
|
39
|
+
except (OSError, subprocess.SubprocessError):
|
|
40
|
+
return ""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main() -> int:
|
|
44
|
+
parser = argparse.ArgumentParser(description="Generate HTML-03 artifact manifest")
|
|
45
|
+
parser.add_argument("--result", required=True)
|
|
46
|
+
parser.add_argument("--result-zh", required=True)
|
|
47
|
+
parser.add_argument("--html-dir", required=True)
|
|
48
|
+
parser.add_argument("--out", required=True)
|
|
49
|
+
parser.add_argument("--renderer-version", default=RENDERER_VERSION)
|
|
50
|
+
parser.add_argument("--git-commit", default="")
|
|
51
|
+
args = parser.parse_args()
|
|
52
|
+
|
|
53
|
+
html_dir = Path(args.html_dir)
|
|
54
|
+
html_paths = sorted(
|
|
55
|
+
p for p in html_dir.glob("EduEvidence_Report_*.html")
|
|
56
|
+
if any(p.name.endswith(f"_{t}.html") for t in THEME_NAMES))
|
|
57
|
+
if len(html_paths) != len(THEME_NAMES):
|
|
58
|
+
print(f"ERROR: expected {len(THEME_NAMES)} theme HTMLs in {html_dir}, found {len(html_paths)}")
|
|
59
|
+
return 2
|
|
60
|
+
commit = args.git_commit or git_commit()
|
|
61
|
+
manifest = write_artifact_manifest(Path(args.result), Path(args.result_zh), html_paths,
|
|
62
|
+
args.renderer_version, commit, Path(args.out))
|
|
63
|
+
print(f"wrote {args.out}: result={manifest['result_sha256'][:12]}… "
|
|
64
|
+
f"evidence={manifest['evidence_count']} sources={manifest['source_count']} "
|
|
65
|
+
f"themes={len(manifest['themes'])} commit={commit or '(none)'}")
|
|
66
|
+
return 0
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
sys.exit(main())
|