eduevidence 5.2.0 → 6.0.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.
Files changed (276) hide show
  1. package/README.md +54 -42
  2. package/README.zh-CN.md +51 -28
  3. package/SKILL.md +390 -133
  4. package/agents/openai.yaml +4 -0
  5. package/assets/readme/controlled-execution.svg +34 -0
  6. package/assets/readme/logo.png +0 -0
  7. package/assets/readme/research-workflow.svg +56 -0
  8. package/assets/readme/studio-graph.png +0 -0
  9. package/assets/readme/studio-overview.png +0 -0
  10. package/assets/readme/studio-reports.png +0 -0
  11. package/autoevolve/config.yaml +17 -0
  12. package/autoevolve/program.md +25 -0
  13. package/autoevolve/protected.manifest.yaml +34 -0
  14. package/benchmarks/adversarial/cases.jsonl +7 -0
  15. package/benchmarks/evidence-library.json +5268 -0
  16. package/benchmarks/partitions.json +8 -0
  17. package/docs/architecture.md +220 -0
  18. package/docs/autoresearch-evolution-plan.md +2903 -0
  19. package/docs/autoresearch-implementation-status.md +101 -0
  20. package/docs/demo-storyboard.md +20 -0
  21. package/docs/demo-workplace-ai.md +92 -0
  22. package/docs/demo.md +32 -0
  23. package/docs/install-guide.md +150 -0
  24. package/docs/orchestration-role-model.md +1254 -0
  25. package/docs/release-closeout/README.md +17 -0
  26. package/docs/release-closeout/frontend-acceptance.md +23 -0
  27. package/docs/release-closeout/issues.md +19 -0
  28. package/docs/release-closeout/verification.md +28 -0
  29. package/docs/release-contract.md +108 -0
  30. package/docs/research-studio-guide.zh-CN.md +166 -0
  31. package/eduevidence_cli.py +17 -11
  32. package/engine/_resources.py +13 -0
  33. package/engine/autoevolve/__init__.py +3 -0
  34. package/engine/autoevolve/agent_view.py +167 -0
  35. package/engine/autoevolve/core.py +357 -0
  36. package/engine/autoevolve/events.py +11 -0
  37. package/engine/autoevolve/git_workspace.py +77 -0
  38. package/engine/autoevolve/projection.py +23 -0
  39. package/engine/autoevolve/runner.py +413 -0
  40. package/engine/autoevolve/trust.py +146 -0
  41. package/engine/autoresearch/__init__.py +6 -0
  42. package/engine/autoresearch/commit.py +132 -0
  43. package/engine/autoresearch/contracts.py +126 -0
  44. package/engine/autoresearch/controller.py +207 -0
  45. package/engine/autoresearch/events.py +12 -0
  46. package/engine/autoresearch/gap_priority.py +168 -0
  47. package/engine/autoresearch/projection.py +30 -0
  48. package/engine/autoresearch/research_memory.py +59 -0
  49. package/engine/autoresearch/saturation.py +91 -0
  50. package/engine/briefs.py +2 -1
  51. package/engine/capabilities.py +1 -0
  52. package/engine/contracts.py +3 -1
  53. package/engine/evidencecore.py +7 -5
  54. package/engine/gaps.py +90 -51
  55. package/engine/judge_pack.py +65 -0
  56. package/engine/library_builtin.py +3 -1
  57. package/engine/living.py +2 -1
  58. package/engine/meta_synthesis.py +3 -1
  59. package/engine/orchestration.py +460 -0
  60. package/engine/pilot.py +2 -1
  61. package/engine/project.py +2 -2
  62. package/engine/research_service.py +113 -0
  63. package/engine/studio_read_model.py +400 -0
  64. package/engine/tribunal.py +1 -2
  65. package/engine/update.py +1 -0
  66. package/engine/versions.py +1 -1
  67. package/engine/worker_result.py +109 -0
  68. package/engine/workflows.py +70 -0
  69. package/examples/ai-coding-assistant-evidence/EduEvidence_Report.html +1720 -0
  70. package/examples/ai-coding-assistant-evidence/artifact_manifest.json +15 -0
  71. package/examples/ai-coding-assistant-evidence/citation_check.json +79 -0
  72. package/examples/ai-coding-assistant-evidence/claims.jsonl +12 -0
  73. package/examples/ai-coding-assistant-evidence/evaluation.json +35 -0
  74. package/examples/ai-coding-assistant-evidence/evidence.jsonl +12 -0
  75. package/examples/ai-coding-assistant-evidence/frame.json +48 -0
  76. package/examples/ai-coding-assistant-evidence/intervention.json +51 -0
  77. package/examples/ai-coding-assistant-evidence/methodology.json +36 -0
  78. package/examples/ai-coding-assistant-evidence/raw_verdict.json +86 -0
  79. package/examples/ai-coding-assistant-evidence/report_spec.json +219 -0
  80. package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_academic.html +2614 -0
  81. package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_claude.html +2614 -0
  82. package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_datalab-dark.html +2614 -0
  83. package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_datalab.html +2614 -0
  84. package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_presentation.html +2614 -0
  85. package/examples/ai-coding-assistant-evidence/reports-5themes/report_academic.html +1720 -0
  86. package/examples/ai-coding-assistant-evidence/reports-5themes/report_claude.html +1720 -0
  87. package/examples/ai-coding-assistant-evidence/reports-5themes/report_datalab-dark.html +1720 -0
  88. package/examples/ai-coding-assistant-evidence/reports-5themes/report_datalab.html +1720 -0
  89. package/examples/ai-coding-assistant-evidence/reports-5themes/report_presentation.html +1720 -0
  90. package/examples/ai-coding-assistant-evidence/result.json +1453 -0
  91. package/examples/ai-coding-assistant-evidence/result.zh.json +1453 -0
  92. package/examples/ai-coding-assistant-evidence/sources.jsonl +8 -0
  93. package/examples/ai-coding-assistant-evidence/verdict.json +103 -0
  94. package/examples/workplace-ai-assistant/claims.jsonl +4 -0
  95. package/examples/workplace-ai-assistant/evaluation.json +19 -0
  96. package/examples/workplace-ai-assistant/evidence.jsonl +4 -0
  97. package/examples/workplace-ai-assistant/evidence_graph.json +444 -0
  98. package/examples/workplace-ai-assistant/frame.json +41 -0
  99. package/examples/workplace-ai-assistant/intervention.json +27 -0
  100. package/examples/workplace-ai-assistant/legacy-link-check.json +16 -0
  101. package/examples/workplace-ai-assistant/methodology.json +60 -0
  102. package/examples/workplace-ai-assistant/report_spec.json +55 -0
  103. package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_academic.html +2484 -0
  104. package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_claude.html +2484 -0
  105. package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_datalab-dark.html +2484 -0
  106. package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_datalab.html +2484 -0
  107. package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_presentation.html +2484 -0
  108. package/examples/workplace-ai-assistant/result.json +553 -0
  109. package/examples/workplace-ai-assistant/result.zh.json +553 -0
  110. package/examples/workplace-ai-assistant/search_log.json +19 -0
  111. package/examples/workplace-ai-assistant/sources.jsonl +3 -0
  112. package/examples/workplace-ai-assistant/validation_result.json +9 -0
  113. package/examples/workplace-ai-assistant/verdict.json +52 -0
  114. package/install.sh +7 -7
  115. package/integrations/orchestration_dispatch.py +146 -0
  116. package/package.json +37 -3
  117. package/pyproject.toml +11 -20
  118. package/references/autoresearch.md +30 -0
  119. package/references/evaluation-policy.md +24 -0
  120. package/references/orchestration.md +22 -0
  121. package/references/scientific-invariants.md +19 -0
  122. package/retrieval/audit.py +154 -0
  123. package/schemas/intervention.schema.json +106 -21
  124. package/schemas/report-result.schema.json +9 -1
  125. package/schemas/v2/project.schema.json +2 -2
  126. package/schemas/v2/run.schema.json +1 -1
  127. package/schemas/vNext/autoevolve-session.schema.json +1 -0
  128. package/schemas/vNext/eval-snapshot.schema.json +1 -0
  129. package/schemas/vNext/execution-plan.schema.json +1 -0
  130. package/schemas/vNext/gap-priority.schema.json +1 -0
  131. package/schemas/vNext/negative-search-record.schema.json +1 -0
  132. package/schemas/vNext/research-iteration.schema.json +1 -0
  133. package/schemas/vNext/research-strategy.schema.json +1 -0
  134. package/schemas/vNext/skill-experiment.schema.json +1 -0
  135. package/schemas/vNext/task-spec.schema.json +1 -0
  136. package/schemas/vNext/worker-result.schema.json +1 -0
  137. package/scripts/benchmark_judge.py +2 -2
  138. package/scripts/benchmark_v3.py +26 -43
  139. package/scripts/build_esl_artifacts.py +2 -2
  140. package/scripts/build_evidence_library.py +2 -2
  141. package/scripts/build_gh_pages.py +98 -0
  142. package/scripts/build_readme_diagrams.py +72 -0
  143. package/scripts/build_report_variants.py +85 -0
  144. package/scripts/check_autoresearch_invariants.py +95 -0
  145. package/scripts/daily_evolve.py +30 -0
  146. package/scripts/dashboard_server.py +130 -101
  147. package/scripts/did_regression.py +5 -30
  148. package/scripts/enrich_projects_human_and_lieflat.py +1 -1
  149. package/scripts/generate_metrics.py +4 -3
  150. package/scripts/generate_new_projects.py +1 -1
  151. package/scripts/orchestrator.py +172 -18
  152. package/scripts/rebake_all_5themes.py +1 -2
  153. package/scripts/research_auto_cli.py +475 -0
  154. package/scripts/run_workspace.py +17 -7
  155. package/scripts/search_provenance.py +64 -0
  156. package/scripts/serve_web.py +9 -10
  157. package/scripts/skill_lint.py +1 -1
  158. package/scripts/skill_payload.py +78 -0
  159. package/scripts/validate_schema.py +15 -1
  160. package/scripts/vnext_cli.py +133 -0
  161. package/setup.py +12 -0
  162. package/skill/roles/registry.yaml +45 -0
  163. package/skill/sub-skills/report-generation/SKILL.md +12 -6
  164. package/skill/task-briefs/applicability.md +3 -0
  165. package/skill/task-briefs/projection.md +3 -0
  166. package/skill/workflows/decision-and-pilot.md +10 -0
  167. package/skill/workflows/evaluate-and-update.md +10 -0
  168. package/skill/workflows/evidence-review.md +13 -0
  169. package/visualization/eduevidence-report/assets/base.css +2 -2
  170. package/visualization/eduevidence-report/assets/reader.css +752 -0
  171. package/visualization/eduevidence-report/assets/reader.js +132 -0
  172. package/visualization/eduevidence-report/references/chart-selection-catalog.md +109 -0
  173. package/visualization/eduevidence-report/references/lieflat-composition.md +3 -1
  174. package/visualization/eduevidence-report/scripts/build_report.py +58 -65
  175. package/visualization/eduevidence-report/scripts/lieflat_engine.py +24 -100
  176. package/visualization/eduevidence-report/themes/academic.css +1 -1
  177. package/visualization/eduevidence-report/themes/claude.css +1 -1
  178. package/visualization/eduevidence-report/themes/datalab-dark.css +2 -2
  179. package/visualization/eduevidence-report/themes/datalab.css +2 -2
  180. package/visualization/eduevidence-report/themes/presentation.css +2 -2
  181. package/web/README.md +18 -0
  182. package/web/index.html +53 -0
  183. package/web/studio/THIRD_PARTY_LICENSES.txt +146 -0
  184. package/web/studio/assets/index-CzXocaGv.css +1 -0
  185. package/web/studio/assets/index-pa7jD7n4.js +230 -0
  186. package/web/studio/config.json +1 -0
  187. package/web/studio/index.html +14 -0
  188. package/engine/__pycache__/__init__.cpython-312.pyc +0 -0
  189. package/engine/__pycache__/analysis.cpython-312.pyc +0 -0
  190. package/engine/__pycache__/bias.cpython-312.pyc +0 -0
  191. package/engine/__pycache__/briefs.cpython-312.pyc +0 -0
  192. package/engine/__pycache__/capabilities.cpython-312.pyc +0 -0
  193. package/engine/__pycache__/citation_check.cpython-312.pyc +0 -0
  194. package/engine/__pycache__/contracts.cpython-312.pyc +0 -0
  195. package/engine/__pycache__/datasets.cpython-312.pyc +0 -0
  196. package/engine/__pycache__/events.cpython-312.pyc +0 -0
  197. package/engine/__pycache__/evidence_graph.cpython-312.pyc +0 -0
  198. package/engine/__pycache__/evidence_review.cpython-312.pyc +0 -0
  199. package/engine/__pycache__/evidencecore.cpython-312.pyc +0 -0
  200. package/engine/__pycache__/gap_lens.cpython-312.pyc +0 -0
  201. package/engine/__pycache__/gaps.cpython-312.pyc +0 -0
  202. package/engine/__pycache__/graph_store.cpython-312.pyc +0 -0
  203. package/engine/__pycache__/graph_validate.cpython-312.pyc +0 -0
  204. package/engine/__pycache__/ids.cpython-312.pyc +0 -0
  205. package/engine/__pycache__/library.cpython-312.pyc +0 -0
  206. package/engine/__pycache__/library_builtin.cpython-312.pyc +0 -0
  207. package/engine/__pycache__/living.cpython-312.pyc +0 -0
  208. package/engine/__pycache__/log.cpython-312.pyc +0 -0
  209. package/engine/__pycache__/meta_analysis.cpython-312.pyc +0 -0
  210. package/engine/__pycache__/meta_synthesis.cpython-312.pyc +0 -0
  211. package/engine/__pycache__/migration.cpython-312.pyc +0 -0
  212. package/engine/__pycache__/mode_router.cpython-312.pyc +0 -0
  213. package/engine/__pycache__/paths.cpython-312.pyc +0 -0
  214. package/engine/__pycache__/pilot.cpython-312.pyc +0 -0
  215. package/engine/__pycache__/planner.cpython-312.pyc +0 -0
  216. package/engine/__pycache__/project.cpython-312.pyc +0 -0
  217. package/engine/__pycache__/projections.cpython-312.pyc +0 -0
  218. package/engine/__pycache__/robustness.cpython-312.pyc +0 -0
  219. package/engine/__pycache__/run.cpython-312.pyc +0 -0
  220. package/engine/__pycache__/semantics.cpython-312.pyc +0 -0
  221. package/engine/__pycache__/study_design.cpython-312.pyc +0 -0
  222. package/engine/__pycache__/synthesis.cpython-312.pyc +0 -0
  223. package/engine/__pycache__/tribunal.cpython-312.pyc +0 -0
  224. package/engine/__pycache__/update.cpython-312.pyc +0 -0
  225. package/engine/__pycache__/versions.cpython-312.pyc +0 -0
  226. package/integrations/__pycache__/__init__.cpython-312.pyc +0 -0
  227. package/integrations/__pycache__/agent_mcp.cpython-312.pyc +0 -0
  228. package/integrations/__pycache__/smart_web_fetch.cpython-312.pyc +0 -0
  229. package/retrieval/__pycache__/__init__.cpython-312.pyc +0 -0
  230. package/retrieval/__pycache__/corpus_store.cpython-312.pyc +0 -0
  231. package/retrieval/__pycache__/dedupe.cpython-312.pyc +0 -0
  232. package/retrieval/__pycache__/failures.cpython-312.pyc +0 -0
  233. package/retrieval/__pycache__/fetch.cpython-312.pyc +0 -0
  234. package/retrieval/__pycache__/search.cpython-312.pyc +0 -0
  235. package/retrieval/__pycache__/source.cpython-312.pyc +0 -0
  236. package/retrieval/__pycache__/validate.cpython-312.pyc +0 -0
  237. package/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  238. package/scripts/__pycache__/benchmark.cpython-312.pyc +0 -0
  239. package/scripts/__pycache__/benchmark_evaluator.cpython-312.pyc +0 -0
  240. package/scripts/__pycache__/benchmark_judge.cpython-312.pyc +0 -0
  241. package/scripts/__pycache__/benchmark_routing.cpython-312.pyc +0 -0
  242. package/scripts/__pycache__/benchmark_v2.cpython-312.pyc +0 -0
  243. package/scripts/__pycache__/benchmark_v3.cpython-312.pyc +0 -0
  244. package/scripts/__pycache__/build_result.cpython-312.pyc +0 -0
  245. package/scripts/__pycache__/claim_audit.cpython-312.pyc +0 -0
  246. package/scripts/__pycache__/complexity_gate.cpython-312.pyc +0 -0
  247. package/scripts/__pycache__/compute_confidence.cpython-312.pyc +0 -0
  248. package/scripts/__pycache__/dashboard_server.cpython-312.pyc +0 -0
  249. package/scripts/__pycache__/did_regression.cpython-312.pyc +0 -0
  250. package/scripts/__pycache__/effect_calculator.cpython-312.pyc +0 -0
  251. package/scripts/__pycache__/evidence_matrix.cpython-312.pyc +0 -0
  252. package/scripts/__pycache__/evidence_score.cpython-312.pyc +0 -0
  253. package/scripts/__pycache__/evidence_semantics.cpython-312.pyc +0 -0
  254. package/scripts/__pycache__/fetch_benchmark.cpython-312.pyc +0 -0
  255. package/scripts/__pycache__/lint_report_layout.cpython-312.pyc +0 -0
  256. package/scripts/__pycache__/orchestrator.cpython-312.pyc +0 -0
  257. package/scripts/__pycache__/pre_verdict_gate.cpython-312.pyc +0 -0
  258. package/scripts/__pycache__/recompute_demo_quality.cpython-312.pyc +0 -0
  259. package/scripts/__pycache__/render_report.cpython-312.pyc +0 -0
  260. package/scripts/__pycache__/render_report_html.cpython-312.pyc +0 -0
  261. package/scripts/__pycache__/run_workspace.cpython-312.pyc +0 -0
  262. package/scripts/__pycache__/skill_lint.cpython-312.pyc +0 -0
  263. package/scripts/__pycache__/startup_probe.cpython-312.pyc +0 -0
  264. package/scripts/__pycache__/sync_killer_demo_report.cpython-312.pyc +0 -0
  265. package/scripts/__pycache__/test_adversarial_empirical.cpython-312-pytest-9.0.2.pyc +0 -0
  266. package/scripts/__pycache__/test_adversarial_empirical.cpython-312-pytest-9.1.1.pyc +0 -0
  267. package/scripts/__pycache__/validate_schema.cpython-312.pyc +0 -0
  268. package/visualization/eduevidence-report/scripts/__pycache__/adapter_contract.cpython-312.pyc +0 -0
  269. package/visualization/eduevidence-report/scripts/__pycache__/build_artifact_manifest.cpython-312.pyc +0 -0
  270. package/visualization/eduevidence-report/scripts/__pycache__/build_charts.cpython-312.pyc +0 -0
  271. package/visualization/eduevidence-report/scripts/__pycache__/build_figures.cpython-312.pyc +0 -0
  272. package/visualization/eduevidence-report/scripts/__pycache__/build_infographics.cpython-312.pyc +0 -0
  273. package/visualization/eduevidence-report/scripts/__pycache__/build_report.cpython-312.pyc +0 -0
  274. package/visualization/eduevidence-report/scripts/__pycache__/charts_data.cpython-312.pyc +0 -0
  275. package/visualization/eduevidence-report/scripts/__pycache__/lieflat_engine.cpython-312.pyc +0 -0
  276. package/visualization/eduevidence-report/scripts/__pycache__/zh_labels.cpython-312.pyc +0 -0
@@ -0,0 +1,72 @@
1
+ """Generate GitHub-safe vector diagrams from the canonical protocol registry."""
2
+ from pathlib import Path
3
+ import sys
4
+ from html import escape
5
+
6
+ ROOT = Path(__file__).resolve().parents[1]
7
+ sys.path.insert(0, str(ROOT))
8
+ from engine.workflows import SCIENTIFIC_STAGE_IDS # noqa: E402
9
+
10
+ OUT = ROOT / 'assets/readme'
11
+ OUT.mkdir(parents=True, exist_ok=True)
12
+
13
+
14
+ def start(title, subtitle, height):
15
+ return [f'''<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="{height}" viewBox="0 0 1200 {height}" role="img" aria-label="{escape(title)}">
16
+ <title>{escape(title)}</title><desc>{escape(subtitle)}</desc>
17
+ <defs><marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0L10 5L0 10" fill="none" stroke="#a15c40" stroke-width="1.5"/></marker></defs>
18
+ <rect width="1200" height="{height}" rx="24" fill="#f7f5f0"/>
19
+ <g font-family="-apple-system,BlinkMacSystemFont,Segoe UI,Arial,sans-serif">
20
+ <text x="48" y="43" font-size="12" letter-spacing="3" fill="#9b5e45">EDUEVIDENCE / RESEARCH STUDIO</text>
21
+ <text x="48" y="92" font-size="32" font-weight="600" fill="#272924">{escape(title)}</text>
22
+ <text x="48" y="126" font-size="16" fill="#6f7068">{escape(subtitle)}</text>''']
23
+
24
+
25
+ def card(parts, x, y, w, num, title, detail, accent=False):
26
+ fill = '#eee2d8' if accent else '#ffffff'
27
+ parts.append(f'<rect x="{x}" y="{y}" width="{w}" height="96" rx="14" fill="{fill}" stroke="#dcd8ce"/>')
28
+ parts.append(f'<text x="{x+20}" y="{y+28}" font-size="12" fill="#a15c40">{escape(num)}</text>')
29
+ parts.append(f'<text x="{x+20}" y="{y+54}" font-size="21" font-weight="600" fill="#30332e">{escape(title)}</text>')
30
+ parts.append(f'<text x="{x+20}" y="{y+78}" font-size="13" fill="#6f7068">{escape(detail)}</text>')
31
+
32
+
33
+ def line(parts, d):
34
+ parts.append(f'<path d="{d}" fill="none" stroke="#a15c40" stroke-width="1.7" marker-end="url(#arrow)"/>')
35
+
36
+
37
+ labels = {
38
+ 'frame': ('Frame / 定义问题', 'Question, population, comparison, outcomes'),
39
+ 'retrieve': ('Retrieve / 检索来源', 'Primary sources and retrieval provenance'),
40
+ 'extract': ('Extract / 提取证据', 'Study findings, measures and uncertainty'),
41
+ 'challenge': ('Challenge / 反证质疑', 'Counter-evidence and alternative explanations'),
42
+ 'audit': ('Audit / 方法审计', 'Study quality, bias and evidence limitations'),
43
+ 'adjudicate': ('Adjudicate / 证据裁决', 'Supported claims and bounded decisions'),
44
+ 'applicability': ('Applicability / 适用边界', 'For whom, where and under which conditions'),
45
+ 'intervene': ('Intervene / 设计试点', 'A grounded knowledge gap before a new design'),
46
+ 'evaluate': ('Evaluate / 评估更新', 'Validate new data and revise the decision'),
47
+ }
48
+ p=start('From evidence to a decision you can inspect', 'Nine scientific stages · 三条公开工作流 · Education + organizational policy', 704)
49
+ for i, stage in enumerate(SCIENTIFIC_STAGE_IDS):
50
+ row,col=divmod(i,3)
51
+ if row==1: col=2-col
52
+ x,y=48+col*376,166+row*128
53
+ card(p,x,y,352,f'{i+1:02d}',*labels[stage],stage=='adjudicate')
54
+ if i in (0,1,6,7): line(p,f'M{x+352} {y+48} H{x+370}')
55
+ if i in (3,4): line(p,f'M{x} {y+48} H{x-18}')
56
+ if i in (2,5): line(p,f'M{x+176} {y+96} V{y+121}')
57
+ p.append('<rect x="48" y="568" width="1104" height="88" rx="14" fill="#e9eee7"/>')
58
+ p.append('<text x="70" y="600" font-size="18" font-weight="600" fill="#456450">Projection / 展示制品</text>')
59
+ p.append('<text x="70" y="627" font-size="15" fill="#456450">Read-only Studio · Five report themes · Bilingual HTML · A report is not proof of an executed study.</text>')
60
+ p.append('<text x="48" y="682" font-size="12" fill="#6f7068">Evidence Review 01–07 / Decision &amp; Pilot 01–08 / Evaluate &amp; Update 09</text></g></svg>')
61
+ (OUT/'research-workflow.svg').write_text('\n'.join(p))
62
+ p=start('One research record. Controlled contributions.', 'Roles describe scientific responsibilities. Workers contribute only when the host supports delegation.',600)
63
+ card(p,48,178,290,'01 / LEAD','Plan the work','Bounded tasks and input snapshots')
64
+ card(p,442,178,310,'02 / EXECUTION','Native or delegated','Same scientific protocol and validation gates')
65
+ card(p,854,178,298,'03 / STAGING','Review contributions','Evidence, critique and audit artifacts')
66
+ line(p,'M338 226 H432'); line(p,'M752 226 H844');line(p,'M1004 274 V330 H599 V358')
67
+ card(p,442,368,310,'04 / VALIDATED COMMIT','Single writer','Lead commits a new immutable graph revision',True)
68
+ line(p,'M762 416 H844');card(p,854,368,298,'05 / PROJECTION','Read and trace','Studio, reports and revision history')
69
+ p.append('<text x="48" y="520" font-size="17" fill="#456450">Append evidence. Preserve provenance. Derive the decision from validated facts.</text>')
70
+ p.append('<text x="48" y="550" font-size="14" fill="#6f7068">Native execution needs no worker service. Cross-backend empirical performance is a separate verification task.</text></g></svg>')
71
+ (OUT/'controlled-execution.svg').write_text('\n'.join(p))
72
+ print('Generated research-workflow.svg and controlled-execution.svg from current protocol.')
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env python3
2
+ """Bake all five report identities from the same validated bilingual inputs.
3
+
4
+ This is a build step, never a read endpoint. No evidence or decision is changed.
5
+ Failures are explicit and never replaced with a synthetic success document.
6
+ """
7
+ from __future__ import annotations
8
+ import argparse
9
+ import hashlib
10
+ import json
11
+ import os
12
+ import subprocess
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ ROOT = Path(__file__).resolve().parent.parent
17
+ THEMES = ('claude', 'academic', 'datalab', 'datalab-dark', 'presentation')
18
+
19
+
20
+ def bake(examples: Path, *, force: bool = False) -> list[dict]:
21
+ renderer_dir = ROOT / 'visualization' / 'eduevidence-report'
22
+ renderer = renderer_dir / 'scripts' / 'build_report.py'
23
+ digest = hashlib.sha256()
24
+ for path in sorted(renderer_dir.rglob('*')):
25
+ if path.suffix in {'.py', '.css', '.js', '.json'} and '__pycache__' not in path.parts:
26
+ digest.update(path.relative_to(renderer_dir).as_posix().encode())
27
+ digest.update(path.read_bytes())
28
+ engine_hash = digest.hexdigest()
29
+ reports = []
30
+ for directory in sorted(examples.iterdir()):
31
+ if not directory.is_dir() or directory.is_symlink():
32
+ continue
33
+ source, parallel = directory / 'result.json', directory / 'result.zh.json'
34
+ if not source.exists() or not parallel.exists():
35
+ continue
36
+ result_hash = hashlib.sha256(source.read_bytes()).hexdigest()
37
+ cache_key = hashlib.sha256((engine_hash + result_hash + hashlib.sha256(parallel.read_bytes()).hexdigest()).encode()).hexdigest()
38
+ out_dir = directory / 'reports-5themes'
39
+ manifest = out_dir / 'reader-manifest.json'
40
+ if not force and manifest.is_file():
41
+ try:
42
+ prior = json.loads(manifest.read_text(encoding='utf-8'))
43
+ valid = prior.get('cache_key') == cache_key and all(
44
+ (out_dir / record['file']).is_file() and hashlib.sha256((out_dir / record['file']).read_bytes()).hexdigest() == record['sha256']
45
+ for record in prior.get('reports', [])) and len(prior.get('reports', [])) == len(THEMES)
46
+ if valid:
47
+ reports.append(prior)
48
+ continue
49
+ except (ValueError, KeyError, OSError):
50
+ pass
51
+ out_dir.mkdir(parents=True, exist_ok=True)
52
+ records = []
53
+ for theme in THEMES:
54
+ target = out_dir / f'EduEvidence_Report_{theme}.html'
55
+ # Build to temporary files, promote only after scientific gates pass.
56
+ temporary = out_dir / f'.{theme}.pending.html'
57
+ spec = out_dir / f'report_spec_{theme}.json'
58
+ completed = subprocess.run([sys.executable, str(renderer), '--result', str(source),
59
+ '--result-zh', str(parallel), '--theme', theme,
60
+ '--out', str(temporary), '--spec-out', str(spec)],
61
+ cwd=ROOT, capture_output=True, text=True, timeout=120)
62
+ if completed.returncode:
63
+ temporary.unlink(missing_ok=True)
64
+ raise RuntimeError(f'{directory.name}/{theme}: renderer rejected input\n{completed.stdout}\n{completed.stderr}')
65
+ os.replace(temporary, target)
66
+ records.append({'theme': theme, 'file': target.name, 'sha256': hashlib.sha256(target.read_bytes()).hexdigest()})
67
+ value = {'schema_version': 1, 'project': directory.name, 'cache_key': cache_key,
68
+ 'result_sha256': result_hash, 'renderer_sha256': engine_hash, 'reports': records}
69
+ manifest.write_text(json.dumps(value, indent=2) + '\n', encoding='utf-8')
70
+ reports.append(value)
71
+ print(f'{directory.name}: {len(records)} verified report variants')
72
+ return reports
73
+
74
+
75
+ def main() -> int:
76
+ parser = argparse.ArgumentParser(description=__doc__)
77
+ parser.add_argument('--examples', type=Path, default=ROOT / 'examples')
78
+ parser.add_argument('--force', action='store_true')
79
+ args = parser.parse_args()
80
+ bake(args.examples, force=args.force)
81
+ return 0
82
+
83
+
84
+ if __name__ == '__main__':
85
+ raise SystemExit(main())
@@ -0,0 +1,95 @@
1
+ from __future__ import annotations
2
+ import json
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ ROOT = Path(__file__).resolve().parent.parent
9
+
10
+
11
+ def fail(message: str) -> None:
12
+ print(f"ERROR: {message}", file=sys.stderr)
13
+ raise SystemExit(1)
14
+
15
+
16
+ def main() -> int:
17
+ invariants = ROOT / "references" / "scientific-invariants.md"
18
+ if not invariants.is_file():
19
+ fail("missing scientific invariants")
20
+ text = invariants.read_text(encoding="utf-8").lower()
21
+ for phrase in (
22
+ "optimize the research process, never the conclusion.",
23
+ "single writer",
24
+ "append-only",
25
+ ):
26
+ if phrase not in text:
27
+ fail(f"missing invariant: {phrase}")
28
+
29
+ registry = ROOT / "skill" / "roles" / "registry.yaml"
30
+ if not registry.is_file():
31
+ fail("missing role registry")
32
+ registry_text = registry.read_text(encoding="utf-8")
33
+ for role in ("evidence-retriever", "skeptic", "method-reviewer", "evidence-judge"):
34
+ if role not in registry_text:
35
+ fail(f"role missing: {role}")
36
+
37
+ from engine.orchestration import CanonicalWriteGuard, ExecutionPlanner
38
+ for level, cap in (("S", 0), ("M", 3), ("L", 6)):
39
+ plan = ExecutionPlanner().plan(level)
40
+ if level == "S" and plan.delegated_tasks:
41
+ fail("S must delegate zero tasks")
42
+ if len(plan.delegated_tasks) > cap:
43
+ fail(f"{level} delegated worker plan exceeds policy cap")
44
+ if max((len(group) for group in plan.parallel_groups), default=0) > plan.max_parallel_workers:
45
+ fail(f"{level} execution group exceeds max_parallel_workers")
46
+ try:
47
+ CanonicalWriteGuard().require("worker", "GraphRevision")
48
+ fail("single writer guard did not block worker")
49
+ except PermissionError:
50
+ pass
51
+
52
+ schema_dir = ROOT / "schemas" / "vNext"
53
+ required = {
54
+ "research-iteration.schema.json",
55
+ "research-strategy.schema.json",
56
+ "negative-search-record.schema.json",
57
+ "gap-priority.schema.json",
58
+ "task-spec.schema.json",
59
+ "worker-result.schema.json",
60
+ "execution-plan.schema.json",
61
+ "skill-experiment.schema.json",
62
+ "eval-snapshot.schema.json",
63
+ "autoevolve-session.schema.json",
64
+ }
65
+ missing = [name for name in required if not (schema_dir / name).is_file()]
66
+ if missing:
67
+ fail("missing schemas: " + ",".join(sorted(missing)))
68
+ for name in required:
69
+ json.loads((schema_dir / name).read_text(encoding="utf-8"))
70
+
71
+ head = os.getenv("GITHUB_HEAD_REF", "") or os.getenv("GITHUB_REF_NAME", "")
72
+ if head.startswith("autoresearch/"):
73
+ base = os.getenv("GITHUB_BASE_REF", "main")
74
+ subprocess.run(
75
+ ["git", "fetch", "origin", base, "--depth=1"],
76
+ cwd=ROOT,
77
+ check=True,
78
+ stdout=subprocess.DEVNULL,
79
+ )
80
+ changed = subprocess.check_output(
81
+ ["git", "diff", "--name-only", f"origin/{base}...HEAD"],
82
+ cwd=ROOT,
83
+ text=True,
84
+ ).splitlines()
85
+ from engine.autoevolve import ProtectedManifest
86
+ ok, bad = ProtectedManifest.from_repo(ROOT).validate_changes(changed)
87
+ if not ok:
88
+ fail("protected mutation on autoresearch branch: " + ",".join(bad))
89
+
90
+ print("autoresearch invariants OK")
91
+ return 0
92
+
93
+
94
+ if __name__ == "__main__":
95
+ raise SystemExit(main())
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+ import argparse
3
+ import json
4
+ from engine.autoevolve import DailyEvolutionRunner, DailyProfile
5
+
6
+
7
+ def main(argv=None):
8
+ parser = argparse.ArgumentParser(description="Run bounded branch-only EduEvidence evolution")
9
+ parser.add_argument("--repo", default=".")
10
+ parser.add_argument("--agent-command", required=True)
11
+ parser.add_argument("--eval-command", required=True)
12
+ parser.add_argument("--run-tag")
13
+ parser.add_argument("--max-experiments", type=int, default=20)
14
+ parser.add_argument("--max-cost-usd", type=float, default=5)
15
+ parser.add_argument("--max-wall-minutes", type=int, default=180)
16
+ parser.add_argument("--push-branch", action="store_true")
17
+ args = parser.parse_args(argv)
18
+ profile = DailyProfile(args.max_experiments, args.max_cost_usd, args.max_wall_minutes)
19
+ report = DailyEvolutionRunner(args.repo, profile=profile).run(
20
+ agent_command=args.agent_command,
21
+ eval_command=args.eval_command,
22
+ run_tag=args.run_tag,
23
+ push_branch=args.push_branch,
24
+ )
25
+ print(json.dumps(report, indent=2))
26
+ return 0
27
+
28
+
29
+ if __name__ == "__main__":
30
+ raise SystemExit(main())