eduevidence 5.2.0 → 6.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/CONTRIBUTING.md +105 -0
- package/README.md +142 -75
- package/README.zh-CN.md +73 -30
- package/SKILL.md +397 -131
- package/agents/openai.yaml +4 -0
- package/assets/readme/controlled-execution.svg +34 -0
- package/assets/readme/landing-tour.gif +0 -0
- package/assets/readme/logo.png +0 -0
- package/assets/readme/research-workflow.svg +56 -0
- package/assets/readme/studio-graph.png +0 -0
- package/assets/readme/studio-overview.png +0 -0
- package/assets/readme/studio-reports.png +0 -0
- package/assets/readme/studio-tour.gif +0 -0
- package/autoevolve/config.yaml +17 -0
- package/autoevolve/program.md +25 -0
- package/autoevolve/protected.manifest.yaml +34 -0
- package/benchmarks/adversarial/cases.jsonl +7 -0
- package/benchmarks/evidence-library.json +5268 -0
- package/benchmarks/partitions.json +8 -0
- package/bin/eduevidence.js +2 -1
- package/docs/architecture.md +496 -0
- package/docs/autoresearch-evolution-plan.md +2903 -0
- package/docs/autoresearch-implementation-status.md +101 -0
- package/docs/demo-storyboard.md +20 -0
- package/docs/demo-workplace-ai.md +92 -0
- package/docs/demo.md +32 -0
- package/docs/install-guide.md +150 -0
- package/docs/orchestration-role-model.md +1254 -0
- package/docs/release-closeout/README.md +17 -0
- package/docs/release-closeout/frontend-acceptance.md +23 -0
- package/docs/release-closeout/issues.md +19 -0
- package/docs/release-closeout/verification.md +28 -0
- package/docs/release-contract.md +108 -0
- package/docs/research-studio-guide.zh-CN.md +166 -0
- package/docs/sciverse-api.md +125 -0
- package/eduevidence_cli.py +29 -13
- package/engine/_resources.py +13 -0
- package/engine/autoevolve/__init__.py +3 -0
- package/engine/autoevolve/agent_view.py +167 -0
- package/engine/autoevolve/core.py +357 -0
- package/engine/autoevolve/events.py +11 -0
- package/engine/autoevolve/git_workspace.py +77 -0
- package/engine/autoevolve/projection.py +23 -0
- package/engine/autoevolve/runner.py +413 -0
- package/engine/autoevolve/trust.py +146 -0
- package/engine/autoresearch/__init__.py +6 -0
- package/engine/autoresearch/commit.py +132 -0
- package/engine/autoresearch/contracts.py +126 -0
- package/engine/autoresearch/controller.py +207 -0
- package/engine/autoresearch/events.py +12 -0
- package/engine/autoresearch/gap_priority.py +168 -0
- package/engine/autoresearch/projection.py +30 -0
- package/engine/autoresearch/research_memory.py +59 -0
- package/engine/autoresearch/saturation.py +91 -0
- package/engine/briefs.py +2 -1
- package/engine/capabilities.py +1 -0
- package/engine/contracts.py +3 -1
- package/engine/decision_policy.py +96 -0
- package/engine/evidence_graph.py +14 -10
- package/engine/evidencecore.py +7 -5
- package/engine/gaps.py +132 -73
- package/engine/ids.py +2 -0
- package/engine/judge_pack.py +65 -0
- package/engine/library.py +6 -2
- package/engine/library_builtin.py +3 -1
- package/engine/living.py +36 -5
- package/engine/meta_synthesis.py +3 -1
- package/engine/migration.py +88 -3
- package/engine/orchestration.py +460 -0
- package/engine/paths.py +2 -0
- package/engine/pilot.py +36 -33
- package/engine/project.py +2 -2
- package/engine/research_service.py +113 -0
- package/engine/studio_read_model.py +400 -0
- package/engine/taxonomy.py +211 -0
- package/engine/tribunal.py +44 -33
- package/engine/update.py +1 -0
- package/engine/versions.py +1 -1
- package/engine/worker_result.py +109 -0
- package/engine/workflows.py +70 -0
- package/examples/ai-coding-assistant-evidence/EduEvidence_Report.html +2934 -0
- package/examples/ai-coding-assistant-evidence/artifact_manifest.json +15 -0
- package/examples/ai-coding-assistant-evidence/citation_check.json +79 -0
- package/examples/ai-coding-assistant-evidence/claims.jsonl +12 -0
- package/examples/ai-coding-assistant-evidence/evaluation.json +35 -0
- package/examples/ai-coding-assistant-evidence/evidence.jsonl +12 -0
- package/examples/ai-coding-assistant-evidence/final_verdict.json +107 -0
- package/examples/ai-coding-assistant-evidence/frame.json +48 -0
- package/examples/ai-coding-assistant-evidence/gate_report.json +101 -0
- package/examples/ai-coding-assistant-evidence/intervention.json +51 -0
- package/examples/ai-coding-assistant-evidence/methodology.json +36 -0
- package/examples/ai-coding-assistant-evidence/raw_verdict.json +86 -0
- package/examples/ai-coding-assistant-evidence/report_spec.json +230 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_academic.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_claude.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_datalab-dark.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_datalab.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/EduEvidence_Report_presentation.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/report_academic.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/report_claude.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/report_datalab-dark.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/report_datalab.html +2934 -0
- package/examples/ai-coding-assistant-evidence/reports-5themes/report_presentation.html +2934 -0
- package/examples/ai-coding-assistant-evidence/result.json +1457 -0
- package/examples/ai-coding-assistant-evidence/result.zh.json +1457 -0
- package/examples/ai-coding-assistant-evidence/skeptic.json +72 -0
- package/examples/ai-coding-assistant-evidence/sources.jsonl +8 -0
- package/examples/ai-coding-assistant-evidence/verdict.json +107 -0
- package/examples/spaced-retrieval-practice/applicability.json +14 -0
- package/examples/spaced-retrieval-practice/artifact_manifest.json +15 -0
- package/examples/spaced-retrieval-practice/claims.jsonl +3 -0
- package/examples/spaced-retrieval-practice/evidence.jsonl +6 -0
- package/examples/spaced-retrieval-practice/final_verdict.json +93 -0
- package/examples/spaced-retrieval-practice/frame.json +58 -0
- package/examples/spaced-retrieval-practice/gate_report.json +101 -0
- package/examples/spaced-retrieval-practice/methodology.json +78 -0
- package/examples/spaced-retrieval-practice/report_spec.json +212 -0
- package/examples/spaced-retrieval-practice/reports-5themes/EduEvidence_Report_academic.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/EduEvidence_Report_claude.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/EduEvidence_Report_datalab-dark.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/EduEvidence_Report_datalab.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/EduEvidence_Report_presentation.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/report_academic.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/report_claude.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/report_datalab-dark.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/report_datalab.html +2728 -0
- package/examples/spaced-retrieval-practice/reports-5themes/report_presentation.html +2728 -0
- package/examples/spaced-retrieval-practice/result.json +942 -0
- package/examples/spaced-retrieval-practice/result.zh.json +942 -0
- package/examples/spaced-retrieval-practice/skeptic.json +70 -0
- package/examples/spaced-retrieval-practice/sources.jsonl +7 -0
- package/examples/spaced-retrieval-practice/verdict.json +93 -0
- package/examples/workplace-ai-assistant/artifact_manifest.json +15 -0
- package/examples/workplace-ai-assistant/claims.jsonl +4 -0
- package/examples/workplace-ai-assistant/evaluation.json +19 -0
- package/examples/workplace-ai-assistant/evidence.jsonl +4 -0
- package/examples/workplace-ai-assistant/evidence_graph.json +444 -0
- package/examples/workplace-ai-assistant/final_verdict.json +78 -0
- package/examples/workplace-ai-assistant/frame.json +41 -0
- package/examples/workplace-ai-assistant/gate_report.json +101 -0
- package/examples/workplace-ai-assistant/intervention.json +27 -0
- package/examples/workplace-ai-assistant/legacy-link-check.json +16 -0
- package/examples/workplace-ai-assistant/methodology.json +60 -0
- package/examples/workplace-ai-assistant/report_spec.json +224 -0
- package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_academic.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_claude.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_datalab-dark.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_datalab.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/EduEvidence_Report_presentation.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/report_academic.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/report_claude.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/report_datalab-dark.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/report_datalab.html +2814 -0
- package/examples/workplace-ai-assistant/reports-5themes/report_presentation.html +2814 -0
- package/examples/workplace-ai-assistant/result.json +615 -0
- package/examples/workplace-ai-assistant/result.zh.json +615 -0
- package/examples/workplace-ai-assistant/search_log.json +19 -0
- package/examples/workplace-ai-assistant/skeptic.json +72 -0
- package/examples/workplace-ai-assistant/sources.jsonl +3 -0
- package/examples/workplace-ai-assistant/validation_result.json +9 -0
- package/examples/workplace-ai-assistant/verdict.json +78 -0
- package/install.sh +7 -7
- package/integrations/agent_mcp.py +2 -2
- package/integrations/orchestration_dispatch.py +146 -0
- package/package.json +46 -3
- package/pyproject.toml +14 -22
- package/references/autoresearch.md +30 -0
- package/references/evaluation-policy.md +24 -0
- package/references/orchestration.md +22 -0
- package/references/report-copy-style.md +67 -0
- package/references/retrieval-compliance.md +75 -0
- package/references/retrieval-protocol.md +20 -0
- package/references/scientific-invariants.md +19 -0
- package/retrieval/audit.py +178 -0
- package/retrieval/fetch.py +96 -0
- package/retrieval/sciverse.py +398 -0
- package/retrieval/search.py +47 -7
- package/schemas/applicability.schema.json +94 -0
- package/schemas/chart-spec.schema.json +10 -3
- package/schemas/evidence.schema.json +316 -43
- package/schemas/fetch-result.schema.json +2 -1
- package/schemas/intervention.schema.json +106 -21
- package/schemas/report-result.schema.json +12 -4
- package/schemas/report-spec.schema.json +98 -100
- package/schemas/skeptic.schema.json +86 -0
- package/schemas/source.schema.json +21 -2
- package/schemas/v2/finding.schema.json +5 -1
- package/schemas/v2/methodology-audit.schema.json +5 -1
- package/schemas/v2/outcome.schema.json +28 -5
- package/schemas/v2/project.schema.json +2 -2
- package/schemas/v2/run.schema.json +1 -1
- package/schemas/v2/study.schema.json +5 -1
- package/schemas/vNext/autoevolve-session.schema.json +34 -0
- package/schemas/vNext/eval-snapshot.schema.json +77 -0
- package/schemas/vNext/execution-plan.schema.json +50 -0
- package/schemas/vNext/gap-priority.schema.json +54 -0
- package/schemas/vNext/negative-search-record.schema.json +68 -0
- package/schemas/vNext/research-iteration.schema.json +87 -0
- package/schemas/vNext/research-strategy.schema.json +62 -0
- package/schemas/vNext/skill-experiment.schema.json +90 -0
- package/schemas/vNext/task-spec.schema.json +156 -0
- package/schemas/vNext/worker-result.schema.json +60 -0
- package/schemas/verdict.schema.json +164 -28
- package/scripts/benchmark_judge.py +2 -2
- package/scripts/benchmark_v3.py +26 -43
- package/scripts/build_esl_artifacts.py +4 -4
- package/scripts/build_evidence_library.py +2 -2
- package/scripts/build_gh_pages.py +98 -0
- package/scripts/build_readme_diagrams.py +72 -0
- package/scripts/build_report_variants.py +101 -0
- package/scripts/build_result.py +74 -9
- package/scripts/check_autoresearch_invariants.py +95 -0
- package/scripts/check_package_parity.py +85 -0
- package/scripts/check_protocol_alignment.py +375 -0
- package/scripts/check_versioned_schemas.py +254 -0
- package/scripts/claim_audit.py +13 -8
- package/scripts/compute_confidence.py +10 -0
- package/scripts/daily_evolve.py +30 -0
- package/scripts/dashboard_server.py +130 -101
- package/scripts/did_regression.py +17 -32
- package/scripts/enrich_projects_human_and_lieflat.py +1 -1
- package/scripts/evidence_score.py +5 -2
- package/scripts/generate_metrics.py +4 -3
- package/scripts/generate_new_projects.py +5 -5
- package/scripts/orchestrator.py +286 -36
- package/scripts/pre_verdict_gate.py +224 -26
- package/scripts/quickstart.py +18 -2
- package/scripts/rebake_all_5themes.py +1 -2
- package/scripts/research_auto_cli.py +475 -0
- package/scripts/run_workspace.py +24 -8
- package/scripts/search_provenance.py +64 -0
- package/scripts/serve_web.py +9 -10
- package/scripts/skill_lint.py +1 -1
- package/scripts/skill_payload.py +81 -0
- package/scripts/test_adversarial_empirical.py +26 -19
- package/scripts/validate_schema.py +46 -2
- package/scripts/vnext_cli.py +133 -0
- package/setup.py +12 -0
- package/skill/agents/evaluation-designer.md +20 -4
- package/skill/agents/evidence-analyst.md +19 -3
- package/skill/agents/evidence-judge.md +50 -2
- package/skill/agents/evidence-retriever.md +20 -3
- package/skill/agents/intervention-designer.md +20 -4
- package/skill/agents/method-reviewer.md +18 -2
- package/skill/agents/{education-planner.md → research-planner.md} +19 -3
- package/skill/agents/skeptic.md +18 -2
- package/skill/roles/registry.yaml +45 -0
- package/skill/sub-skills/aihot-trend-analysis/SKILL.md +28 -9
- package/skill/sub-skills/contradiction-analysis/SKILL.md +31 -11
- package/skill/sub-skills/data-analysis/SKILL.md +34 -15
- package/skill/sub-skills/ethics-review/SKILL.md +33 -10
- package/skill/sub-skills/evidence-extraction/SKILL.md +29 -11
- package/skill/sub-skills/evidence-review/SKILL.md +31 -12
- package/skill/sub-skills/gap-analysis/SKILL.md +31 -9
- package/skill/sub-skills/literature-review/SKILL.md +35 -14
- package/skill/sub-skills/methodology-audit/SKILL.md +29 -12
- package/skill/sub-skills/report-generation/SKILL.md +40 -6
- package/skill/sub-skills/research-planning/SKILL.md +41 -14
- package/skill/sub-skills/study-design/SKILL.md +30 -9
- package/skill/task-briefs/adjudicate.md +32 -7
- package/skill/task-briefs/applicability.md +38 -0
- package/skill/task-briefs/audit.md +32 -7
- package/skill/task-briefs/challenge.md +34 -5
- package/skill/task-briefs/evaluate.md +30 -5
- package/skill/task-briefs/extract.md +31 -8
- package/skill/task-briefs/frame.md +39 -10
- package/skill/task-briefs/intervene.md +32 -6
- package/skill/task-briefs/present.md +32 -8
- package/skill/task-briefs/projection.md +37 -0
- package/skill/task-briefs/retrieve.md +36 -6
- package/skill/workflows/decision-and-pilot.md +85 -0
- package/skill/workflows/evaluate-and-update.md +93 -0
- package/skill/workflows/evidence-review.md +117 -0
- package/visualization/eduevidence-report/assets/base.css +2 -2
- package/visualization/eduevidence-report/assets/reader.css +752 -0
- package/visualization/eduevidence-report/assets/reader.js +132 -0
- package/visualization/eduevidence-report/references/chart-selection-catalog.md +109 -0
- package/visualization/eduevidence-report/references/lieflat-composition.md +3 -1
- package/visualization/eduevidence-report/scripts/build_figures.py +25 -3
- package/visualization/eduevidence-report/scripts/build_infographics.py +5 -1
- package/visualization/eduevidence-report/scripts/build_report.py +561 -121
- package/visualization/eduevidence-report/scripts/charts_data.py +2 -0
- package/visualization/eduevidence-report/scripts/lieflat_engine.py +371 -136
- package/visualization/eduevidence-report/scripts/zh_labels.py +80 -1
- package/visualization/eduevidence-report/themes/academic.css +1 -1
- package/visualization/eduevidence-report/themes/claude.css +1 -1
- package/visualization/eduevidence-report/themes/datalab-dark.css +2 -2
- package/visualization/eduevidence-report/themes/datalab.css +2 -2
- package/visualization/eduevidence-report/themes/presentation.css +2 -2
- package/web/README.md +18 -0
- package/web/architecture.html +14885 -0
- package/web/index.html +53 -0
- package/web/studio/THIRD_PARTY_LICENSES.txt +146 -0
- package/web/studio/assets/index-B8tkF44Q.css +1 -0
- package/web/studio/assets/index-CQ6Keoyc.js +230 -0
- package/web/studio/config.json +1 -0
- package/web/studio/index.html +14 -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/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/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/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/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
|
@@ -7,7 +7,7 @@ reads ONLY the run workspace — no model call, no network.
|
|
|
7
7
|
|
|
8
8
|
Checklist:
|
|
9
9
|
|
|
10
|
-
1. research_frame_valid frame.json validates against
|
|
10
|
+
1. research_frame_valid frame.json validates against the run domain frame schema
|
|
11
11
|
2. sources_valid sources.jsonl non-empty and schema-valid
|
|
12
12
|
3. evidence_schema_valid evidence.jsonl non-empty and schema-valid
|
|
13
13
|
4. source_dedupe no duplicate sources remain (dedupe applied)
|
|
@@ -58,7 +58,7 @@ for _p in (str(ROOT), str(ROOT / "scripts")):
|
|
|
58
58
|
|
|
59
59
|
from validate_schema import SchemaError, Validator # noqa: E402
|
|
60
60
|
from evidence_score import independent_samples, independent_studies # noqa: E402
|
|
61
|
-
from evidence_semantics import claim_relation # noqa: E402
|
|
61
|
+
from evidence_semantics import claim_relation, decision_relation # noqa: E402
|
|
62
62
|
from run_workspace import utc_now # noqa: E402
|
|
63
63
|
|
|
64
64
|
GATE_VERSION = "2026-08-13.v1"
|
|
@@ -66,29 +66,52 @@ GATE_VERSION = "2026-08-13.v1"
|
|
|
66
66
|
CONFIDENCE_RANK = {"Insufficient": 0, "Low": 1, "Moderate": 2, "High": 3}
|
|
67
67
|
|
|
68
68
|
#: Advisory taxonomy for verdict outcome keys (shared with claim_audit).
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
|
|
69
|
+
def _supported_outcomes() -> set[str]:
|
|
70
|
+
"""Every registered outcome token, read from the domain registry.
|
|
71
|
+
|
|
72
|
+
This was a hand-copied 20-token education list in three separate files;
|
|
73
|
+
it silently rejected policy tokens such as policy_effectiveness. The
|
|
74
|
+
registry (domains/<id>/outcome_taxonomy.json) is the single authority.
|
|
75
|
+
"""
|
|
76
|
+
from engine.taxonomy import all_tokens_ordered
|
|
77
|
+
|
|
78
|
+
return set(all_tokens_ordered())
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
SUPPORTED_OUTCOMES = _supported_outcomes()
|
|
77
82
|
|
|
78
83
|
_CLAIM_ID_RE = re.compile(r"\b[A-Z]{1,3}-\d{2,4}\b")
|
|
79
84
|
|
|
80
85
|
_SCHEMA_CACHE: dict[str, dict[str, Any]] = {}
|
|
81
86
|
|
|
82
87
|
|
|
88
|
+
def _schema_path(name: str) -> Path:
|
|
89
|
+
"""Resolve a schema name to a file.
|
|
90
|
+
|
|
91
|
+
Accepts a bare name in schemas/ as well as a repository-relative path,
|
|
92
|
+
because a domain may own its frame contract outside schemas/ (policy does:
|
|
93
|
+
domains/policy/frame.schema.json).
|
|
94
|
+
"""
|
|
95
|
+
candidate = ROOT / "schemas" / name
|
|
96
|
+
if candidate.is_file():
|
|
97
|
+
return candidate
|
|
98
|
+
owned = ROOT / name
|
|
99
|
+
if owned.is_file():
|
|
100
|
+
return owned
|
|
101
|
+
return candidate # missing: the caller reports it
|
|
102
|
+
|
|
103
|
+
|
|
83
104
|
def _schema(name: str) -> dict[str, Any]:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
path = _schema_path(name)
|
|
106
|
+
key = str(path)
|
|
107
|
+
if key not in _SCHEMA_CACHE:
|
|
108
|
+
_SCHEMA_CACHE[key] = json.loads(path.read_text(encoding="utf-8"))
|
|
109
|
+
return _SCHEMA_CACHE[key]
|
|
87
110
|
|
|
88
111
|
|
|
89
112
|
def _validate_records(records: list[dict[str, Any]], schema_name: str, path: str) -> list[str]:
|
|
90
113
|
schema = _schema(schema_name)
|
|
91
|
-
validator = Validator(schema, base_dir=(
|
|
114
|
+
validator = Validator(schema, base_dir=_schema_path(schema_name).parent)
|
|
92
115
|
errors = []
|
|
93
116
|
for idx, record in enumerate(records):
|
|
94
117
|
try:
|
|
@@ -133,11 +156,43 @@ def _item_res(status: str, detail: str, *, blocks_high: bool | None = None) -> d
|
|
|
133
156
|
return res
|
|
134
157
|
|
|
135
158
|
|
|
159
|
+
def workspace_domain(ws: Path) -> str:
|
|
160
|
+
"""The domain this run/pack registered; defaults to education when absent.
|
|
161
|
+
|
|
162
|
+
A run workspace records it in run_manifest.json, but an example pack has
|
|
163
|
+
no manifest: reading only that file made a policy pack validate against the
|
|
164
|
+
education frame schema and fail item 1. Fall back to the same declared
|
|
165
|
+
places the read model uses, in the same order.
|
|
166
|
+
"""
|
|
167
|
+
manifest = _load_ws_json(ws, "run_manifest.json")
|
|
168
|
+
if manifest.get("domain"):
|
|
169
|
+
return str(manifest["domain"])
|
|
170
|
+
frame = _load_ws_json(ws, "frame.json")
|
|
171
|
+
declared = (frame.get("extensions") or {}).get("domain")
|
|
172
|
+
if declared:
|
|
173
|
+
return str(declared)
|
|
174
|
+
result_meta = (_load_ws_json(ws, "result.json").get("meta") or {})
|
|
175
|
+
if result_meta.get("domain"):
|
|
176
|
+
return str(result_meta["domain"])
|
|
177
|
+
return "education"
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def frame_schema_name(domain: str) -> str:
|
|
181
|
+
"""Registered frame schema for a domain (repository-relative path)."""
|
|
182
|
+
from engine.evidencecore import load_domain
|
|
183
|
+
|
|
184
|
+
return str(load_domain(domain)["frame_schema"])
|
|
185
|
+
|
|
186
|
+
|
|
136
187
|
def check_research_frame(ws: Path) -> dict[str, str]:
|
|
137
188
|
frame = _load_ws_json(ws, "frame.json")
|
|
138
189
|
if not frame:
|
|
139
190
|
return _item_res("fail", "frame.json missing or empty (research question not framed)")
|
|
140
|
-
|
|
191
|
+
try:
|
|
192
|
+
schema_name = frame_schema_name(workspace_domain(ws))
|
|
193
|
+
except KeyError as exc:
|
|
194
|
+
return _item_res("fail", f"run declares an unknown domain: {exc}")
|
|
195
|
+
errors = _validate_records([frame], schema_name, "frame")
|
|
141
196
|
if errors:
|
|
142
197
|
return _item_res("fail", f"frame.json schema invalid: {errors[0]}")
|
|
143
198
|
return _item_res("pass", f"frame.json valid (question={frame.get('question', '')[:80]})")
|
|
@@ -182,11 +237,41 @@ def check_counter_evidence(ws: Path) -> dict[str, str]:
|
|
|
182
237
|
return _item_res("fail", "skeptic.json missing or empty (counter-evidence search not performed)")
|
|
183
238
|
if skeptic.get("search_performed") is not True:
|
|
184
239
|
return _item_res("fail", "skeptic.json lacks search_performed=true")
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
240
|
+
|
|
241
|
+
# The nine fixed checks are the contract (skill/task-briefs/challenge.md).
|
|
242
|
+
# A two-key shell used to pass this gate, which made the counter-evidence
|
|
243
|
+
# check cosmetic on every deterministic path.
|
|
244
|
+
required_checks = (
|
|
245
|
+
"1_null_result", "2_negative_result", "3_contradictory_evidence",
|
|
246
|
+
"4_alternative_explanation", "5_measurement_mismatch", "6_sampling_bias",
|
|
247
|
+
"7_novelty_effect", "8_ai_dependency", "9_scope_overreach",
|
|
248
|
+
)
|
|
249
|
+
findings = skeptic.get("skeptic_findings")
|
|
250
|
+
if not isinstance(findings, list) or not findings:
|
|
251
|
+
return _item_res(
|
|
252
|
+
"fail", "skeptic.json lacks skeptic_findings[] (nine fixed checks not run)")
|
|
253
|
+
present = {str(f.get("check")) for f in findings if isinstance(f, dict)}
|
|
254
|
+
missing = [c for c in required_checks if c not in present]
|
|
255
|
+
if missing:
|
|
256
|
+
return _item_res("fail", f"skeptic findings incomplete; missing {missing}")
|
|
257
|
+
for item in findings:
|
|
258
|
+
if not isinstance(item, dict) or item.get("status") not in ("found", "not_found"):
|
|
259
|
+
return _item_res(
|
|
260
|
+
"fail", f"skeptic finding {item.get('check')!r} lacks a found/not_found status")
|
|
261
|
+
|
|
262
|
+
found = bool(skeptic.get("contradictory_evidence_found"))
|
|
263
|
+
statement = skeptic.get("no_contradictory_evidence_statement")
|
|
264
|
+
if not found and not statement:
|
|
265
|
+
# Absence of counter-evidence must be asserted, not left implicit.
|
|
266
|
+
return _item_res(
|
|
267
|
+
"fail", "no contradictory evidence found but no statement recorded")
|
|
268
|
+
if found and statement:
|
|
269
|
+
return _item_res(
|
|
270
|
+
"fail", "contradictory_evidence_found=true together with a no-evidence statement")
|
|
271
|
+
|
|
272
|
+
found_checks = sum(1 for f in findings if f.get("status") == "found")
|
|
273
|
+
detail = (f"search_performed=true; 9/9 checks run; findings={found_checks}; "
|
|
274
|
+
f"contradictory_evidence_found={found}")
|
|
190
275
|
return _item_res("pass", detail)
|
|
191
276
|
|
|
192
277
|
|
|
@@ -270,6 +355,96 @@ def check_claim_evidence(ws: Path) -> dict[str, str]:
|
|
|
270
355
|
return _item_res("pass", "all verdict claims bind to existing evidence with consistent categories")
|
|
271
356
|
|
|
272
357
|
|
|
358
|
+
def _primary_evidence_summary(ws: Path) -> dict[str, Any]:
|
|
359
|
+
"""Re-derive ADOPT eligibility from the pack's own evidence records.
|
|
360
|
+
|
|
361
|
+
The gate audits an artifact another party wrote, so it cannot trust the
|
|
362
|
+
verdict about itself: primary-result directness is read back from the
|
|
363
|
+
corpus (frame primary outcomes + per-record D5 Directness), using the same
|
|
364
|
+
domain registry and directness threshold the tribunal imports.
|
|
365
|
+
"""
|
|
366
|
+
from engine.decision_policy import (
|
|
367
|
+
ADOPT_DIRECTNESS,
|
|
368
|
+
outcome_category,
|
|
369
|
+
primary_effect_categories,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
domain = workspace_domain(ws)
|
|
373
|
+
try:
|
|
374
|
+
primary = primary_effect_categories(domain)
|
|
375
|
+
except (KeyError, ValueError) as exc:
|
|
376
|
+
return {"domain": domain, "primary": (), "direct": False, "error": str(exc)}
|
|
377
|
+
|
|
378
|
+
frame = _load_ws_json(ws, "frame.json")
|
|
379
|
+
declared_primary = [
|
|
380
|
+
str(token) for token in ((frame.get("outcomes") or {}).get("primary") or [])
|
|
381
|
+
]
|
|
382
|
+
evidence = _load_ws_jsonl(ws, "evidence.jsonl")
|
|
383
|
+
direct_hits: list[str] = []
|
|
384
|
+
for ev in evidence:
|
|
385
|
+
token = str(ev.get("outcome_type") or "")
|
|
386
|
+
category = outcome_category(domain, token, primary)
|
|
387
|
+
if category is None or category not in primary:
|
|
388
|
+
continue
|
|
389
|
+
dims = ev.get("quality_dimensions") or {}
|
|
390
|
+
d5 = dims.get("D5_directness")
|
|
391
|
+
if isinstance(d5, bool) or not isinstance(d5, int):
|
|
392
|
+
continue
|
|
393
|
+
if d5 >= ADOPT_DIRECTNESS:
|
|
394
|
+
direct_hits.append(str(ev.get("evidence_id") or "?"))
|
|
395
|
+
return {
|
|
396
|
+
"domain": domain,
|
|
397
|
+
"primary": primary,
|
|
398
|
+
"declared_primary": declared_primary,
|
|
399
|
+
"direct": bool(direct_hits),
|
|
400
|
+
"direct_evidence_ids": direct_hits,
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def check_decision_action(ws: Path) -> dict[str, str]:
|
|
405
|
+
"""The stated action must be the action the evidence supports.
|
|
406
|
+
|
|
407
|
+
A verdict cannot hand itself ADOPT: the gate requires High confidence, a
|
|
408
|
+
supporting decisive relation, and primary-outcome evidence at directness 2.
|
|
409
|
+
Anything less is capped to pilot - the conservative bound - because the
|
|
410
|
+
underlying evidence may still justify a bounded trial.
|
|
411
|
+
"""
|
|
412
|
+
verdict = _verdict_for_audit(ws)
|
|
413
|
+
if not verdict:
|
|
414
|
+
return _item_res("warn", "no verdict artifact yet; action not audited")
|
|
415
|
+
action = str(verdict.get("recommended_action") or "").lower()
|
|
416
|
+
if action != "adopt":
|
|
417
|
+
label = action or "unset"
|
|
418
|
+
return _item_res("pass", "action=" + label + " is within the conservative bound")
|
|
419
|
+
|
|
420
|
+
from engine.decision_policy import ADOPT_REQUIRED_LABEL, decision_action
|
|
421
|
+
|
|
422
|
+
evidence = _load_ws_jsonl(ws, "evidence.jsonl")
|
|
423
|
+
relations = [decision_relation(ev) for ev in evidence]
|
|
424
|
+
decisive = {str(index): rel for index, rel in enumerate(relations)
|
|
425
|
+
if rel in ("support_adoption", "oppose_adoption")}
|
|
426
|
+
label = str(verdict.get("confidence") or "")
|
|
427
|
+
summary = _primary_evidence_summary(ws)
|
|
428
|
+
expected = decision_action(
|
|
429
|
+
confidence_label=label,
|
|
430
|
+
decisive_relations=decisive,
|
|
431
|
+
has_direct_primary_evidence=bool(summary.get("direct")),
|
|
432
|
+
)
|
|
433
|
+
if expected == "ADOPT":
|
|
434
|
+
detail = "ADOPT is supported: " + label + " confidence with direct primary-outcome evidence"
|
|
435
|
+
return _item_res("pass", detail)
|
|
436
|
+
reasons: list[str] = []
|
|
437
|
+
if label != ADOPT_REQUIRED_LABEL:
|
|
438
|
+
reasons.append("confidence=" + (label or "unset") + " (needs " + ADOPT_REQUIRED_LABEL + ")")
|
|
439
|
+
if "support_adoption" not in relations:
|
|
440
|
+
reasons.append("no decisive supporting evidence")
|
|
441
|
+
if not summary.get("direct"):
|
|
442
|
+
reasons.append("no primary-outcome evidence at directness 2")
|
|
443
|
+
detail = ("recommended_action=adopt is not supported (" + "; ".join(reasons)
|
|
444
|
+
+ "); the evidence bounds this decision to pilot")
|
|
445
|
+
return _item_res("fail", detail)
|
|
446
|
+
|
|
447
|
+
|
|
273
448
|
def check_outcome_mapping(ws: Path) -> dict[str, str]:
|
|
274
449
|
verdict = _verdict_for_audit(ws)
|
|
275
450
|
frame = _load_ws_json(ws, "frame.json")
|
|
@@ -282,18 +457,35 @@ def check_outcome_mapping(ws: Path) -> dict[str, str]:
|
|
|
282
457
|
issues.append(f"unknown outcome key(s) in verdict: {', '.join(sorted(unknown))}")
|
|
283
458
|
|
|
284
459
|
evidence_outcomes = {e.get("outcome_type") for e in _load_ws_jsonl(ws, "evidence.jsonl")}
|
|
460
|
+
frame_outcomes = frame.get("outcomes", {}) or {}
|
|
285
461
|
declared = set()
|
|
286
462
|
for group in ("primary", "secondary", "risk"):
|
|
287
|
-
declared.update(
|
|
463
|
+
declared.update(frame_outcomes.get(group, []) or [])
|
|
288
464
|
if declared:
|
|
289
465
|
missing = sorted(d for d in declared if d and d not in evidence_outcomes)
|
|
290
466
|
if missing:
|
|
291
|
-
|
|
467
|
+
# Missing evidence is not a zero effect, and a secondary or risk
|
|
468
|
+
# outcome the frame named but the corpus never measured does not
|
|
469
|
+
# contaminate the decision. Only a PRIMARY outcome with no
|
|
470
|
+
# evidence at all means the decision rests on the wrong construct,
|
|
471
|
+
# so only that case blocks High confidence.
|
|
472
|
+
primary_missing = sorted(
|
|
473
|
+
d for d in (frame_outcomes.get("primary", []) or [])
|
|
474
|
+
if d and d not in evidence_outcomes)
|
|
475
|
+
note = f"frame-declared outcomes without evidence: {', '.join(missing)}"
|
|
476
|
+
if primary_missing:
|
|
477
|
+
return _item_res(
|
|
478
|
+
"warn",
|
|
479
|
+
note + f"; primary outcomes unmeasured: {', '.join(primary_missing)}",
|
|
480
|
+
blocks_high=True)
|
|
481
|
+
notes.append(note)
|
|
482
|
+
else:
|
|
483
|
+
notes.append("all frame-declared outcomes are covered by evidence")
|
|
292
484
|
|
|
293
485
|
if issues:
|
|
294
486
|
return _item_res("fail", "; ".join(issues))
|
|
295
|
-
if notes:
|
|
296
|
-
return _item_res("warn", "outcome keys known; " + notes[0])
|
|
487
|
+
if notes and "without evidence" in notes[0]:
|
|
488
|
+
return _item_res("warn", "outcome keys known; " + notes[0], blocks_high=False)
|
|
297
489
|
if not declared:
|
|
298
490
|
return _item_res("warn", "outcome keys known; frame declares no outcomes to map")
|
|
299
491
|
return _item_res("pass", f"outcome mapping complete ({len(evidence_outcomes)} outcome type(s) covered)")
|
|
@@ -375,13 +567,15 @@ GATE_ITEMS: list[dict[str, Any]] = [
|
|
|
375
567
|
{"id": "claim_evidence_audit", "title": "Claim-Evidence Audit", "critical": True,
|
|
376
568
|
"blocks_high": False, "check": check_claim_evidence},
|
|
377
569
|
{"id": "outcome_mapping", "title": "Outcome mapping", "critical": False,
|
|
378
|
-
"blocks_high":
|
|
570
|
+
"blocks_high": True, "check": check_outcome_mapping},
|
|
379
571
|
{"id": "scope_calibration", "title": "Scope calibration", "critical": False,
|
|
380
|
-
"blocks_high":
|
|
572
|
+
"blocks_high": True, "check": check_scope_calibration},
|
|
381
573
|
{"id": "independent_study_count", "title": "Independent study-sample count", "critical": True,
|
|
382
574
|
"blocks_high": True, "check": check_study_count},
|
|
383
575
|
{"id": "deterministic_confidence", "title": "Deterministic confidence", "critical": True,
|
|
384
576
|
"blocks_high": True, "check": None},
|
|
577
|
+
{"id": "decision_action_consistency", "title": "Decision action consistency",
|
|
578
|
+
"critical": True, "blocks_high": False, "check": check_decision_action},
|
|
385
579
|
]
|
|
386
580
|
|
|
387
581
|
|
|
@@ -437,6 +631,7 @@ def apply_enforcement(verdict: dict[str, Any], gate: dict[str, Any]) -> dict[str
|
|
|
437
631
|
|
|
438
632
|
- gate failed -> confidence at most Low; adopt downgraded to pilot
|
|
439
633
|
- gate passed but High blocked -> confidence at most Moderate
|
|
634
|
+
- stated adopt the evidence does not support -> downgraded to pilot
|
|
440
635
|
Always records the enforcement inside verdict.extensions.gate_enforcement.
|
|
441
636
|
"""
|
|
442
637
|
import copy
|
|
@@ -448,6 +643,9 @@ def apply_enforcement(verdict: dict[str, Any], gate: dict[str, Any]) -> dict[str
|
|
|
448
643
|
out["confidence"] = cap
|
|
449
644
|
if not gate.get("passed", False) and out.get("recommended_action") == "adopt":
|
|
450
645
|
out["recommended_action"] = "pilot"
|
|
646
|
+
action_item = (gate.get("items") or {}).get("decision_action_consistency") or {}
|
|
647
|
+
if action_item.get("status") == "fail" and out.get("recommended_action") == "adopt":
|
|
648
|
+
out["recommended_action"] = "pilot"
|
|
451
649
|
extensions = out.setdefault("extensions", {})
|
|
452
650
|
if not isinstance(extensions, dict):
|
|
453
651
|
extensions = {}
|
package/scripts/quickstart.py
CHANGED
|
@@ -40,8 +40,23 @@ STAGE_BRIEFS = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
def runs_root() -> Path:
|
|
44
|
+
"""Runs directory, honouring EDUEVIDENCE_RUNS_DIR like the orchestrator does.
|
|
45
|
+
|
|
46
|
+
Without this the quickstart wrote into the repository even when the user had
|
|
47
|
+
pointed the runs directory elsewhere.
|
|
48
|
+
"""
|
|
49
|
+
import os
|
|
50
|
+
|
|
51
|
+
return Path(os.environ.get("EDUEVIDENCE_RUNS_DIR") or (ROOT / "runs"))
|
|
52
|
+
|
|
53
|
+
|
|
43
54
|
def newest_run_dir() -> Path:
|
|
44
|
-
runs_dir =
|
|
55
|
+
runs_dir = runs_root()
|
|
56
|
+
if not runs_dir.is_dir():
|
|
57
|
+
raise SystemExit(
|
|
58
|
+
f"no runs directory at {runs_dir}; run `eduevidence run --question ...` first "
|
|
59
|
+
"(or set EDUEVIDENCE_RUNS_DIR)")
|
|
45
60
|
candidates = sorted((p for p in runs_dir.iterdir() if p.is_dir()),
|
|
46
61
|
key=lambda p: p.stat().st_mtime, reverse=True)
|
|
47
62
|
if not candidates:
|
|
@@ -86,7 +101,8 @@ def build_next_steps(run_dir: Path, question: str, depth: str) -> str:
|
|
|
86
101
|
"",
|
|
87
102
|
"## 可信度自检",
|
|
88
103
|
"",
|
|
89
|
-
"-
|
|
104
|
+
"- 引用逐条核验报告:包内 `citation_check.md`"
|
|
105
|
+
"(源码仓库另见 `benchmarks/doi-audit/report.md`)",
|
|
90
106
|
"- 报告头徽章标注 data_origin;synthetic 演示不得当作实证引用",
|
|
91
107
|
""]
|
|
92
108
|
return "\n".join(lines)
|
|
@@ -10,8 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
ROOT = Path(__file__).resolve().parent.parent
|
|
11
11
|
|
|
12
12
|
PROJECTS = [
|
|
13
|
-
"examples/
|
|
14
|
-
"examples/esl-academic-writing-ai",
|
|
13
|
+
"examples/workplace-ai-assistant",
|
|
15
14
|
"examples/ai-coding-assistant-evidence"
|
|
16
15
|
]
|
|
17
16
|
|