psyclaw 0.27.22 → 0.28.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 (1048) hide show
  1. package/README.md +11 -5
  2. package/dist/apps/panel/index.html +2 -2
  3. package/dist/src/adapters/pi/extension.js +225 -92
  4. package/dist/src/adapters/pi/extension.js.map +1 -1
  5. package/dist/src/agents/import.js +44 -32
  6. package/dist/src/agents/import.js.map +1 -1
  7. package/dist/src/analysis/hooks.d.ts +1 -0
  8. package/dist/src/analysis/hooks.js +20 -1
  9. package/dist/src/analysis/hooks.js.map +1 -1
  10. package/dist/src/ars/bridge.d.ts +20 -0
  11. package/dist/src/ars/bridge.js +132 -0
  12. package/dist/src/ars/bridge.js.map +1 -0
  13. package/dist/src/ars/contracts.d.ts +55 -0
  14. package/dist/src/ars/contracts.js +2 -0
  15. package/dist/src/ars/contracts.js.map +1 -0
  16. package/dist/src/ars/panel-plan.d.ts +4 -0
  17. package/dist/src/ars/panel-plan.js +11 -0
  18. package/dist/src/ars/panel-plan.js.map +1 -0
  19. package/dist/src/ars/pi-panel-executor.d.ts +30 -0
  20. package/dist/src/ars/pi-panel-executor.js +140 -0
  21. package/dist/src/ars/pi-panel-executor.js.map +1 -0
  22. package/dist/src/ars/profile.d.ts +36 -0
  23. package/dist/src/ars/profile.js +119 -0
  24. package/dist/src/ars/profile.js.map +1 -0
  25. package/dist/src/ars/re-review.d.ts +22 -0
  26. package/dist/src/ars/re-review.js +172 -0
  27. package/dist/src/ars/re-review.js.map +1 -0
  28. package/dist/src/branding.d.ts +2 -4
  29. package/dist/src/branding.js +3 -5
  30. package/dist/src/branding.js.map +1 -1
  31. package/dist/src/bundled-tools.d.ts +3 -0
  32. package/dist/src/bundled-tools.js +21 -0
  33. package/dist/src/bundled-tools.js.map +1 -0
  34. package/dist/src/chat.js +6 -5
  35. package/dist/src/chat.js.map +1 -1
  36. package/dist/src/creation/contracts.d.ts +38 -0
  37. package/dist/src/creation/contracts.js +2 -0
  38. package/dist/src/creation/contracts.js.map +1 -0
  39. package/dist/src/creation/service.d.ts +7 -0
  40. package/dist/src/creation/service.js +196 -0
  41. package/dist/src/creation/service.js.map +1 -0
  42. package/dist/src/index.d.ts +10 -0
  43. package/dist/src/index.js +10 -0
  44. package/dist/src/index.js.map +1 -1
  45. package/dist/src/install/installer.js +32 -10
  46. package/dist/src/install/installer.js.map +1 -1
  47. package/dist/src/orchestration/personas.d.ts +15 -0
  48. package/dist/src/orchestration/personas.js +51 -0
  49. package/dist/src/orchestration/personas.js.map +1 -0
  50. package/dist/src/orchestration/pi-executor.d.ts +1 -0
  51. package/dist/src/orchestration/pi-executor.js +1 -1
  52. package/dist/src/orchestration/pi-executor.js.map +1 -1
  53. package/dist/src/panel/extension.js +29 -8
  54. package/dist/src/panel/extension.js.map +1 -1
  55. package/dist/src/panel/server.js +14 -5
  56. package/dist/src/panel/server.js.map +1 -1
  57. package/dist/src/project/paths.d.ts +3 -0
  58. package/dist/src/project/paths.js +7 -0
  59. package/dist/src/project/paths.js.map +1 -1
  60. package/dist/src/rules/user-rules.d.ts +8 -0
  61. package/dist/src/rules/user-rules.js +36 -0
  62. package/dist/src/rules/user-rules.js.map +1 -0
  63. package/dist/src/skills/contracts.d.ts +4 -4
  64. package/dist/src/skills/recommended.js +1 -1
  65. package/dist/src/skills/registry.js +49 -28
  66. package/dist/src/skills/registry.js.map +1 -1
  67. package/dist/src/style/cli-ui.js +0 -1
  68. package/dist/src/style/cli-ui.js.map +1 -1
  69. package/package.json +14 -3
  70. package/scripts/rebrand-pi.mjs +6 -0
  71. package/skills/recommended/catalog.json +2 -11
  72. package/vendor/ars/.claude/CLAUDE.md +371 -0
  73. package/vendor/ars/.command-invariants.toml +24 -0
  74. package/vendor/ars/CITATION.cff +35 -0
  75. package/vendor/ars/LICENSE +417 -0
  76. package/vendor/ars/MODE_REGISTRY.md +76 -0
  77. package/vendor/ars/NOTICE.md +26 -0
  78. package/vendor/ars/POSITIONING.md +99 -0
  79. package/vendor/ars/PSYCLAW_SOURCE.json +10 -0
  80. package/vendor/ars/README.md +751 -0
  81. package/vendor/ars/SECURITY.md +52 -0
  82. package/vendor/ars/THIRD_PARTY.md +70 -0
  83. package/vendor/ars/academic-paper/SKILL.md +542 -0
  84. package/vendor/ars/academic-paper/agents/abstract_bilingual_agent.md +171 -0
  85. package/vendor/ars/academic-paper/agents/argument_builder_agent.md +276 -0
  86. package/vendor/ars/academic-paper/agents/citation_compliance_agent.md +422 -0
  87. package/vendor/ars/academic-paper/agents/draft_writer_agent.md +656 -0
  88. package/vendor/ars/academic-paper/agents/formatter_agent.md +999 -0
  89. package/vendor/ars/academic-paper/agents/intake_agent.md +393 -0
  90. package/vendor/ars/academic-paper/agents/literature_strategist_agent.md +626 -0
  91. package/vendor/ars/academic-paper/agents/peer_reviewer_agent.md +516 -0
  92. package/vendor/ars/academic-paper/agents/revision_coach_agent.md +334 -0
  93. package/vendor/ars/academic-paper/agents/socratic_mentor_agent.md +527 -0
  94. package/vendor/ars/academic-paper/agents/structure_architect_agent.md +401 -0
  95. package/vendor/ars/academic-paper/agents/visualization_agent.md +441 -0
  96. package/vendor/ars/academic-paper/examples/chinese_paper_example.md +278 -0
  97. package/vendor/ars/academic-paper/examples/clinical_citation_verification_checklist.md +95 -0
  98. package/vendor/ars/academic-paper/examples/clinical_epistemic_status_example.md +100 -0
  99. package/vendor/ars/academic-paper/examples/commitment_ledger_example.md +147 -0
  100. package/vendor/ars/academic-paper/examples/imrad_hei_example.md +234 -0
  101. package/vendor/ars/academic-paper/examples/literature_review_example.md +260 -0
  102. package/vendor/ars/academic-paper/examples/plan_mode_guided_writing.md +600 -0
  103. package/vendor/ars/academic-paper/examples/revision_mode_example.md +344 -0
  104. package/vendor/ars/academic-paper/examples/revision_recovery_example.md +506 -0
  105. package/vendor/ars/academic-paper/examples/version_family_reconciliation_example.md +89 -0
  106. package/vendor/ars/academic-paper/references/abstract_writing_guide.md +169 -0
  107. package/vendor/ars/academic-paper/references/academic_writing_style.md +188 -0
  108. package/vendor/ars/academic-paper/references/anti_leakage_protocol.md +83 -0
  109. package/vendor/ars/academic-paper/references/apa7_chinese_citation_guide.md +364 -0
  110. package/vendor/ars/academic-paper/references/apa7_extended_guide.md +198 -0
  111. package/vendor/ars/academic-paper/references/changelog.md +11 -0
  112. package/vendor/ars/academic-paper/references/citation_format_switcher.md +228 -0
  113. package/vendor/ars/academic-paper/references/committee_correspondence_protocol.md +158 -0
  114. package/vendor/ars/academic-paper/references/credit_authorship_guide.md +308 -0
  115. package/vendor/ars/academic-paper/references/disclosure_mode_protocol.md +478 -0
  116. package/vendor/ars/academic-paper/references/domain_evidence_profiles.md +38 -0
  117. package/vendor/ars/academic-paper/references/failure_paths.md +349 -0
  118. package/vendor/ars/academic-paper/references/funding_statement_guide.md +319 -0
  119. package/vendor/ars/academic-paper/references/hei_domain_glossary.md +169 -0
  120. package/vendor/ars/academic-paper/references/intro_title_rhetoric_guide.md +114 -0
  121. package/vendor/ars/academic-paper/references/journal_submission_guide.md +249 -0
  122. package/vendor/ars/academic-paper/references/latex_template_reference.md +378 -0
  123. package/vendor/ars/academic-paper/references/mode_selection_guide.md +378 -0
  124. package/vendor/ars/academic-paper/references/paper_structure_patterns.md +330 -0
  125. package/vendor/ars/academic-paper/references/plan_mode_protocol.md +112 -0
  126. package/vendor/ars/academic-paper/references/policy_anchor_disclosure_protocol.md +200 -0
  127. package/vendor/ars/academic-paper/references/policy_anchor_table.md +157 -0
  128. package/vendor/ars/academic-paper/references/revision_patch_protocol.md +173 -0
  129. package/vendor/ars/academic-paper/references/statistical_visualization_standards.md +750 -0
  130. package/vendor/ars/academic-paper/references/venue_disclosure_policies.md +259 -0
  131. package/vendor/ars/academic-paper/references/vlm_figure_verification.md +126 -0
  132. package/vendor/ars/academic-paper/references/workflow_phase_details.md +135 -0
  133. package/vendor/ars/academic-paper/references/writing_judgment_framework.md +59 -0
  134. package/vendor/ars/academic-paper/references/writing_quality_check.md +173 -0
  135. package/vendor/ars/academic-paper/templates/bilingual_abstract_template.md +78 -0
  136. package/vendor/ars/academic-paper/templates/case_study_template.md +129 -0
  137. package/vendor/ars/academic-paper/templates/conference_paper_template.md +108 -0
  138. package/vendor/ars/academic-paper/templates/credit_statement_template.md +132 -0
  139. package/vendor/ars/academic-paper/templates/funding_statement_template.md +290 -0
  140. package/vendor/ars/academic-paper/templates/imrad_template.md +183 -0
  141. package/vendor/ars/academic-paper/templates/latex_article_template.tex +199 -0
  142. package/vendor/ars/academic-paper/templates/literature_review_template.md +135 -0
  143. package/vendor/ars/academic-paper/templates/policy_brief_template.md +139 -0
  144. package/vendor/ars/academic-paper/templates/revision_tracking_template.md +199 -0
  145. package/vendor/ars/academic-paper/templates/theoretical_paper_template.md +119 -0
  146. package/vendor/ars/academic-paper-reviewer/SKILL.md +491 -0
  147. package/vendor/ars/academic-paper-reviewer/agents/devils_advocate_reviewer_agent.md +443 -0
  148. package/vendor/ars/academic-paper-reviewer/agents/domain_reviewer_agent.md +412 -0
  149. package/vendor/ars/academic-paper-reviewer/agents/editorial_synthesizer_agent.md +478 -0
  150. package/vendor/ars/academic-paper-reviewer/agents/eic_agent.md +339 -0
  151. package/vendor/ars/academic-paper-reviewer/agents/field_analyst_agent.md +221 -0
  152. package/vendor/ars/academic-paper-reviewer/agents/methodology_reviewer_agent.md +449 -0
  153. package/vendor/ars/academic-paper-reviewer/agents/perspective_reviewer_agent.md +427 -0
  154. package/vendor/ars/academic-paper-reviewer/examples/hei_paper_review_example.md +391 -0
  155. package/vendor/ars/academic-paper-reviewer/examples/interdisciplinary_review_example.md +299 -0
  156. package/vendor/ars/academic-paper-reviewer/examples/subclaim_decomposition_example.md +80 -0
  157. package/vendor/ars/academic-paper-reviewer/references/calibration_mode_protocol.md +256 -0
  158. package/vendor/ars/academic-paper-reviewer/references/changelog.md +10 -0
  159. package/vendor/ars/academic-paper-reviewer/references/editorial_decision_standards.md +236 -0
  160. package/vendor/ars/academic-paper-reviewer/references/guided_mode_protocol.md +34 -0
  161. package/vendor/ars/academic-paper-reviewer/references/integration_guide.md +15 -0
  162. package/vendor/ars/academic-paper-reviewer/references/quality_rubrics.md +84 -0
  163. package/vendor/ars/academic-paper-reviewer/references/re_review_mode_protocol.md +340 -0
  164. package/vendor/ars/academic-paper-reviewer/references/review_criteria_framework.md +98 -0
  165. package/vendor/ars/academic-paper-reviewer/references/review_panel_provenance_protocol.md +197 -0
  166. package/vendor/ars/academic-paper-reviewer/references/review_quality_thinking.md +58 -0
  167. package/vendor/ars/academic-paper-reviewer/references/reviewer_sprint_prompt_source.md +324 -0
  168. package/vendor/ars/academic-paper-reviewer/references/sprint_contract_protocol.md +296 -0
  169. package/vendor/ars/academic-paper-reviewer/references/statistical_reporting_standards.md +505 -0
  170. package/vendor/ars/academic-paper-reviewer/references/top_journals_by_field.md +206 -0
  171. package/vendor/ars/academic-paper-reviewer/templates/editorial_decision_template.md +235 -0
  172. package/vendor/ars/academic-paper-reviewer/templates/peer_review_report_template.md +305 -0
  173. package/vendor/ars/academic-paper-reviewer/templates/revision_response_template.md +248 -0
  174. package/vendor/ars/academic-pipeline/SKILL.md +736 -0
  175. package/vendor/ars/academic-pipeline/agents/claim_ref_alignment_audit_agent.md +382 -0
  176. package/vendor/ars/academic-pipeline/agents/collaboration_depth_agent.md +164 -0
  177. package/vendor/ars/academic-pipeline/agents/integrity_verification_agent.md +870 -0
  178. package/vendor/ars/academic-pipeline/agents/pipeline_orchestrator_agent.md +1379 -0
  179. package/vendor/ars/academic-pipeline/agents/state_tracker_agent.md +622 -0
  180. package/vendor/ars/academic-pipeline/examples/full_pipeline_example.md +482 -0
  181. package/vendor/ars/academic-pipeline/examples/integrity_failure_recovery.md +389 -0
  182. package/vendor/ars/academic-pipeline/examples/mid_entry_example.md +414 -0
  183. package/vendor/ars/academic-pipeline/references/adapters/.gitkeep +0 -0
  184. package/vendor/ars/academic-pipeline/references/adapters/overview.md +153 -0
  185. package/vendor/ars/academic-pipeline/references/ai_research_failure_modes.md +185 -0
  186. package/vendor/ars/academic-pipeline/references/changelog.md +14 -0
  187. package/vendor/ars/academic-pipeline/references/claim_audit_calibration_protocol.md +175 -0
  188. package/vendor/ars/academic-pipeline/references/claim_verification_protocol.md +282 -0
  189. package/vendor/ars/academic-pipeline/references/external_review_protocol.md +131 -0
  190. package/vendor/ars/academic-pipeline/references/integrity_review_protocol.md +110 -0
  191. package/vendor/ars/academic-pipeline/references/literature_corpus_consumers.md +193 -0
  192. package/vendor/ars/academic-pipeline/references/mode_advisor.md +135 -0
  193. package/vendor/ars/academic-pipeline/references/passport_as_reset_boundary.md +132 -0
  194. package/vendor/ars/academic-pipeline/references/pipeline_state_machine.md +405 -0
  195. package/vendor/ars/academic-pipeline/references/plagiarism_detection_protocol.md +239 -0
  196. package/vendor/ars/academic-pipeline/references/process_summary_protocol.md +209 -0
  197. package/vendor/ars/academic-pipeline/references/progress_dashboard_template.md +38 -0
  198. package/vendor/ars/academic-pipeline/references/reinforcement_content.md +15 -0
  199. package/vendor/ars/academic-pipeline/references/reproducibility_audit.md +55 -0
  200. package/vendor/ars/academic-pipeline/references/score_trajectory_protocol.md +78 -0
  201. package/vendor/ars/academic-pipeline/references/team_collaboration_protocol.md +261 -0
  202. package/vendor/ars/academic-pipeline/references/two_stage_review_protocol.md +27 -0
  203. package/vendor/ars/academic-pipeline/templates/pipeline_status_template.md +146 -0
  204. package/vendor/ars/agents/report_compiler_agent.md +341 -0
  205. package/vendor/ars/agents/research_architect_agent.md +298 -0
  206. package/vendor/ars/agents/synthesis_agent.md +356 -0
  207. package/vendor/ars/commands/ars-3w.md +10 -0
  208. package/vendor/ars/commands/ars-abstract.md +10 -0
  209. package/vendor/ars/commands/ars-cache-invalidate.md +20 -0
  210. package/vendor/ars/commands/ars-citation-check.md +10 -0
  211. package/vendor/ars/commands/ars-disclosure.md +10 -0
  212. package/vendor/ars/commands/ars-format-convert.md +10 -0
  213. package/vendor/ars/commands/ars-full.md +9 -0
  214. package/vendor/ars/commands/ars-lit-review.md +12 -0
  215. package/vendor/ars/commands/ars-mark-read.md +18 -0
  216. package/vendor/ars/commands/ars-outline.md +10 -0
  217. package/vendor/ars/commands/ars-plan.md +10 -0
  218. package/vendor/ars/commands/ars-rebuttal-audit.md +12 -0
  219. package/vendor/ars/commands/ars-reviewer.md +9 -0
  220. package/vendor/ars/commands/ars-revision-coach.md +9 -0
  221. package/vendor/ars/commands/ars-revision.md +10 -0
  222. package/vendor/ars/commands/ars-unmark-read.md +16 -0
  223. package/vendor/ars/deep-research/SKILL.md +600 -0
  224. package/vendor/ars/deep-research/agents/bibliography_agent.md +473 -0
  225. package/vendor/ars/deep-research/agents/devils_advocate_agent.md +192 -0
  226. package/vendor/ars/deep-research/agents/editor_in_chief_agent.md +167 -0
  227. package/vendor/ars/deep-research/agents/ethics_review_agent.md +267 -0
  228. package/vendor/ars/deep-research/agents/meta_analysis_agent.md +325 -0
  229. package/vendor/ars/deep-research/agents/monitoring_agent.md +209 -0
  230. package/vendor/ars/deep-research/agents/report_compiler_agent.md +341 -0
  231. package/vendor/ars/deep-research/agents/research_architect_agent.md +298 -0
  232. package/vendor/ars/deep-research/agents/research_question_agent.md +216 -0
  233. package/vendor/ars/deep-research/agents/risk_of_bias_agent.md +231 -0
  234. package/vendor/ars/deep-research/agents/socratic_mentor_agent.md +764 -0
  235. package/vendor/ars/deep-research/agents/source_verification_agent.md +219 -0
  236. package/vendor/ars/deep-research/agents/synthesis_agent.md +356 -0
  237. package/vendor/ars/deep-research/agents/timeline_extraction_agent.md +99 -0
  238. package/vendor/ars/deep-research/examples/exploratory_research.md +157 -0
  239. package/vendor/ars/deep-research/examples/fact_check_mode.md +173 -0
  240. package/vendor/ars/deep-research/examples/handoff_to_paper.md +318 -0
  241. package/vendor/ars/deep-research/examples/idea_diversity_coverage_gap_advisory.md +64 -0
  242. package/vendor/ars/deep-research/examples/policy_analysis.md +161 -0
  243. package/vendor/ars/deep-research/examples/review_mode.md +253 -0
  244. package/vendor/ars/deep-research/examples/socratic_guided_research.md +331 -0
  245. package/vendor/ars/deep-research/examples/systematic_review.md +133 -0
  246. package/vendor/ars/deep-research/references/apa7_style_guide.md +162 -0
  247. package/vendor/ars/deep-research/references/argumentation_reasoning_framework.md +68 -0
  248. package/vendor/ars/deep-research/references/arxiv_api_protocol.md +76 -0
  249. package/vendor/ars/deep-research/references/changelog.md +22 -0
  250. package/vendor/ars/deep-research/references/chinese_literature_api_protocol.md +317 -0
  251. package/vendor/ars/deep-research/references/cross_agent_quality_definitions.md +14 -0
  252. package/vendor/ars/deep-research/references/crossref_api_protocol.md +84 -0
  253. package/vendor/ars/deep-research/references/equator_reporting_guidelines.md +482 -0
  254. package/vendor/ars/deep-research/references/ethics_checklist.md +282 -0
  255. package/vendor/ars/deep-research/references/failure_paths.md +355 -0
  256. package/vendor/ars/deep-research/references/interdisciplinary_bridges.md +292 -0
  257. package/vendor/ars/deep-research/references/irb_decision_tree.md +315 -0
  258. package/vendor/ars/deep-research/references/literature_monitoring_strategies.md +263 -0
  259. package/vendor/ars/deep-research/references/logical_fallacies.md +192 -0
  260. package/vendor/ars/deep-research/references/methodology_patterns.md +462 -0
  261. package/vendor/ars/deep-research/references/mode_selection_guide.md +331 -0
  262. package/vendor/ars/deep-research/references/openalex_api_protocol.md +82 -0
  263. package/vendor/ars/deep-research/references/preregistration_guide.md +324 -0
  264. package/vendor/ars/deep-research/references/semantic_scholar_api_protocol.md +107 -0
  265. package/vendor/ars/deep-research/references/socratic_mode_protocol.md +99 -0
  266. package/vendor/ars/deep-research/references/socratic_questioning_framework.md +232 -0
  267. package/vendor/ars/deep-research/references/source_quality_hierarchy.md +188 -0
  268. package/vendor/ars/deep-research/references/systematic_review_protocol.md +95 -0
  269. package/vendor/ars/deep-research/references/systematic_review_toolkit.md +353 -0
  270. package/vendor/ars/deep-research/templates/evidence_assessment_template.md +127 -0
  271. package/vendor/ars/deep-research/templates/literature_matrix_template.md +85 -0
  272. package/vendor/ars/deep-research/templates/preregistration_template.md +318 -0
  273. package/vendor/ars/deep-research/templates/prisma_protocol_template.md +248 -0
  274. package/vendor/ars/deep-research/templates/prisma_report_template.md +415 -0
  275. package/vendor/ars/deep-research/templates/research_brief_template.md +93 -0
  276. package/vendor/ars/package.json +24 -0
  277. package/vendor/ars/pi/README.md +161 -0
  278. package/vendor/ars/pi/package.json +26 -0
  279. package/vendor/ars/pi/wrapper.js +193 -0
  280. package/vendor/ars/pi/wrapper.test.mjs +201 -0
  281. package/vendor/ars/pyproject.toml +2 -0
  282. package/vendor/ars/requirements-pdf-content-classifier.txt +5 -0
  283. package/vendor/ars/scripts/_block_parser.py +396 -0
  284. package/vendor/ars/scripts/_ci_pytest_manifest.toml +661 -0
  285. package/vendor/ars/scripts/_claim_audit_constants.py +268 -0
  286. package/vendor/ars/scripts/_e4_evidence.py +110 -0
  287. package/vendor/ars/scripts/_eval_threshold_gate.py +73 -0
  288. package/vendor/ars/scripts/_markdown_lint_util.py +224 -0
  289. package/vendor/ars/scripts/_next_verified_at_ms.py +176 -0
  290. package/vendor/ars/scripts/_passport_yaml.py +53 -0
  291. package/vendor/ars/scripts/_skill_lint.py +254 -0
  292. package/vendor/ars/scripts/_text_similarity.py +141 -0
  293. package/vendor/ars/scripts/adapters/README.md +89 -0
  294. package/vendor/ars/scripts/adapters/_common.py +209 -0
  295. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_passport.yaml +25 -0
  296. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_rejection_log.yaml +18 -0
  297. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Chen2024_AIAssessment.pdf +0 -0
  298. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Wang_2023_formative_feedback.pdf +0 -0
  299. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/paper1.pdf +0 -0
  300. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture//344/270/255/346/226/207/346/252/224/345/220/215_2024.pdf +0 -0
  301. package/vendor/ars/scripts/adapters/examples/obsidian/expected_passport.yaml +40 -0
  302. package/vendor/ars/scripts/adapters/examples/obsidian/expected_rejection_log.yaml +13 -0
  303. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.gitkeep +0 -0
  304. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.obsidian/app.json +1 -0
  305. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/_templates/tmpl.md +7 -0
  306. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/chen2024ai.md +13 -0
  307. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/invalid.md +1 -0
  308. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/wang2023formative.md +10 -0
  309. package/vendor/ars/scripts/adapters/examples/zotero/expected_passport.yaml +34 -0
  310. package/vendor/ars/scripts/adapters/examples/zotero/expected_rejection_log.yaml +34 -0
  311. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/.gitkeep +0 -0
  312. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/export.json +43 -0
  313. package/vendor/ars/scripts/adapters/folder_scan.py +214 -0
  314. package/vendor/ars/scripts/adapters/obsidian.py +336 -0
  315. package/vendor/ars/scripts/adapters/tests/.gitkeep +0 -0
  316. package/vendor/ars/scripts/adapters/tests/conftest.py +77 -0
  317. package/vendor/ars/scripts/adapters/tests/test_check_corpus_consumer_protocol.py +632 -0
  318. package/vendor/ars/scripts/adapters/tests/test_check_literature_corpus_schema.py +631 -0
  319. package/vendor/ars/scripts/adapters/tests/test_common.py +365 -0
  320. package/vendor/ars/scripts/adapters/tests/test_conftest.py +96 -0
  321. package/vendor/ars/scripts/adapters/tests/test_folder_scan.py +260 -0
  322. package/vendor/ars/scripts/adapters/tests/test_literature_corpus_entry_schema.py +745 -0
  323. package/vendor/ars/scripts/adapters/tests/test_obsidian.py +357 -0
  324. package/vendor/ars/scripts/adapters/tests/test_rejection_log_schema.py +271 -0
  325. package/vendor/ars/scripts/adapters/tests/test_sync_adapter_docs.py +88 -0
  326. package/vendor/ars/scripts/adapters/tests/test_zotero.py +454 -0
  327. package/vendor/ars/scripts/adapters/zotero.py +318 -0
  328. package/vendor/ars/scripts/adjudication_activity.py +1592 -0
  329. package/vendor/ars/scripts/announce-ars-loaded.sh +144 -0
  330. package/vendor/ars/scripts/ars_anchorize_draft.py +170 -0
  331. package/vendor/ars/scripts/ars_apply_revision_patch.py +912 -0
  332. package/vendor/ars/scripts/ars_cache_invalidate.py +40 -0
  333. package/vendor/ars/scripts/ars_mark_read.py +521 -0
  334. package/vendor/ars/scripts/ars_phase_scope_manifest.json +33 -0
  335. package/vendor/ars/scripts/ars_update_check.sh +215 -0
  336. package/vendor/ars/scripts/ars_write_scope_guard.py +506 -0
  337. package/vendor/ars/scripts/arxiv_client.py +222 -0
  338. package/vendor/ars/scripts/audit_snapshot.py +572 -0
  339. package/vendor/ars/scripts/bibliographic_integrity_signals.py +800 -0
  340. package/vendor/ars/scripts/bootstrap_timeline_yaml.py +146 -0
  341. package/vendor/ars/scripts/build_claim_standing_candidate_ledger.py +1238 -0
  342. package/vendor/ars/scripts/build_claim_standing_query_plan.py +643 -0
  343. package/vendor/ars/scripts/build_content_coverage_advisory.py +1205 -0
  344. package/vendor/ars/scripts/build_cross_document_consistency_advisory.py +2332 -0
  345. package/vendor/ars/scripts/build_review_pathway_rule_trace.py +830 -0
  346. package/vendor/ars/scripts/build_submission_packet_manifest.py +2310 -0
  347. package/vendor/ars/scripts/check_215_field_norm.py +173 -0
  348. package/vendor/ars/scripts/check_216_surface_form.py +250 -0
  349. package/vendor/ars/scripts/check_268_nested_commitment_ledger.py +180 -0
  350. package/vendor/ars/scripts/check_390_revision_patch_discipline.py +296 -0
  351. package/vendor/ars/scripts/check_392_citation_verification_intake.py +126 -0
  352. package/vendor/ars/scripts/check_394_submission_policy.py +178 -0
  353. package/vendor/ars/scripts/check_439_format_profile.py +307 -0
  354. package/vendor/ars/scripts/check_619_disclosure_closeout.py +237 -0
  355. package/vendor/ars/scripts/check_630_codex_subscription_transport.py +456 -0
  356. package/vendor/ars/scripts/check_669_review_pathway_rule_trace.py +662 -0
  357. package/vendor/ars/scripts/check_670_revision_roadmap_integration.py +518 -0
  358. package/vendor/ars/scripts/check_673_adjudication_activity.py +684 -0
  359. package/vendor/ars/scripts/check_684_review_criteria_binding.py +557 -0
  360. package/vendor/ars/scripts/check_agents_mirror_sync.py +115 -0
  361. package/vendor/ars/scripts/check_audit_artifact_consistency.py +2313 -0
  362. package/vendor/ars/scripts/check_benchmark_report.py +79 -0
  363. package/vendor/ars/scripts/check_bibliographic_integrity_signals.py +831 -0
  364. package/vendor/ars/scripts/check_calibration_tiers.py +235 -0
  365. package/vendor/ars/scripts/check_changelog_covers_merges.py +289 -0
  366. package/vendor/ars/scripts/check_ci_pytest_manifest.py +204 -0
  367. package/vendor/ars/scripts/check_claim_audit_consistency.py +1664 -0
  368. package/vendor/ars/scripts/check_claim_standing_candidate_ledger_integration.py +500 -0
  369. package/vendor/ars/scripts/check_claim_standing_freshness.py +253 -0
  370. package/vendor/ars/scripts/check_claim_standing_transmissions.py +449 -0
  371. package/vendor/ars/scripts/check_collaboration_depth_rubric.py +180 -0
  372. package/vendor/ars/scripts/check_command_frontmatter_name.py +116 -0
  373. package/vendor/ars/scripts/check_committee_correspondence.py +333 -0
  374. package/vendor/ars/scripts/check_compliance_report.py +108 -0
  375. package/vendor/ars/scripts/check_content_coverage_advisory_integration.py +796 -0
  376. package/vendor/ars/scripts/check_control_availability.py +172 -0
  377. package/vendor/ars/scripts/check_corpus_consumer_protocol.py +404 -0
  378. package/vendor/ars/scripts/check_cross_document_consistency_advisory_integration.py +1191 -0
  379. package/vendor/ars/scripts/check_cross_model_handoff_contract.py +234 -0
  380. package/vendor/ars/scripts/check_cross_model_verification_sync.py +261 -0
  381. package/vendor/ars/scripts/check_data_access_level.py +131 -0
  382. package/vendor/ars/scripts/check_data_flows.py +252 -0
  383. package/vendor/ars/scripts/check_decision_contract.py +464 -0
  384. package/vendor/ars/scripts/check_degradation_registry.py +326 -0
  385. package/vendor/ars/scripts/check_distribution_surface_claims.py +226 -0
  386. package/vendor/ars/scripts/check_domain_evidence_profile.py +538 -0
  387. package/vendor/ars/scripts/check_e4_promotion.py +195 -0
  388. package/vendor/ars/scripts/check_evals_gold_set.py +279 -0
  389. package/vendor/ars/scripts/check_evidence_row_integration.py +396 -0
  390. package/vendor/ars/scripts/check_experiment_provenance.py +117 -0
  391. package/vendor/ars/scripts/check_field_norm_severity.py +144 -0
  392. package/vendor/ars/scripts/check_firm_rules_sync.py +375 -0
  393. package/vendor/ars/scripts/check_heldout_measurement_report.py +1179 -0
  394. package/vendor/ars/scripts/check_human_subjects_output_contract.py +139 -0
  395. package/vendor/ars/scripts/check_human_subjects_reference_migration.py +844 -0
  396. package/vendor/ars/scripts/check_indirect_prompt_injection_no_call.py +328 -0
  397. package/vendor/ars/scripts/check_instruction_data_boundary.py +236 -0
  398. package/vendor/ars/scripts/check_judge_prompt_version.py +125 -0
  399. package/vendor/ars/scripts/check_literature_corpus_schema.py +402 -0
  400. package/vendor/ars/scripts/check_model_tiering.py +223 -0
  401. package/vendor/ars/scripts/check_panel_synthesis.py +1331 -0
  402. package/vendor/ars/scripts/check_passport_reset_contract.py +214 -0
  403. package/vendor/ars/scripts/check_pattern_eval_manifest.py +422 -0
  404. package/vendor/ars/scripts/check_persuasion_invariance_fixtures.py +637 -0
  405. package/vendor/ars/scripts/check_phase_conformance.py +2180 -0
  406. package/vendor/ars/scripts/check_pipeline_boundary_semantics.py +600 -0
  407. package/vendor/ars/scripts/check_pipeline_integrity.py +340 -0
  408. package/vendor/ars/scripts/check_policy_anchor_protocol.py +159 -0
  409. package/vendor/ars/scripts/check_policy_anchor_table.py +286 -0
  410. package/vendor/ars/scripts/check_preprint_venues_consistency.py +123 -0
  411. package/vendor/ars/scripts/check_prisma_trAIce_freshness.py +84 -0
  412. package/vendor/ars/scripts/check_promotion_bakeoff_preregistration.py +1303 -0
  413. package/vendor/ars/scripts/check_ranking_lift.py +323 -0
  414. package/vendor/ars/scripts/check_re_review_synthesis.py +2719 -0
  415. package/vendor/ars/scripts/check_receipt_enum_sync.py +203 -0
  416. package/vendor/ars/scripts/check_repro_lock.py +85 -0
  417. package/vendor/ars/scripts/check_review_pathway_output.py +276 -0
  418. package/vendor/ars/scripts/check_reviewer_data_fences.py +224 -0
  419. package/vendor/ars/scripts/check_reviewer_finding_contract.py +783 -0
  420. package/vendor/ars/scripts/check_reviewer_role_label.py +447 -0
  421. package/vendor/ars/scripts/check_reviewer_scoring_honesty.py +292 -0
  422. package/vendor/ars/scripts/check_reviewer_sprint_prompt_sync.py +409 -0
  423. package/vendor/ars/scripts/check_revision_claim_drift_suite_v2.py +1622 -0
  424. package/vendor/ars/scripts/check_revision_token_conservation.py +263 -0
  425. package/vendor/ars/scripts/check_risk_register.py +280 -0
  426. package/vendor/ars/scripts/check_role_scoped_contract.py +702 -0
  427. package/vendor/ars/scripts/check_rq_framing_patterns.py +184 -0
  428. package/vendor/ars/scripts/check_rubric_weight_consistency.py +32 -0
  429. package/vendor/ars/scripts/check_seeded_defect_fixtures.py +425 -0
  430. package/vendor/ars/scripts/check_setup_cross_model_parity.py +139 -0
  431. package/vendor/ars/scripts/check_spec_consistency.py +1249 -0
  432. package/vendor/ars/scripts/check_sprint_contract.py +371 -0
  433. package/vendor/ars/scripts/check_stage_capability_matrix.py +784 -0
  434. package/vendor/ars/scripts/check_submission_packet_manifest_integration.py +358 -0
  435. package/vendor/ars/scripts/check_surface_form_parity.py +445 -0
  436. package/vendor/ars/scripts/check_task_type.py +22 -0
  437. package/vendor/ars/scripts/check_tools_allowlist.py +538 -0
  438. package/vendor/ars/scripts/check_tortured_phrase_screening_integration.py +1974 -0
  439. package/vendor/ars/scripts/check_v3_10_134_write_scope.py +286 -0
  440. package/vendor/ars/scripts/check_v3_10_policy.py +656 -0
  441. package/vendor/ars/scripts/check_v3_6_6_ab_manifest.py +364 -0
  442. package/vendor/ars/scripts/check_v3_6_7_pattern_protection.py +1366 -0
  443. package/vendor/ars/scripts/check_v3_6_8_audit_scope_block.py +464 -0
  444. package/vendor/ars/scripts/check_v3_6_8_cite_provenance_pipeline.py +231 -0
  445. package/vendor/ars/scripts/check_v3_6_8_frontmatter_trust_schema.py +248 -0
  446. package/vendor/ars/scripts/check_v3_6_8_mark_read_commands.py +79 -0
  447. package/vendor/ars/scripts/check_v3_6_8_pattern_protection.py +941 -0
  448. package/vendor/ars/scripts/check_v3_7_3_three_layer_citation.py +318 -0
  449. package/vendor/ars/scripts/check_v3_8_annotation_literal_sync.py +228 -0
  450. package/vendor/ars/scripts/check_v3_9_0_triangulation.py +366 -0
  451. package/vendor/ars/scripts/check_v3_9_2_phase_boundary.py +270 -0
  452. package/vendor/ars/scripts/check_v3_9_4_temporal_verification.py +139 -0
  453. package/vendor/ars/scripts/check_venue_disclosure_policies.py +63 -0
  454. package/vendor/ars/scripts/check_version_consistency.py +826 -0
  455. package/vendor/ars/scripts/check_workflow_classification.py +223 -0
  456. package/vendor/ars/scripts/chinese_literature_client.py +1938 -0
  457. package/vendor/ars/scripts/citation_verification_summary.py +85 -0
  458. package/vendor/ars/scripts/claim_audit_calibration.py +517 -0
  459. package/vendor/ars/scripts/claim_audit_finalizer.py +456 -0
  460. package/vendor/ars/scripts/claim_audit_pipeline.py +1594 -0
  461. package/vendor/ars/scripts/claim_registry_coverage.py +493 -0
  462. package/vendor/ars/scripts/claim_standing_discovery.py +784 -0
  463. package/vendor/ars/scripts/claim_standing_stance_runner.py +758 -0
  464. package/vendor/ars/scripts/claim_standing_stance_scorer.py +239 -0
  465. package/vendor/ars/scripts/claim_strength_drift_disposition.py +666 -0
  466. package/vendor/ars/scripts/contamination_signals.py +689 -0
  467. package/vendor/ars/scripts/corpus_consumer_manifest.json +19 -0
  468. package/vendor/ars/scripts/cross_model_codex_transport.py +1374 -0
  469. package/vendor/ars/scripts/cross_model_codex_verify.sh +6 -0
  470. package/vendor/ars/scripts/cross_model_handoff.py +359 -0
  471. package/vendor/ars/scripts/cross_model_smoke_test.sh +183 -0
  472. package/vendor/ars/scripts/cross_model_smoke_test_codex.sh +35 -0
  473. package/vendor/ars/scripts/cross_model_verification/gemini_is_grounded.jq +45 -0
  474. package/vendor/ars/scripts/cross_model_verification/gemini_sources.jq +45 -0
  475. package/vendor/ars/scripts/cross_model_verification/normalize_compat_verdict.py +57 -0
  476. package/vendor/ars/scripts/cross_model_verification/openai_has_completed_web_search.jq +15 -0
  477. package/vendor/ars/scripts/cross_model_verification/openai_sources.jq +17 -0
  478. package/vendor/ars/scripts/cross_model_verification/openai_text.jq +11 -0
  479. package/vendor/ars/scripts/crossref_client.py +225 -0
  480. package/vendor/ars/scripts/dispatch_e4_panel.py +2731 -0
  481. package/vendor/ars/scripts/evidence_rows.py +2043 -0
  482. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3.json +32 -0
  483. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_input.json +27 -0
  484. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime.json +32 -0
  485. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime_input.json +27 -0
  486. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override.json +50 -0
  487. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override_action.json +14 -0
  488. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_pass.json +44 -0
  489. package/vendor/ars/scripts/fixtures/adjudication_activity/explicit_user_request_log.json +26 -0
  490. package/vendor/ars/scripts/fixtures/adjudication_activity/mandatory_checkpoint_log.json +116 -0
  491. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/README.md +56 -0
  492. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +24 -0
  493. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  494. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  495. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  496. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a7_orphan_completion/2026-04-30T15-22-04Z-d8f3.jsonl +3 -0
  497. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +26 -0
  498. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  499. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  500. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  501. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +24 -0
  502. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  503. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  504. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.verdict.yaml +12 -0
  505. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction.json +46 -0
  506. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction_check_attestation.json +44 -0
  507. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase.json +44 -0
  508. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_abstract_missing.json +107 -0
  509. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_detected.json +124 -0
  510. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/expected_outcomes.json +77 -0
  511. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/manifest.yaml +37 -0
  512. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/001-valid-doi-test.json +20 -0
  513. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/002-valid-arxiv-test.json +19 -0
  514. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/003-fabricated-test.json +20 -0
  515. package/vendor/ars/scripts/fixtures/claim_audit_calibration/gold_set.json +344 -0
  516. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/query_plan.json +108 -0
  517. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/retrieval_input.json +179 -0
  518. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/concern_tracker.json +129 -0
  519. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/response_skeleton.md +19 -0
  520. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/source_letter.txt +9 -0
  521. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_draft.json +48 -0
  522. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_inventory.json +38 -0
  523. package/vendor/ars/scripts/fixtures/content_coverage_advisory/packet/consent.txt +1 -0
  524. package/vendor/ars/scripts/fixtures/content_coverage_advisory/session_sources.json +3 -0
  525. package/vendor/ars/scripts/fixtures/cross_document_consistency/README.md +6 -0
  526. package/vendor/ars/scripts/fixtures/cross_document_consistency/accepted_draft.md +35 -0
  527. package/vendor/ars/scripts/fixtures/cross_document_consistency/cases.json +75 -0
  528. package/vendor/ars/scripts/fixtures/cross_document_consistency/preregistration.md +5 -0
  529. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/forbidden_event.jsonl +4 -0
  530. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/grounded_verified.jsonl +3 -0
  531. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/malformed.jsonl +3 -0
  532. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/missing_search.jsonl +2 -0
  533. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/multiple_finals.jsonl +4 -0
  534. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/not_found.jsonl +3 -0
  535. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/unbound_source.jsonl +3 -0
  536. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/wrong_search_shape.jsonl +3 -0
  537. package/vendor/ars/scripts/fixtures/evidence_rows/phase_e_inputs.json +114 -0
  538. package/vendor/ars/scripts/fixtures/evidence_rows/session_sources.json +5 -0
  539. package/vendor/ars/scripts/fixtures/human_subjects_authority/cross-border-us-tw-gdpr.json +71 -0
  540. package/vendor/ars/scripts/fixtures/human_subjects_authority/gdpr-member-state-unresolved.json +62 -0
  541. package/vendor/ars/scripts/fixtures/human_subjects_authority/missing-data-axis.json +45 -0
  542. package/vendor/ars/scripts/fixtures/human_subjects_authority/no-profile.json +33 -0
  543. package/vendor/ars/scripts/fixtures/human_subjects_authority/tw-gdpr-two-axis.json +74 -0
  544. package/vendor/ars/scripts/fixtures/human_subjects_authority/us-gdpr-two-axis.json +74 -0
  545. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/lint-near-misses.json +72 -0
  546. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/no-profile-request.json +18 -0
  547. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/tw-candidates-request.json +63 -0
  548. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/us-candidates-request.json +77 -0
  549. package/vendor/ars/scripts/fixtures/review_target_context/exact-declaration.json +24 -0
  550. package/vendor/ars/scripts/fixtures/review_target_context/field-general-declaration.json +24 -0
  551. package/vendor/ars/scripts/fixtures/review_target_context/msr-2027-technical-full-declaration.json +24 -0
  552. package/vendor/ars/scripts/fixtures/review_target_context/synthetic-registry.json +92 -0
  553. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/README.md +21 -0
  554. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_attested_only.json +55 -0
  555. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_machine_supported.json +49 -0
  556. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_not_isolated.json +56 -0
  557. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_unknown.json +49 -0
  558. package/vendor/ars/scripts/fixtures/submission_package/clean/paper.md +16 -0
  559. package/vendor/ars/scripts/fixtures/submission_package/clean/references.bib +13 -0
  560. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/paper.md +11 -0
  561. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/references.bib +13 -0
  562. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/paper.tex +9 -0
  563. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/references.bib +13 -0
  564. package/vendor/ars/scripts/fixtures/submission_package/marker_no_join/paper.md +7 -0
  565. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/paper.md +8 -0
  566. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/references.bib +6 -0
  567. package/vendor/ars/scripts/fixtures/submission_package/passports/corpus_only.yaml +9 -0
  568. package/vendor/ars/scripts/fixtures/submission_package/passports/summary_join.yaml +16 -0
  569. package/vendor/ars/scripts/fixtures/submission_package/profiles/full.yaml +15 -0
  570. package/vendor/ars/scripts/fixtures/submission_package/profiles/tight.yaml +15 -0
  571. package/vendor/ars/scripts/fixtures/submission_package/summary_join/paper.md +7 -0
  572. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/paper.md +9 -0
  573. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/references.bib +13 -0
  574. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/paper.md +26 -0
  575. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/references.bib +13 -0
  576. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/paper.md +20 -0
  577. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/references.bib +13 -0
  578. package/vendor/ars/scripts/fixtures/submission_packet_manifest/base_inventory.json +101 -0
  579. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/consent-materials.txt +3 -0
  580. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/training-certificate.txt +2 -0
  581. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/tw-consent-materials.txt +3 -0
  582. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/corpus_input.yaml +30 -0
  583. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.md +36 -0
  584. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.tex +21 -0
  585. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/seed_expectations.json +218 -0
  586. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot.json +164 -0
  587. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot_manifest.json +29 -0
  588. package/vendor/ars/scripts/fixtures/transport_bodies/README.md +55 -0
  589. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/empty_feed.xml +10 -0
  590. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/error_5xx.html +7 -0
  591. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/id_hit.xml +26 -0
  592. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/README.md +69 -0
  593. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/cnki_landing_page.html +13 -0
  594. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/error_5xx.html +2 -0
  595. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_ambiguous.json +16 -0
  596. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_hit.json +16 -0
  597. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_zero.json +14 -0
  598. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_hit.json +15 -0
  599. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_zero.json +13 -0
  600. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_hit.json +43 -0
  601. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_issn_mismatch.json +31 -0
  602. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_no_doi.json +31 -0
  603. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_unknown_ra.json +34 -0
  604. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_year_mismatch.json +31 -0
  605. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_absent.json +4 -0
  606. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_exists.json +16 -0
  607. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_internal_error.json +4 -0
  608. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_hit.json +25 -0
  609. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_other_title.json +18 -0
  610. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_cnki.json +6 -0
  611. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_crossref.json +6 -0
  612. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_istic.json +6 -0
  613. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_unknown_prefix.json +6 -0
  614. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/doi_hit.json +24 -0
  615. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/error_5xx.html +7 -0
  616. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/title_search_miss.json +15 -0
  617. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/doi_hit.json +29 -0
  618. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/error_5xx.json +4 -0
  619. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/title_search_miss.json +11 -0
  620. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/doi_hit.json +14 -0
  621. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/error_5xx.json +3 -0
  622. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/title_search_miss.json +5 -0
  623. package/vendor/ars/scripts/human_read_attestation_resolver.py +467 -0
  624. package/vendor/ars/scripts/ideation_diversity_assignment_gate.py +430 -0
  625. package/vendor/ars/scripts/inquiry_branch_ledger.py +2540 -0
  626. package/vendor/ars/scripts/legacy/ars_apply_revision_patch_v1_0.py +715 -0
  627. package/vendor/ars/scripts/legacy/check_re_review_synthesis_v1_0.py +2215 -0
  628. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_10.py +223 -0
  629. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_7_3.py +277 -0
  630. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_9_0.py +304 -0
  631. package/vendor/ars/scripts/model_tiering_manifest.json +46 -0
  632. package/vendor/ars/scripts/openalex_client.py +232 -0
  633. package/vendor/ars/scripts/parse_audit_verdict.py +802 -0
  634. package/vendor/ars/scripts/pdf_content_classifier_worker.py +176 -0
  635. package/vendor/ars/scripts/pdf_read_preflight.py +1455 -0
  636. package/vendor/ars/scripts/policy_anchor_disclosure_referee.py +354 -0
  637. package/vendor/ars/scripts/recompute_receipts.py +1414 -0
  638. package/vendor/ars/scripts/render_claim_standing_view.py +374 -0
  639. package/vendor/ars/scripts/render_eval_comment.py +130 -0
  640. package/vendor/ars/scripts/render_harness_retirement_issue.py +167 -0
  641. package/vendor/ars/scripts/repro_lock_validation.py +90 -0
  642. package/vendor/ars/scripts/research_workflow_profile.py +1079 -0
  643. package/vendor/ars/scripts/resolve_human_subjects_authority.py +1158 -0
  644. package/vendor/ars/scripts/resolve_review_target_context.py +683 -0
  645. package/vendor/ars/scripts/resume_e4_record.py +509 -0
  646. package/vendor/ars/scripts/retraction_status.py +484 -0
  647. package/vendor/ars/scripts/review_criteria_binding.py +889 -0
  648. package/vendor/ars/scripts/review_panel_provenance.py +744 -0
  649. package/vendor/ars/scripts/revision_roadmap.py +1967 -0
  650. package/vendor/ars/scripts/run_ci_pytest_manifest.py +116 -0
  651. package/vendor/ars/scripts/run_codex_audit.sh +1191 -0
  652. package/vendor/ars/scripts/run_evals.py +513 -0
  653. package/vendor/ars/scripts/run_ideation_diversity_no_call.py +3505 -0
  654. package/vendor/ars/scripts/run_indirect_prompt_injection_no_call.py +3330 -0
  655. package/vendor/ars/scripts/run_indirect_prompt_injection_probe.py +399 -0
  656. package/vendor/ars/scripts/run_review_criteria_constructive_value.py +1895 -0
  657. package/vendor/ars/scripts/run_role_topology_utility_dry_run.py +606 -0
  658. package/vendor/ars/scripts/score_review_criteria_constructive_value.py +617 -0
  659. package/vendor/ars/scripts/semantic_scholar_client.py +291 -0
  660. package/vendor/ars/scripts/slr_lineage.py +59 -0
  661. package/vendor/ars/scripts/sync_adapter_docs.py +118 -0
  662. package/vendor/ars/scripts/temporal_integrity_audit.py +840 -0
  663. package/vendor/ars/scripts/test_431_exact_or_bust.py +253 -0
  664. package/vendor/ars/scripts/test__eval_threshold_gate.py +125 -0
  665. package/vendor/ars/scripts/test__markdown_lint_util.py +129 -0
  666. package/vendor/ars/scripts/test__next_verified_at_ms.py +256 -0
  667. package/vendor/ars/scripts/test_adjacent_framing_probe_lint.py +171 -0
  668. package/vendor/ars/scripts/test_adjudication_activity.py +1515 -0
  669. package/vendor/ars/scripts/test_ars_anchorize_draft.py +178 -0
  670. package/vendor/ars/scripts/test_ars_apply_revision_patch.py +1335 -0
  671. package/vendor/ars/scripts/test_ars_cache_invalidate.py +51 -0
  672. package/vendor/ars/scripts/test_ars_mark_read.py +910 -0
  673. package/vendor/ars/scripts/test_ars_update_check.py +816 -0
  674. package/vendor/ars/scripts/test_ars_write_scope_guard.py +790 -0
  675. package/vendor/ars/scripts/test_arxiv_client.py +374 -0
  676. package/vendor/ars/scripts/test_audit_schemas.py +560 -0
  677. package/vendor/ars/scripts/test_audit_snapshot_render_section_0.py +105 -0
  678. package/vendor/ars/scripts/test_block_parser.py +259 -0
  679. package/vendor/ars/scripts/test_bootstrap_timeline_yaml.py +148 -0
  680. package/vendor/ars/scripts/test_build_claim_standing_candidate_ledger.py +1203 -0
  681. package/vendor/ars/scripts/test_build_claim_standing_query_plan.py +791 -0
  682. package/vendor/ars/scripts/test_build_submission_packet_manifest.py +2644 -0
  683. package/vendor/ars/scripts/test_check_215_field_norm.py +238 -0
  684. package/vendor/ars/scripts/test_check_216_surface_form.py +341 -0
  685. package/vendor/ars/scripts/test_check_268_nested_commitment_ledger.py +194 -0
  686. package/vendor/ars/scripts/test_check_390_revision_patch_discipline.py +279 -0
  687. package/vendor/ars/scripts/test_check_392_citation_verification_intake.py +144 -0
  688. package/vendor/ars/scripts/test_check_394_submission_policy.py +200 -0
  689. package/vendor/ars/scripts/test_check_439_format_profile.py +252 -0
  690. package/vendor/ars/scripts/test_check_619_disclosure_closeout.py +158 -0
  691. package/vendor/ars/scripts/test_check_630_codex_subscription_transport.py +245 -0
  692. package/vendor/ars/scripts/test_check_669_review_pathway_rule_trace.py +304 -0
  693. package/vendor/ars/scripts/test_check_670_revision_roadmap_integration.py +260 -0
  694. package/vendor/ars/scripts/test_check_673_adjudication_activity.py +367 -0
  695. package/vendor/ars/scripts/test_check_684_review_criteria_binding.py +274 -0
  696. package/vendor/ars/scripts/test_check_agents_mirror_sync.py +137 -0
  697. package/vendor/ars/scripts/test_check_audit_artifact_consistency.py +2133 -0
  698. package/vendor/ars/scripts/test_check_benchmark_report.py +117 -0
  699. package/vendor/ars/scripts/test_check_bibliographic_integrity_signals.py +609 -0
  700. package/vendor/ars/scripts/test_check_calibration_tiers.py +376 -0
  701. package/vendor/ars/scripts/test_check_changelog_covers_merges.py +509 -0
  702. package/vendor/ars/scripts/test_check_ci_pytest_manifest.py +425 -0
  703. package/vendor/ars/scripts/test_check_claim_standing_candidate_ledger_integration.py +256 -0
  704. package/vendor/ars/scripts/test_check_claim_standing_freshness.py +277 -0
  705. package/vendor/ars/scripts/test_check_collaboration_depth_rubric.py +239 -0
  706. package/vendor/ars/scripts/test_check_command_frontmatter_name.py +178 -0
  707. package/vendor/ars/scripts/test_check_committee_correspondence.py +298 -0
  708. package/vendor/ars/scripts/test_check_compliance_report.py +381 -0
  709. package/vendor/ars/scripts/test_check_content_coverage_advisory_integration.py +308 -0
  710. package/vendor/ars/scripts/test_check_control_availability.py +361 -0
  711. package/vendor/ars/scripts/test_check_cross_document_consistency_advisory_integration.py +698 -0
  712. package/vendor/ars/scripts/test_check_cross_model_handoff_contract.py +301 -0
  713. package/vendor/ars/scripts/test_check_cross_model_verification_sync.py +203 -0
  714. package/vendor/ars/scripts/test_check_data_access_level.py +227 -0
  715. package/vendor/ars/scripts/test_check_data_flows.py +382 -0
  716. package/vendor/ars/scripts/test_check_decision_contract.py +387 -0
  717. package/vendor/ars/scripts/test_check_degradation_registry.py +270 -0
  718. package/vendor/ars/scripts/test_check_distribution_surface_claims.py +225 -0
  719. package/vendor/ars/scripts/test_check_domain_evidence_profile.py +439 -0
  720. package/vendor/ars/scripts/test_check_e4_promotion.py +163 -0
  721. package/vendor/ars/scripts/test_check_evals_gold_set.py +312 -0
  722. package/vendor/ars/scripts/test_check_evidence_row_integration.py +187 -0
  723. package/vendor/ars/scripts/test_check_field_norm_severity.py +173 -0
  724. package/vendor/ars/scripts/test_check_firm_rules_sync.py +342 -0
  725. package/vendor/ars/scripts/test_check_heldout_measurement_report.py +1508 -0
  726. package/vendor/ars/scripts/test_check_human_subjects_output_contract.py +129 -0
  727. package/vendor/ars/scripts/test_check_human_subjects_reference_migration.py +756 -0
  728. package/vendor/ars/scripts/test_check_instruction_data_boundary.py +204 -0
  729. package/vendor/ars/scripts/test_check_judge_prompt_version.py +90 -0
  730. package/vendor/ars/scripts/test_check_model_tiering.py +236 -0
  731. package/vendor/ars/scripts/test_check_panel_synthesis.py +1658 -0
  732. package/vendor/ars/scripts/test_check_passport_reset_contract.py +249 -0
  733. package/vendor/ars/scripts/test_check_pattern_eval_manifest.py +381 -0
  734. package/vendor/ars/scripts/test_check_persuasion_invariance_fixtures.py +591 -0
  735. package/vendor/ars/scripts/test_check_phase_conformance.py +4366 -0
  736. package/vendor/ars/scripts/test_check_pipeline_boundary_semantics.py +931 -0
  737. package/vendor/ars/scripts/test_check_pipeline_integrity.py +243 -0
  738. package/vendor/ars/scripts/test_check_policy_anchor_protocol.py +236 -0
  739. package/vendor/ars/scripts/test_check_policy_anchor_table.py +295 -0
  740. package/vendor/ars/scripts/test_check_prisma_trAIce_freshness.py +68 -0
  741. package/vendor/ars/scripts/test_check_promotion_bakeoff_preregistration.py +799 -0
  742. package/vendor/ars/scripts/test_check_ranking_lift.py +377 -0
  743. package/vendor/ars/scripts/test_check_re_review_synthesis.py +3398 -0
  744. package/vendor/ars/scripts/test_check_receipt_enum_sync.py +176 -0
  745. package/vendor/ars/scripts/test_check_repro_lock.py +107 -0
  746. package/vendor/ars/scripts/test_check_reviewer_data_fences.py +334 -0
  747. package/vendor/ars/scripts/test_check_reviewer_finding_contract.py +1107 -0
  748. package/vendor/ars/scripts/test_check_reviewer_role_label.py +491 -0
  749. package/vendor/ars/scripts/test_check_reviewer_scoring_honesty.py +222 -0
  750. package/vendor/ars/scripts/test_check_reviewer_sprint_prompt_sync.py +373 -0
  751. package/vendor/ars/scripts/test_check_revision_claim_drift_suite_v2.py +1925 -0
  752. package/vendor/ars/scripts/test_check_revision_token_conservation.py +398 -0
  753. package/vendor/ars/scripts/test_check_risk_register.py +336 -0
  754. package/vendor/ars/scripts/test_check_role_scoped_contract.py +1104 -0
  755. package/vendor/ars/scripts/test_check_rq_framing_patterns.py +110 -0
  756. package/vendor/ars/scripts/test_check_rubric_weight_consistency.py +32 -0
  757. package/vendor/ars/scripts/test_check_seeded_defect_fixtures.py +392 -0
  758. package/vendor/ars/scripts/test_check_setup_cross_model_parity.py +121 -0
  759. package/vendor/ars/scripts/test_check_spec_consistency.py +1081 -0
  760. package/vendor/ars/scripts/test_check_sprint_contract.py +458 -0
  761. package/vendor/ars/scripts/test_check_stage_capability_matrix.py +698 -0
  762. package/vendor/ars/scripts/test_check_submission_packet_manifest_integration.py +177 -0
  763. package/vendor/ars/scripts/test_check_surface_form_parity.py +417 -0
  764. package/vendor/ars/scripts/test_check_task_type.py +116 -0
  765. package/vendor/ars/scripts/test_check_tools_allowlist.py +835 -0
  766. package/vendor/ars/scripts/test_check_tortured_phrase_screening_integration.py +1306 -0
  767. package/vendor/ars/scripts/test_check_v3_10_134_write_scope.py +251 -0
  768. package/vendor/ars/scripts/test_check_v3_10_policy.py +547 -0
  769. package/vendor/ars/scripts/test_check_v3_6_7_pattern_protection.py +960 -0
  770. package/vendor/ars/scripts/test_check_v3_6_8_audit_scope_block.py +1000 -0
  771. package/vendor/ars/scripts/test_check_v3_6_8_cite_provenance_pipeline.py +454 -0
  772. package/vendor/ars/scripts/test_check_v3_6_8_frontmatter_trust_schema.py +581 -0
  773. package/vendor/ars/scripts/test_check_v3_6_8_mark_read_commands.py +120 -0
  774. package/vendor/ars/scripts/test_check_v3_6_8_pattern_protection.py +1138 -0
  775. package/vendor/ars/scripts/test_check_v3_7_3_three_layer_citation.py +566 -0
  776. package/vendor/ars/scripts/test_check_v3_8_annotation_literal_sync.py +262 -0
  777. package/vendor/ars/scripts/test_check_v3_9_0_triangulation.py +321 -0
  778. package/vendor/ars/scripts/test_check_v3_9_2_phase_boundary.py +190 -0
  779. package/vendor/ars/scripts/test_check_v3_9_4_temporal_verification.py +471 -0
  780. package/vendor/ars/scripts/test_check_version_consistency.py +1462 -0
  781. package/vendor/ars/scripts/test_check_workflow_classification.py +225 -0
  782. package/vendor/ars/scripts/test_chinese_literature_client.py +1889 -0
  783. package/vendor/ars/scripts/test_citation_existence_policy.py +480 -0
  784. package/vendor/ars/scripts/test_citation_verification_summary.py +342 -0
  785. package/vendor/ars/scripts/test_claim_audit_calibration.py +882 -0
  786. package/vendor/ars/scripts/test_claim_audit_finalizer.py +979 -0
  787. package/vendor/ars/scripts/test_claim_audit_pipeline.py +2398 -0
  788. package/vendor/ars/scripts/test_claim_audit_schema.py +1778 -0
  789. package/vendor/ars/scripts/test_claim_intent_manifest.py +666 -0
  790. package/vendor/ars/scripts/test_claim_registry_coverage.py +246 -0
  791. package/vendor/ars/scripts/test_claim_standing_discovery.py +579 -0
  792. package/vendor/ars/scripts/test_claim_standing_pipeline_wiring.py +290 -0
  793. package/vendor/ars/scripts/test_claim_standing_stance_assets.py +399 -0
  794. package/vendor/ars/scripts/test_claim_standing_stance_contracts.py +383 -0
  795. package/vendor/ars/scripts/test_claim_standing_stance_runner.py +349 -0
  796. package/vendor/ars/scripts/test_claim_standing_transmissions.py +605 -0
  797. package/vendor/ars/scripts/test_claim_strength_drift_disposition.py +517 -0
  798. package/vendor/ars/scripts/test_claim_verification_coverage_contract.py +104 -0
  799. package/vendor/ars/scripts/test_contamination_signals.py +1086 -0
  800. package/vendor/ars/scripts/test_content_coverage_advisory.py +1767 -0
  801. package/vendor/ars/scripts/test_cross_document_consistency_advisory.py +1270 -0
  802. package/vendor/ars/scripts/test_cross_model_codex_transport.py +1152 -0
  803. package/vendor/ars/scripts/test_cross_model_handoff.py +571 -0
  804. package/vendor/ars/scripts/test_cross_model_verification_guards.py +792 -0
  805. package/vendor/ars/scripts/test_crossref_client.py +393 -0
  806. package/vendor/ars/scripts/test_dispatch_e4_panel.py +4235 -0
  807. package/vendor/ars/scripts/test_e2e_claim_audit.py +540 -0
  808. package/vendor/ars/scripts/test_eval_harness_workflow.py +140 -0
  809. package/vendor/ars/scripts/test_evals_citation_extraction.py +150 -0
  810. package/vendor/ars/scripts/test_evals_lift_report_schema.py +108 -0
  811. package/vendor/ars/scripts/test_evidence_rows.py +2593 -0
  812. package/vendor/ars/scripts/test_experiment_provenance.py +915 -0
  813. package/vendor/ars/scripts/test_human_read_attestation_resolver.py +477 -0
  814. package/vendor/ars/scripts/test_ideation_diversity_assignment_gate.py +615 -0
  815. package/vendor/ars/scripts/test_indirect_prompt_injection_behavior_probe.py +250 -0
  816. package/vendor/ars/scripts/test_inquiry_branch_ledger.py +2296 -0
  817. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_10.py +248 -0
  818. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_7_3.py +545 -0
  819. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_9_0.py +497 -0
  820. package/vendor/ars/scripts/test_normalize_compat_verdict.py +149 -0
  821. package/vendor/ars/scripts/test_openalex_client.py +490 -0
  822. package/vendor/ars/scripts/test_passport_yaml.py +104 -0
  823. package/vendor/ars/scripts/test_pattern_eval_runtime.py +1295 -0
  824. package/vendor/ars/scripts/test_pdf_read_preflight.py +1943 -0
  825. package/vendor/ars/scripts/test_policy_anchor_disclosure.py +666 -0
  826. package/vendor/ars/scripts/test_reading_probe_lint.py +218 -0
  827. package/vendor/ars/scripts/test_recompute_receipts.py +778 -0
  828. package/vendor/ars/scripts/test_render_claim_standing_view.py +192 -0
  829. package/vendor/ars/scripts/test_render_eval_comment.py +162 -0
  830. package/vendor/ars/scripts/test_render_harness_retirement_issue.py +110 -0
  831. package/vendor/ars/scripts/test_repro_lock_validation_drift.py +100 -0
  832. package/vendor/ars/scripts/test_research_workflow_profile.py +734 -0
  833. package/vendor/ars/scripts/test_resolve_human_subjects_authority.py +1219 -0
  834. package/vendor/ars/scripts/test_resolve_review_target_context.py +703 -0
  835. package/vendor/ars/scripts/test_resume_e4_record.py +315 -0
  836. package/vendor/ars/scripts/test_retraction_status.py +456 -0
  837. package/vendor/ars/scripts/test_review_criteria_binding.py +629 -0
  838. package/vendor/ars/scripts/test_review_panel_provenance.py +565 -0
  839. package/vendor/ars/scripts/test_review_pathway_rule_trace.py +821 -0
  840. package/vendor/ars/scripts/test_revision_roadmap.py +1255 -0
  841. package/vendor/ars/scripts/test_run_ci_pytest_manifest.py +186 -0
  842. package/vendor/ars/scripts/test_run_codex_audit_e2e.py +369 -0
  843. package/vendor/ars/scripts/test_run_evals.py +430 -0
  844. package/vendor/ars/scripts/test_run_guard_launcher.py +500 -0
  845. package/vendor/ars/scripts/test_run_ideation_diversity_no_call.py +1833 -0
  846. package/vendor/ars/scripts/test_run_indirect_prompt_injection_no_call.py +1889 -0
  847. package/vendor/ars/scripts/test_run_review_criteria_constructive_value.py +586 -0
  848. package/vendor/ars/scripts/test_run_role_topology_utility_dry_run.py +428 -0
  849. package/vendor/ars/scripts/test_score_review_criteria_constructive_value.py +340 -0
  850. package/vendor/ars/scripts/test_semantic_scholar_client.py +554 -0
  851. package/vendor/ars/scripts/test_slr_lineage_emission.py +230 -0
  852. package/vendor/ars/scripts/test_socratic_rq_non_generation_contract.py +173 -0
  853. package/vendor/ars/scripts/test_temporal_integrity_audit.py +438 -0
  854. package/vendor/ars/scripts/test_text_similarity.py +95 -0
  855. package/vendor/ars/scripts/test_title_fuzzy_false_positive.py +111 -0
  856. package/vendor/ars/scripts/test_tortured_phrase_screening.py +2959 -0
  857. package/vendor/ars/scripts/test_transport_fixture_citation_gate.py +338 -0
  858. package/vendor/ars/scripts/test_uncited_assertion.py +558 -0
  859. package/vendor/ars/scripts/test_v3_6_7_phase_6_6.py +1279 -0
  860. package/vendor/ars/scripts/test_validate_compliance_fixtures.py +36 -0
  861. package/vendor/ars/scripts/test_validate_ideation_diversity_assets.py +230 -0
  862. package/vendor/ars/scripts/test_venue_disclosure_contract.py +755 -0
  863. package/vendor/ars/scripts/test_verification_cache.py +280 -0
  864. package/vendor/ars/scripts/test_verification_gate.py +461 -0
  865. package/vendor/ars/scripts/test_verify_passport_cli.py +123 -0
  866. package/vendor/ars/scripts/test_verify_submission_package.py +1407 -0
  867. package/vendor/ars/scripts/test_version_records_schema.py +211 -0
  868. package/vendor/ars/scripts/tortured_phrase_screening.py +3502 -0
  869. package/vendor/ars/scripts/uncited_assertion_detector.py +254 -0
  870. package/vendor/ars/scripts/v3_6_7_inversion_manifest.json +9 -0
  871. package/vendor/ars/scripts/v3_6_8_inversion_manifest.json +10 -0
  872. package/vendor/ars/scripts/validate_claim_standing_stance_assets.py +249 -0
  873. package/vendor/ars/scripts/validate_compliance_fixtures.py +56 -0
  874. package/vendor/ars/scripts/validate_ideation_diversity_assets.py +303 -0
  875. package/vendor/ars/scripts/venue_disclosure_contract_harness.py +837 -0
  876. package/vendor/ars/scripts/verification_cache.py +276 -0
  877. package/vendor/ars/scripts/verification_gate/__init__.py +345 -0
  878. package/vendor/ars/scripts/verify_passport.py +133 -0
  879. package/vendor/ars/scripts/verify_submission_package.py +1657 -0
  880. package/vendor/ars/shared/agents/compliance_agent.md +136 -0
  881. package/vendor/ars/shared/artifact_reproducibility_pattern.md +173 -0
  882. package/vendor/ars/shared/benchmark_report.schema.json +81 -0
  883. package/vendor/ars/shared/benchmark_report_pattern.md +180 -0
  884. package/vendor/ars/shared/bibliographic_integrity_signals.md +142 -0
  885. package/vendor/ars/shared/collaboration_depth_rubric.md +154 -0
  886. package/vendor/ars/shared/compliance_checkpoint_protocol.md +162 -0
  887. package/vendor/ars/shared/compliance_report.schema.json +187 -0
  888. package/vendor/ars/shared/contracts/README.md +938 -0
  889. package/vendor/ars/shared/contracts/activity/adjudication_activity_input.schema.json +555 -0
  890. package/vendor/ars/shared/contracts/activity/adjudication_activity_store.schema.json +560 -0
  891. package/vendor/ars/shared/contracts/audit/audit_jsonl.schema.json +128 -0
  892. package/vendor/ars/shared/contracts/audit/audit_sidecar.schema.json +169 -0
  893. package/vendor/ars/shared/contracts/audit/audit_verdict.schema.json +133 -0
  894. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory.schema.json +480 -0
  895. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory_draft.schema.json +564 -0
  896. package/vendor/ars/shared/contracts/audit/cross_document_source_manifest.schema.json +202 -0
  897. package/vendor/ars/shared/contracts/audit/tortured_phrase_advisory.schema.json +1362 -0
  898. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot.schema.json +208 -0
  899. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot_manifest.schema.json +335 -0
  900. package/vendor/ars/shared/contracts/capability/stage_capability_matrix.json +434 -0
  901. package/vendor/ars/shared/contracts/claim_standing/candidate_ledger.schema.json +705 -0
  902. package/vendor/ars/shared/contracts/claim_standing/query_plan.schema.json +389 -0
  903. package/vendor/ars/shared/contracts/claim_standing/query_plan_v1_1.schema.json +782 -0
  904. package/vendor/ars/shared/contracts/claim_standing/retrieval_input.schema.json +440 -0
  905. package/vendor/ars/shared/contracts/claim_standing/stance_record.schema.json +460 -0
  906. package/vendor/ars/shared/contracts/claim_standing/transmission_ledger.schema.json +282 -0
  907. package/vendor/ars/shared/contracts/cross_model/codex_citation_receipt.schema.json +157 -0
  908. package/vendor/ars/shared/contracts/cross_model/codex_citation_request.schema.json +23 -0
  909. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_commitment.schema.json +55 -0
  910. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_reveal.schema.json +50 -0
  911. package/vendor/ars/shared/contracts/degradation_registry.json +428 -0
  912. package/vendor/ars/shared/contracts/evaluator/full.json +126 -0
  913. package/vendor/ars/shared/contracts/evidence/claim_registry.schema.json +50 -0
  914. package/vendor/ars/shared/contracts/evidence/claim_registry_coverage_report.schema.json +79 -0
  915. package/vendor/ars/shared/contracts/evidence/evidence_row.schema.json +504 -0
  916. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_1.schema.json +364 -0
  917. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_2.schema.json +714 -0
  918. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_3.schema.json +524 -0
  919. package/vendor/ars/shared/contracts/human_subjects/authority_profile_registry.schema.json +497 -0
  920. package/vendor/ars/shared/contracts/human_subjects/committee_correspondence.schema.json +253 -0
  921. package/vendor/ars/shared/contracts/human_subjects/content_coverage_advisory.schema.json +620 -0
  922. package/vendor/ars/shared/contracts/human_subjects/irb_context_record.schema.json +329 -0
  923. package/vendor/ars/shared/contracts/human_subjects/resolved_authority_context.schema.json +347 -0
  924. package/vendor/ars/shared/contracts/human_subjects/review_pathway_rule_trace.schema.json +265 -0
  925. package/vendor/ars/shared/contracts/human_subjects/review_pathway_trace_request.schema.json +127 -0
  926. package/vendor/ars/shared/contracts/human_subjects/submission_packet_inventory.schema.json +240 -0
  927. package/vendor/ars/shared/contracts/human_subjects/submission_packet_manifest.schema.json +999 -0
  928. package/vendor/ars/shared/contracts/passport/audit_artifact_entry.schema.json +266 -0
  929. package/vendor/ars/shared/contracts/passport/bibliographic_integrity_signal.schema.json +1676 -0
  930. package/vendor/ars/shared/contracts/passport/citation_provenance.schema.json +107 -0
  931. package/vendor/ars/shared/contracts/passport/citation_verification_summary.schema.json +164 -0
  932. package/vendor/ars/shared/contracts/passport/claim_audit_result.schema.json +124 -0
  933. package/vendor/ars/shared/contracts/passport/claim_drift.schema.json +58 -0
  934. package/vendor/ars/shared/contracts/passport/claim_intent_manifest.schema.json +107 -0
  935. package/vendor/ars/shared/contracts/passport/constraint_violation.schema.json +65 -0
  936. package/vendor/ars/shared/contracts/passport/experiment_alignment_result.schema.json +69 -0
  937. package/vendor/ars/shared/contracts/passport/experiment_provenance_entry.schema.json +169 -0
  938. package/vendor/ars/shared/contracts/passport/human_read_log.schema.json +86 -0
  939. package/vendor/ars/shared/contracts/passport/inquiry_ledger_ref.schema.json +22 -0
  940. package/vendor/ars/shared/contracts/passport/literature_corpus_entry.schema.json +650 -0
  941. package/vendor/ars/shared/contracts/passport/preregistration_artifact.schema.json +132 -0
  942. package/vendor/ars/shared/contracts/passport/rejection_log.schema.json +89 -0
  943. package/vendor/ars/shared/contracts/passport/reset_ledger_entry.schema.json +158 -0
  944. package/vendor/ars/shared/contracts/passport/temporal_audit_results.schema.json +208 -0
  945. package/vendor/ars/shared/contracts/passport/terminal_policies.schema.json +50 -0
  946. package/vendor/ars/shared/contracts/passport/timeline.schema.json +102 -0
  947. package/vendor/ars/shared/contracts/passport/uncited_assertion.schema.json +56 -0
  948. package/vendor/ars/shared/contracts/passport/uncited_audit_failure.schema.json +72 -0
  949. package/vendor/ars/shared/contracts/passport/user_attested_read_resolution.schema.json +87 -0
  950. package/vendor/ars/shared/contracts/passport/version_records.schema.json +138 -0
  951. package/vendor/ars/shared/contracts/patch/block_manifest.schema.json +45 -0
  952. package/vendor/ars/shared/contracts/patch/legacy/v1_0/revision_patch.schema.json +110 -0
  953. package/vendor/ars/shared/contracts/patch/revision_patch.schema.json +250 -0
  954. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_diagnostic.schema.json +39 -0
  955. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_worker.schema.json +88 -0
  956. package/vendor/ars/shared/contracts/pdf/pdf_read_preflight.schema.json +227 -0
  957. package/vendor/ars/shared/contracts/re_review/input_manifest.schema.json +161 -0
  958. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/input_manifest.schema.json +134 -0
  959. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/precommitment.schema.json +193 -0
  960. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/traceability.schema.json +841 -0
  961. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/verdict_record.schema.json +244 -0
  962. package/vendor/ars/shared/contracts/re_review/precommitment.schema.json +193 -0
  963. package/vendor/ars/shared/contracts/re_review/traceability.schema.json +916 -0
  964. package/vendor/ars/shared/contracts/re_review/verdict_record.schema.json +245 -0
  965. package/vendor/ars/shared/contracts/research_workflow/inquiry_branch_ledger.schema.json +449 -0
  966. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile.schema.json +222 -0
  967. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile_selection_receipt.schema.json +111 -0
  968. package/vendor/ars/shared/contracts/review_target/constructive_review_findings.schema.json +172 -0
  969. package/vendor/ars/shared/contracts/review_target/criteria_registry.schema.json +97 -0
  970. package/vendor/ars/shared/contracts/review_target/review_criteria_binding_manifest.schema.json +235 -0
  971. package/vendor/ars/shared/contracts/review_target/review_criteria_source_receipt.schema.json +158 -0
  972. package/vendor/ars/shared/contracts/review_target/review_target_context.schema.json +106 -0
  973. package/vendor/ars/shared/contracts/review_target/review_target_declaration.schema.json +118 -0
  974. package/vendor/ars/shared/contracts/reviewer/full.json +114 -0
  975. package/vendor/ars/shared/contracts/reviewer/methodology_focus.json +75 -0
  976. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance.schema.json +263 -0
  977. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_carrier.schema.json +122 -0
  978. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_input.schema.json +120 -0
  979. package/vendor/ars/shared/contracts/revision/author_adjudication.schema.json +251 -0
  980. package/vendor/ars/shared/contracts/revision/author_adjudication_input.schema.json +25 -0
  981. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition.schema.json +97 -0
  982. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition_input.schema.json +80 -0
  983. package/vendor/ars/shared/contracts/revision/claim_strength_drift_findings.schema.json +139 -0
  984. package/vendor/ars/shared/contracts/revision/claim_surface_manifest.schema.json +99 -0
  985. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization.schema.json +140 -0
  986. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization_input.schema.json +28 -0
  987. package/vendor/ars/shared/contracts/revision/integrity_correction_list.schema.json +48 -0
  988. package/vendor/ars/shared/contracts/revision/integrity_pass_receipt.schema.json +16 -0
  989. package/vendor/ars/shared/contracts/revision/revision_evidence_bundle.schema.json +134 -0
  990. package/vendor/ars/shared/contracts/revision/revision_roadmap.schema.json +334 -0
  991. package/vendor/ars/shared/contracts/submission/format_profile.example.yaml +33 -0
  992. package/vendor/ars/shared/contracts/submission/format_profile.schema.json +102 -0
  993. package/vendor/ars/shared/contracts/submission/submission_verification_report.schema.json +233 -0
  994. package/vendor/ars/shared/contracts/submission/venue_profile.schema.json +114 -0
  995. package/vendor/ars/shared/contracts/writer/full.json +87 -0
  996. package/vendor/ars/shared/cross_model_verification.md +714 -0
  997. package/vendor/ars/shared/evals_lift_report.schema.json +141 -0
  998. package/vendor/ars/shared/ground_truth_isolation_pattern.md +275 -0
  999. package/vendor/ars/shared/handoff_schemas.md +1209 -0
  1000. package/vendor/ars/shared/human_subjects_authority_registry.json +1278 -0
  1001. package/vendor/ars/shared/mode_spectrum.md +57 -0
  1002. package/vendor/ars/shared/model_tiering.md +83 -0
  1003. package/vendor/ars/shared/policy_data/nature_policy.md +56 -0
  1004. package/vendor/ars/shared/prisma_trAIce_protocol.md +157 -0
  1005. package/vendor/ars/shared/raise_framework.md +129 -0
  1006. package/vendor/ars/shared/references/authority_content_coverage_advisory_protocol.md +275 -0
  1007. package/vendor/ars/shared/references/claim_standing_candidate_ledger_protocol.md +66 -0
  1008. package/vendor/ars/shared/references/claim_strength_ladder.md +93 -0
  1009. package/vendor/ars/shared/references/cross_document_consistency_advisory_protocol.md +263 -0
  1010. package/vendor/ars/shared/references/evidence_row_protocol.md +260 -0
  1011. package/vendor/ars/shared/references/firm_rules.md +90 -0
  1012. package/vendor/ars/shared/references/human_subjects_authority_protocol.md +274 -0
  1013. package/vendor/ars/shared/references/intent_clarification_protocol.md +168 -0
  1014. package/vendor/ars/shared/references/irb_terminology_glossary.md +229 -0
  1015. package/vendor/ars/shared/references/protected_hedging_phrases.md +118 -0
  1016. package/vendor/ars/shared/references/psychometric_terminology_glossary.md +109 -0
  1017. package/vendor/ars/shared/references/review_criteria_consumer_protocol.md +238 -0
  1018. package/vendor/ars/shared/references/review_pathway_rule_trace_protocol.md +166 -0
  1019. package/vendor/ars/shared/references/submission_packet_manifest_protocol.md +292 -0
  1020. package/vendor/ars/shared/references/word_count_conventions.md +124 -0
  1021. package/vendor/ars/shared/research_workflow_profiles/field_general.json +1 -0
  1022. package/vendor/ars/shared/review_criteria_registry.json +207 -0
  1023. package/vendor/ars/shared/review_criteria_sources/msr-2027-technical-papers.2026-08-24.json +46 -0
  1024. package/vendor/ars/shared/review_criteria_sources/sigsoft-empirical-standards.2026-08-24.json +31 -0
  1025. package/vendor/ars/shared/sprint_contract.schema.json +482 -0
  1026. package/vendor/ars/shared/style_calibration_protocol.md +151 -0
  1027. package/vendor/ars/shared/templates/codex_audit_multifile_template.md +263 -0
  1028. package/vendor/ars/tools/release-discipline/.toolkit-version +1 -0
  1029. package/vendor/ars/tools/release-discipline/README.md +4 -0
  1030. package/vendor/ars/tools/release-discipline/scripts/_release_doc_alignment_schema.py +1011 -0
  1031. package/vendor/ars/tools/release-discipline/scripts/check_command_invariants.py +497 -0
  1032. package/vendor/ars/tools/release-discipline/scripts/check_release_doc_alignment.py +263 -0
  1033. package/vendor/ars/tools/release-discipline/scripts/sync-toolkit.sh +147 -0
  1034. package/vendor/windows/NOTICE.md +12 -0
  1035. package/vendor/windows/arm64/fd.exe +0 -0
  1036. package/vendor/windows/arm64/licenses/fd/LICENSE-APACHE +201 -0
  1037. package/vendor/windows/arm64/licenses/fd/LICENSE-MIT +21 -0
  1038. package/vendor/windows/arm64/licenses/ripgrep/COPYING +3 -0
  1039. package/vendor/windows/arm64/licenses/ripgrep/LICENSE-MIT +21 -0
  1040. package/vendor/windows/arm64/licenses/ripgrep/UNLICENSE +24 -0
  1041. package/vendor/windows/arm64/rg.exe +0 -0
  1042. package/vendor/windows/x64/fd.exe +0 -0
  1043. package/vendor/windows/x64/licenses/fd/LICENSE-APACHE +201 -0
  1044. package/vendor/windows/x64/licenses/fd/LICENSE-MIT +21 -0
  1045. package/vendor/windows/x64/licenses/ripgrep/COPYING +3 -0
  1046. package/vendor/windows/x64/licenses/ripgrep/LICENSE-MIT +21 -0
  1047. package/vendor/windows/x64/licenses/ripgrep/UNLICENSE +24 -0
  1048. package/vendor/windows/x64/rg.exe +0 -0
@@ -0,0 +1,1658 @@
1
+ """Schema 13.2 panel checker tests, including exhaustive decision profiles."""
2
+ from __future__ import annotations
3
+
4
+ import itertools
5
+ import json
6
+ from pathlib import Path
7
+
8
+ import pytest
9
+
10
+ from scripts import check_panel_synthesis as cps
11
+
12
+ REPO = Path(__file__).resolve().parents[1]
13
+ FULL_PATH = REPO / "shared/contracts/reviewer/full.json"
14
+ MF_PATH = REPO / "shared/contracts/reviewer/methodology_focus.json"
15
+ FULL = json.loads(FULL_PATH.read_text(encoding="utf-8"))
16
+ ROLES = ("eic", "methodology", "domain", "perspective", "da")
17
+
18
+
19
+ @pytest.mark.parametrize(
20
+ "anchor",
21
+ (
22
+ "absence: x",
23
+ "absence: Methods — expected ethics;checked appendix",
24
+ "absence: Methods — expected ethics; checked appendix",
25
+ "absence: Methods — expected ; checked appendix — expected ethics; checked supplement",
26
+ "absence: Methods; checked appendix — expected ethics",
27
+ "equation: Eq. ]3[",
28
+ "absence: Methods — expected ethics; checked appendix]",
29
+ "[absence: Methods — expected ethics; checked appendix",
30
+ "text: §References, six DOI strings in list order",
31
+ '[ text: §5 "short exact quote" ]',
32
+ '` text: §5 "short exact quote" `',
33
+ '`text: §5 "short exact quote"',
34
+ 'text: §5 "short exact quote"`',
35
+ 'text: §5 "short exact quote"]',
36
+ 'text: §5 "short exact quote"`]',
37
+ '[text: §5 "short exact quote"] trailing]',
38
+ '[[text: §5 "short exact quote"]]',
39
+ '``text: §5 "short exact quote"``',
40
+ 'text: §5 "short exact quote”',
41
+ 'text: §5 “short exact quote"',
42
+ 'text: §5 "outer “inner”',
43
+ 'text: §5 “outer "inner”"',
44
+ "text: §5 “outer “” tail”",
45
+ ),
46
+ )
47
+ def test_shared_anchor_validator_rejects_incomplete_or_unpaired_shapes(anchor):
48
+ with pytest.raises(cps.ReportError, match="ANCHOR-INVALID"):
49
+ cps.validate_evidence_anchor(anchor, "probe")
50
+
51
+
52
+ @pytest.mark.parametrize(
53
+ "anchor",
54
+ (
55
+ "absence: Methods — expected an ethics statement; checked Methods, appendix",
56
+ '`text: §5 "short exact quote"`',
57
+ "text: §5 “short exact quote”",
58
+ "equation: Eq. [3]",
59
+ "table: Table 2 [Panel B]",
60
+ "[equation: Eq. [3]]",
61
+ 'text: §4 "short quote" [emphasis added]',
62
+ 'text: §3 "short quote" per `df`',
63
+ '`text: §3 "short quote" per `df``',
64
+ "text: §2 “the term “quality culture” is undefined”",
65
+ 'text: §2 "he said “quality culture” often"',
66
+ ),
67
+ )
68
+ def test_shared_anchor_validator_accepts_complete_paired_shapes(anchor):
69
+ cps.validate_evidence_anchor(anchor, "inverse")
70
+
71
+
72
+ def test_shared_anchor_validator_checks_nested_quote_word_limit_per_pair():
73
+ words_25 = " ".join(["word"] * 25)
74
+ words_26 = " ".join(["word"] * 26)
75
+ cps.validate_evidence_anchor(
76
+ f"text: §2 ““{words_25}””",
77
+ "nested-25-word-boundary",
78
+ )
79
+ with pytest.raises(cps.ReportError, match="at most 25 words"):
80
+ cps.validate_evidence_anchor(
81
+ f"text: §2 ““{words_26}””",
82
+ "nested-26-word-boundary",
83
+ )
84
+ outer_words = " ".join(["outer"] * 24)
85
+ with pytest.raises(cps.ReportError, match="at most 25 words"):
86
+ cps.validate_evidence_anchor(
87
+ f"text: §2 “{outer_words} “inner” tail”",
88
+ "nested-differential-outer-26-inner-1",
89
+ )
90
+
91
+
92
+ def state(value: str) -> cps.DimensionScore:
93
+ if value == "fatal":
94
+ return cps.DimensionScore("block", "fatal", "fatal trigger")
95
+ if value == "block":
96
+ return cps.DimensionScore("block", "repairable", "block trigger")
97
+ if value == "warn":
98
+ return cps.DimensionScore("warn", trigger="warn trigger")
99
+ if value == "abstain":
100
+ return cps.DimensionScore("not_assessed", abstain_reason="not applicable")
101
+ return cps.DimensionScore(value)
102
+
103
+
104
+ def report_text(role: str, overrides=None, da_ids=()) -> str:
105
+ overrides = overrides or {}
106
+ lines = [f"contract_role: {role}", "", "## Dimension Scores", ""]
107
+ for dim in FULL["acceptance_dimensions"]:
108
+ did = dim["id"]
109
+ lines.append(f"### {did}: {dim['name']}")
110
+ if role not in dim["eligible_roles"]:
111
+ lines.append("score: not_assessed")
112
+ else:
113
+ value = overrides.get(did, "pass")
114
+ if value == "warn":
115
+ lines += ["score: warn", 'trigger: "warn trigger"']
116
+ elif value == "block":
117
+ lines += [
118
+ "score: block", "block_class: repairable",
119
+ 'trigger: "block trigger"',
120
+ ]
121
+ elif value == "fatal":
122
+ lines += [
123
+ "score: block", "block_class: fatal",
124
+ 'trigger: "fatal trigger"',
125
+ ]
126
+ elif value == "abstain":
127
+ lines += [
128
+ "score: not_assessed",
129
+ "abstain_reason: materially inapplicable",
130
+ ]
131
+ else:
132
+ lines.append("score: pass")
133
+ lines.append("")
134
+ lines += ["## Review Body", "", "No scored findings.", ""]
135
+ if role == "methodology":
136
+ # #610: a methodology card without its Arithmetic Receipts section
137
+ # stopped being phase-conformant; the synthesis parser itself
138
+ # tolerates the extra H2 either way.
139
+ lines += [
140
+ "## Arithmetic Receipts",
141
+ "",
142
+ "no_recomputable_statistics: the fixture manuscript reports no "
143
+ "statistic covered by a bounded procedure",
144
+ "",
145
+ ]
146
+ if role == "da":
147
+ lines += [
148
+ "#### CRITICAL",
149
+ "| # | Issue | Evidence Anchor |",
150
+ "|---|-------|-----------------|",
151
+ ]
152
+ for finding_id in da_ids:
153
+ lines.append(
154
+ f'| {finding_id} | Issue | text: "quoted evidence" p. 1 |'
155
+ )
156
+ lines += [
157
+ "",
158
+ "#### MAJOR",
159
+ "| # | Issue | Evidence Anchor |",
160
+ "|---|-------|-----------------|",
161
+ ]
162
+ return "\n".join(lines)
163
+
164
+
165
+ def reports(overrides=None, da_ids=()):
166
+ overrides = overrides or {}
167
+ return [
168
+ cps.parse_report(
169
+ f"{role}.md",
170
+ report_text(role, overrides.get(role), da_ids if role == "da" else ()),
171
+ FULL,
172
+ )
173
+ for role in ROLES
174
+ ]
175
+
176
+
177
+ def synthesis_for(
178
+ panel_reports, adjudications=None, decision_override=None,
179
+ marker_count=None, rationales=None,
180
+ ):
181
+ contract, expressions = cps.load_contract(FULL_PATH)
182
+ assessed, fired, decision = cps.recompute_panel(
183
+ panel_reports, contract, expressions, []
184
+ )
185
+ verdicts = cps.compute_dimension_verdicts(assessed)
186
+ adjudications = adjudications or {}
187
+ rationales = rationales or {}
188
+ lines = [
189
+ "dimension_verdicts: [" + ", ".join(
190
+ f"{did}={value}" for did, value in verdicts.items()
191
+ ) + "]",
192
+ "fired_conditions: [" + ", ".join(fired) + "]",
193
+ "da_critical_adjudications: [" + ", ".join(
194
+ f"{finding_id}={value}"
195
+ for finding_id, value in adjudications.items()
196
+ ) + "]",
197
+ ]
198
+ lines += [
199
+ f"{finding_id} rejection rationale: {text}"
200
+ for finding_id, text in rationales.items()
201
+ ]
202
+ lines.append(decision_override or decision)
203
+ if marker_count is not None:
204
+ lines.append(
205
+ f"[DA-CRITICAL-VS-ACCEPT: {marker_count} validated/unresolved]"
206
+ )
207
+ return "\n".join(lines), expressions
208
+
209
+
210
+ def test_majority_n1_is_owner_decides():
211
+ assert cps.quantifier_fires("majority", [True], []) is True
212
+ assert cps.quantifier_fires("majority", [False], []) is False
213
+
214
+
215
+ def test_majority_n2_requires_both_eligible_seats():
216
+ assert cps.quantifier_fires("majority", [True, False], []) is False
217
+ assert cps.quantifier_fires("majority", [True, True], []) is True
218
+
219
+
220
+ @pytest.mark.parametrize(
221
+ "actions",
222
+ (
223
+ ("editorial_decision=minor_revision", "editorial_decision=reject"),
224
+ ("editorial_decision=reject", "editorial_decision=minor_revision"),
225
+ ),
226
+ )
227
+ def test_equal_severity_tie_uses_earliest_condition(actions):
228
+ conditions = [
229
+ {"condition_id": "F1", "severity": 50, "action": actions[0]},
230
+ {"condition_id": "F2", "severity": 50, "action": actions[1]},
231
+ ]
232
+ assert cps.resolve_decision(conditions, {"F1", "F2"}) == actions[0]
233
+
234
+
235
+ @pytest.mark.parametrize(
236
+ "expression",
237
+ [
238
+ "any mandatory dimension scores 'block'",
239
+ "two or more mandatory dimensions score 'warn' or worse",
240
+ "every mandatory dimension scores 'pass'",
241
+ "D1 scores 'block'",
242
+ "D1 scores 'warn' AND every high dimension scores 'pass'",
243
+ "any mandatory dimension has a fatal block",
244
+ "D1 has a fatal block",
245
+ "any dimension scores 'warn' or worse",
246
+ "D2 scores 'warn' or worse",
247
+ "every dimension scores 'pass'",
248
+ ],
249
+ )
250
+ def test_expression_patterns_parse(expression):
251
+ dimensions = {d["id"]: d for d in FULL["acceptance_dimensions"]}
252
+ assert cps.parse_expression(expression, dimensions, "Fx")
253
+
254
+
255
+ @pytest.mark.parametrize(
256
+ "expression",
257
+ ["some dimension fails", "D99 scores 'pass'",
258
+ "any high dimension has a fatal block", "D4 has a fatal block"],
259
+ )
260
+ def test_expression_fail_closed(expression):
261
+ dimensions = {d["id"]: d for d in FULL["acceptance_dimensions"]}
262
+ with pytest.raises(cps.ContractError):
263
+ cps.parse_expression(expression, dimensions, "Fx")
264
+
265
+
266
+ def test_parse_report_role_scope_and_structural_abstention():
267
+ report = cps.parse_report("eic.md", report_text("eic"), FULL)
268
+ assert report.scores["D1"].score == "not_assessed"
269
+ assert report.scores["D5"].score == "pass"
270
+
271
+
272
+ def test_out_of_role_real_score_rejected():
273
+ text = report_text("eic").replace(
274
+ "### D1: methodology_rigor\nscore: not_assessed",
275
+ "### D1: methodology_rigor\nscore: pass",
276
+ )
277
+ with pytest.raises(cps.ReportError, match="OUT-OF-ROLE"):
278
+ cps.parse_report("eic.md", text, FULL)
279
+
280
+
281
+ def test_eligible_abstention_requires_reason():
282
+ text = report_text("eic", {"D5": "abstain"}).replace(
283
+ "\nabstain_reason: materially inapplicable", "", 1
284
+ )
285
+ with pytest.raises(cps.ReportError, match="abstain_reason"):
286
+ cps.parse_report("eic.md", text, FULL)
287
+
288
+
289
+ def test_v1_sections_fail_loudly():
290
+ text = report_text("eic") + "\n## Failure Condition Checks\n"
291
+ with pytest.raises(cps.ReportError, match="V1-GRAMMAR-RETIRED"):
292
+ cps.parse_report("eic.md", text, FULL)
293
+
294
+
295
+ @pytest.mark.parametrize(
296
+ "action",
297
+ (
298
+ "reject", "Reject", "reject-or-major-revision", "unknown_v1_value",
299
+ "mixed_key_case",
300
+ ),
301
+ )
302
+ def test_v1_bare_decision_line_fails_loudly(action):
303
+ key = "Editorial_Decision" if action == "mixed_key_case" else "editorial_decision"
304
+ text = report_text("eic") + f"\n{key}={action}\n"
305
+ with pytest.raises(cps.ReportError, match="V1-GRAMMAR-RETIRED"):
306
+ cps.parse_report("eic.md", text, FULL)
307
+
308
+
309
+ @pytest.mark.parametrize("indent", (" ", "\t"))
310
+ def test_indented_v1_bare_decision_line_fails_loudly(indent):
311
+ text = report_text("eic") + f"\n{indent}editorial_decision=accept\n"
312
+ with pytest.raises(cps.ReportError, match="V1-GRAMMAR-RETIRED"):
313
+ cps.parse_report("eic.md", text, FULL)
314
+
315
+
316
+ def test_fenced_v1_bare_decision_decoy_is_ignored():
317
+ text = (
318
+ report_text("eic")
319
+ + "\n```text\neditorial_decision=Reject\n```\n"
320
+ )
321
+ cps.parse_report("eic.md", text, FULL)
322
+
323
+
324
+ @pytest.mark.parametrize("fence", ("```", "~~~"))
325
+ def test_malformed_fence_closer_does_not_expose_bare_decision(fence):
326
+ text = (
327
+ report_text("eic")
328
+ + f"\n{fence}text\n{fence}not-a-close\n"
329
+ "editorial_decision=accept\n"
330
+ f"{fence}\n"
331
+ )
332
+ cps.parse_report("eic.md", text, FULL)
333
+
334
+
335
+ def test_malformed_fence_closer_keeps_reviewer_report_hidden():
336
+ text = "```text\n```not-a-close\n" + report_text("eic") + "\n```\n"
337
+ with pytest.raises(cps.ReportError, match="Dimension Scores"):
338
+ cps.parse_report("eic.md", text, FULL)
339
+
340
+
341
+ def test_malformed_fence_closer_synthesis_parses_as_fenced_content():
342
+ """The fence never closes (`~~~not-a-close` is content, not a closer),
343
+ so the whole synthesis stays fenced — and fenced audit lines are
344
+ candidates since #637. Fence-STATE correctness stays pinned by the
345
+ parse_report twins above, whose grammars remain fence-blind."""
346
+ synthesis, _ = synthesis_for(reports())
347
+ text = "~~~text\n~~~not-a-close\n" + synthesis + "\n~~~\n"
348
+ parsed = cps.parse_synthesis("s.md", text, FULL)
349
+ assert parsed.decision == "editorial_decision=accept"
350
+
351
+
352
+ @pytest.mark.parametrize("separator", ("\x85", "\u2028", "\u2029"))
353
+ def test_unicode_separator_cannot_close_commonmark_fence(separator):
354
+ text = (
355
+ "```text\n```"
356
+ + separator
357
+ + report_text("methodology", {"D1": "fatal"})
358
+ + "\n```\n"
359
+ )
360
+ with pytest.raises(cps.ReportError, match="Dimension Scores"):
361
+ cps.parse_report("hidden-methodology.md", text, FULL)
362
+
363
+
364
+ @pytest.mark.parametrize("separator", ("\x85", "\u2028", "\u2029"))
365
+ def test_unicode_separator_synthesis_parses_as_fenced_content(separator):
366
+ """A Unicode separator is not a CommonMark line end: it can neither
367
+ close the fence nor split the line, so the glued `~~~<sep>note` stays
368
+ one content line. The rest of the synthesis is ordinary fenced content \u2014
369
+ a candidate since #637 \u2014 and parses."""
370
+ synthesis, _ = synthesis_for(reports())
371
+ text = "~~~text\n~~~" + separator + "note\n" + synthesis + "\n~~~\n"
372
+ parsed = cps.parse_synthesis("fenced-synthesis.md", text, FULL)
373
+ assert parsed.decision == "editorial_decision=accept"
374
+
375
+
376
+ def test_fenced_audit_block_parses_as_observed_in_637_cohort():
377
+ """Every synthesis first attempt of the 2026-08-03 baseline cohort (6/6)
378
+ emitted the four audit lines inside a plain code fence."""
379
+ synthesis, _ = synthesis_for(reports())
380
+ parsed = cps.parse_synthesis(
381
+ "s.md", "```\n" + synthesis + "\n```\n", FULL
382
+ )
383
+ assert parsed.fired == ["F0"]
384
+ assert parsed.decision == "editorial_decision=accept"
385
+
386
+
387
+ def test_inline_code_wrapped_audit_lines_parse():
388
+ """ms01_quant baseline r2's a2 retry wrapped each audit line whole in an
389
+ inline code span, defeating the line-anchored grammar (#637)."""
390
+ synthesis, _ = synthesis_for(reports())
391
+ text = "\n".join(f"`{line}`" for line in synthesis.split("\n"))
392
+ parsed = cps.parse_synthesis("s.md", text, FULL)
393
+ assert parsed.decision == "editorial_decision=accept"
394
+
395
+
396
+ def test_identical_duplicate_audit_lines_collapse():
397
+ """A byte-identical re-statement (plain line plus its fenced copy) is
398
+ one candidate, not a duplicate abort."""
399
+ synthesis, _ = synthesis_for(reports())
400
+ fired_line = next(line for line in synthesis.split("\n")
401
+ if line.startswith("fired_conditions:"))
402
+ text = synthesis + "\n```\n" + fired_line + "\n```\n"
403
+ parsed = cps.parse_synthesis("s.md", text, FULL)
404
+ assert parsed.fired == ["F0"]
405
+
406
+
407
+ def test_conflicting_fenced_audit_line_still_aborts():
408
+ """A fenced decoy that disagrees with the operative line stays a loud
409
+ abort \u2014 tolerance collapses identical values only."""
410
+ synthesis, _ = synthesis_for(reports())
411
+ text = synthesis + "\n```\nfired_conditions: [F1]\n```\n"
412
+ with pytest.raises(cps.SynthesisError, match="found 2"):
413
+ cps.parse_synthesis("s.md", text, FULL)
414
+
415
+
416
+ def test_prose_quoted_checker_diagnostic_is_not_a_candidate():
417
+ """The a2 remediation notes of the #637 cohort quote the checker error
418
+ inside longer prose lines; anchored grammars must not see those."""
419
+ synthesis, _ = synthesis_for(reports())
420
+ note = (
421
+ "**Checker remediation:** the prior emission failed "
422
+ "`[SYNTHESIS-PARSE: expected exactly one fired_conditions line, "
423
+ "found 0]` and the canonical block is re-emitted plainly above."
424
+ )
425
+ parsed = cps.parse_synthesis(
426
+ "s.md", synthesis + "\n" + note + "\n", FULL
427
+ )
428
+ assert parsed.fired == ["F0"]
429
+
430
+
431
+ def test_blockquoted_audit_line_documents_an_accepted_miss():
432
+ """Documents an ACCEPTED miss: a blockquoted audit line renders as
433
+ quotation and is deliberately not a candidate. Change deliberately."""
434
+ synthesis, _ = synthesis_for(reports())
435
+ text = synthesis.replace("fired_conditions:", "> fired_conditions:", 1)
436
+ with pytest.raises(cps.SynthesisError, match="fired_conditions"):
437
+ cps.parse_synthesis("s.md", text, FULL)
438
+
439
+
440
+ def test_inline_span_inside_fence_documents_an_accepted_miss():
441
+ """Documents an ACCEPTED miss: backticks inside a fence are literal
442
+ rendered content, so a wrapped line there is not unwrapped. Change
443
+ deliberately."""
444
+ synthesis, _ = synthesis_for(reports())
445
+ fenced = "\n".join(f"`{line}`" for line in synthesis.split("\n"))
446
+ with pytest.raises(cps.SynthesisError, match="fired_conditions"):
447
+ cps.parse_synthesis("s.md", "```\n" + fenced + "\n```\n", FULL)
448
+
449
+
450
+ def test_fenced_rationale_and_marker_document_an_accepted_miss():
451
+ """Documents an ACCEPTED miss: rationales and the DA marker keep the
452
+ plain-line source \u2014 their fenced occurrences read as quotation. Change
453
+ deliberately."""
454
+ synthesis, _ = synthesis_for(reports())
455
+ text = (
456
+ synthesis
457
+ + "\n```\nC9 rejection rationale: quoted example\n"
458
+ "[DA-CRITICAL-VS-ACCEPT: 2 validated/unresolved]\n```\n"
459
+ )
460
+ parsed = cps.parse_synthesis("s.md", text, FULL)
461
+ assert "C9" not in parsed.rejection_rationales
462
+ assert parsed.marker_count is None
463
+ # The forbidden-marker asymmetry is part of the same accepted boundary:
464
+ # with no active DA-critical adjudications a stated marker is forbidden,
465
+ # and this fenced one stays invisible rather than aborting — the
466
+ # decision channel is pinned independently by the layer-2 recompute.
467
+ assert not any(
468
+ "marker forbidden" in diag
469
+ for diag in cps.check_da_terminal_gate(reports(), parsed)
470
+ )
471
+
472
+
473
+ def test_padded_inline_code_wrapped_audit_lines_parse():
474
+ """CommonMark renders `` ` body ` `` with one padding space stripped
475
+ from each side, so a padded span displays the audit line verbatim and
476
+ must be a candidate in its DISPLAYED form."""
477
+ synthesis, _ = synthesis_for(reports())
478
+ text = "\n".join(f"` {line} `" for line in synthesis.split("\n"))
479
+ parsed = cps.parse_synthesis("s.md", text, FULL)
480
+ assert parsed.decision == "editorial_decision=accept"
481
+
482
+
483
+ def test_padded_span_conflicting_value_still_aborts():
484
+ """Rendering normalization must not weaken the distinct-value guard: a
485
+ padded-span decoy that disagrees with the operative line still aborts."""
486
+ synthesis, _ = synthesis_for(reports())
487
+ text = synthesis + "\n` fired_conditions: [F1] `\n"
488
+ with pytest.raises(cps.SynthesisError, match="found 2"):
489
+ cps.parse_synthesis("s.md", text, FULL)
490
+
491
+
492
+ def test_all_space_span_body_is_not_stripped():
493
+ """CommonMark strips padding only when the body is not all spaces; an
494
+ all-space span stays as-is and is simply a non-candidate."""
495
+ synthesis, _ = synthesis_for(reports())
496
+ parsed = cps.parse_synthesis(
497
+ "s.md", synthesis + "\n` `\n", FULL
498
+ )
499
+ assert parsed.decision == "editorial_decision=accept"
500
+
501
+
502
+ def test_indented_fence_content_parses_dedented():
503
+ """A fence opened with up to 3 leading spaces renders its content
504
+ dedented by the opener's indent, so indented fenced audit lines are
505
+ candidates in their displayed (dedented) form."""
506
+ synthesis, _ = synthesis_for(reports())
507
+ indented = "\n".join(" " + line for line in synthesis.split("\n"))
508
+ text = " ```\n" + indented + "\n ```\n"
509
+ parsed = cps.parse_synthesis("s.md", text, FULL)
510
+ assert parsed.decision == "editorial_decision=accept"
511
+
512
+
513
+ def test_crlf_fenced_audit_block_parses():
514
+ """CRLF line endings are CommonMark line ends; the fenced audit block
515
+ parses identically under them."""
516
+ synthesis, _ = synthesis_for(reports())
517
+ text = ("```\n" + synthesis + "\n```\n").replace("\n", "\r\n")
518
+ parsed = cps.parse_synthesis("s.md", text, FULL)
519
+ assert parsed.decision == "editorial_decision=accept"
520
+
521
+
522
+ def test_malformed_closer_fence_state_pins_wrapped_decoy_hidden():
523
+ """Pins fence STATE through the candidate walker: `~~~not-a-close` does
524
+ not close the fence, so a wrapped decoy after it is fenced — backticks
525
+ render literally, the decoy is never unwrapped, and the plain synthesis
526
+ before the fence parses. A mutation that accepts the malformed closer
527
+ unwraps the decoy and flips this to a found-2 abort."""
528
+ synthesis, _ = synthesis_for(reports())
529
+ text = (
530
+ synthesis
531
+ + "\n~~~text\n~~~not-a-close\n`fired_conditions: [F1]`\n~~~\n"
532
+ )
533
+ parsed = cps.parse_synthesis("s.md", text, FULL)
534
+ assert parsed.fired == ["F0"]
535
+
536
+
537
+ def test_short_closer_fence_state_pins_wrapped_decoy_hidden():
538
+ """A prospective closer shorter than the opener does not close the
539
+ fence (CommonMark length rule), so the wrapped decoy after it stays
540
+ fenced and hidden."""
541
+ synthesis, _ = synthesis_for(reports())
542
+ text = (
543
+ synthesis
544
+ + "\n````\n```\n`fired_conditions: [F1]`\n````\n"
545
+ )
546
+ parsed = cps.parse_synthesis("s.md", text, FULL)
547
+ assert parsed.fired == ["F0"]
548
+
549
+
550
+ def test_mismatched_closer_fence_state_pins_wrapped_decoy_hidden():
551
+ """A backtick closer cannot close a tilde fence; the wrapped decoy
552
+ after it stays fenced and hidden."""
553
+ synthesis, _ = synthesis_for(reports())
554
+ text = (
555
+ synthesis
556
+ + "\n~~~\n```\n`fired_conditions: [F1]`\n~~~\n"
557
+ )
558
+ parsed = cps.parse_synthesis("s.md", text, FULL)
559
+ assert parsed.fired == ["F0"]
560
+
561
+
562
+ @pytest.mark.parametrize("separator", ("\x85", "\u2028", "\u2029"))
563
+ def test_unicode_separator_fence_state_pins_wrapped_decoy_hidden(separator):
564
+ """A Unicode separator is not a CommonMark line end: `~~~<sep>note`
565
+ stays one content line and cannot close the fence, so the wrapped
566
+ decoy after it stays fenced and hidden. A mutation that splits on the
567
+ separator closes the fence and flips this to a found-2 abort."""
568
+ synthesis, _ = synthesis_for(reports())
569
+ text = (
570
+ synthesis
571
+ + "\n~~~text\n~~~" + separator + "note\n"
572
+ "`fired_conditions: [F1]`\n~~~\n"
573
+ )
574
+ parsed = cps.parse_synthesis("s.md", text, FULL)
575
+ assert parsed.fired == ["F0"]
576
+
577
+
578
+ def test_unterminated_fence_content_stays_candidate():
579
+ """An unterminated fence retains (not grows) its content, and fenced
580
+ audit lines remain candidates to end-of-input."""
581
+ synthesis, _ = synthesis_for(reports())
582
+ parsed = cps.parse_synthesis("s.md", "```\n" + synthesis, FULL)
583
+ assert parsed.decision == "editorial_decision=accept"
584
+
585
+
586
+ @pytest.mark.parametrize("score", ("warn", "block"))
587
+ def test_eligible_nonpass_score_requires_trigger(score):
588
+ text = report_text("methodology", {"D1": score}).replace(
589
+ f'trigger: "{score} trigger"\n', "", 1
590
+ )
591
+ with pytest.raises(cps.ReportError, match="TRIGGER-GRAMMAR"):
592
+ cps.parse_report("methodology.md", text, FULL)
593
+
594
+
595
+ @pytest.mark.parametrize(
596
+ "role,did,score_line",
597
+ (
598
+ ("methodology", "D1", "score: pass"),
599
+ ("eic", "D1", "score: not_assessed"),
600
+ ),
601
+ )
602
+ def test_nontriggering_score_forbids_trigger(role, did, score_line):
603
+ text = report_text(role).replace(
604
+ f"### {did}:", f'### {did}:', 1
605
+ ).replace(
606
+ score_line, score_line + '\ntrigger: "post hoc trigger"', 1
607
+ )
608
+ with pytest.raises(cps.ReportError, match="TRIGGER-GRAMMAR"):
609
+ cps.parse_report(f"{role}.md", text, FULL)
610
+
611
+
612
+ def test_nonmandatory_block_cannot_carry_block_class():
613
+ text = report_text("perspective", {"D4": "pass"}).replace(
614
+ "### D4: cross_disciplinary_relevance\nscore: pass",
615
+ "### D4: cross_disciplinary_relevance\nscore: block\n"
616
+ "block_class: repairable\ntrigger: \"block trigger\"",
617
+ )
618
+ with pytest.raises(cps.ReportError, match="BLOCK-CLASS"):
619
+ cps.parse_report("p.md", text, FULL)
620
+
621
+
622
+ def test_denominator_excludes_ineligible_seats():
623
+ panel_reports = reports({"methodology": {"D1": "warn"}})
624
+ _, expressions = cps.load_contract(FULL_PATH)
625
+ _, fired, decision = cps.recompute_panel(
626
+ panel_reports, FULL, expressions, []
627
+ )
628
+ assert "F5" in fired
629
+ assert decision == "editorial_decision=minor_revision"
630
+
631
+
632
+ def test_denominator_exclusion_ignores_decision_flipping_ineligible_score():
633
+ panel_reports = reports()
634
+ eic_report = next(report for report in panel_reports if report.role == "eic")
635
+ eic_report.scores["D1"] = state("fatal")
636
+ contract, expressions = cps.load_contract(FULL_PATH)
637
+ assessed, fired, decision = cps.recompute_panel(
638
+ panel_reports, contract, expressions, []
639
+ )
640
+ assert len(assessed["D1"]) == 1
641
+ assert assessed["D1"][0].score == "pass"
642
+ assert fired == ["F0"]
643
+ assert decision == "editorial_decision=accept"
644
+
645
+
646
+ def test_roles_cross_check_rejects_dispatch_role_swap(tmp_path, capsys):
647
+ report_path = tmp_path / "eic.md"
648
+ report_path.write_text(report_text("eic"), encoding="utf-8")
649
+ result = cps.main([
650
+ "--contract", str(FULL_PATH),
651
+ "--report", str(report_path),
652
+ "--roles", "methodology",
653
+ "--layer1-only",
654
+ ])
655
+ assert result == cps.EXIT_REVIEWER
656
+ assert "[ROLE-BINDING:" in capsys.readouterr().out
657
+
658
+
659
+ def test_roles_cross_check_accepts_matching_dispatch_role(tmp_path, capsys):
660
+ report_path = tmp_path / "eic.md"
661
+ report_path.write_text(report_text("eic"), encoding="utf-8")
662
+ result = cps.main([
663
+ "--contract", str(FULL_PATH),
664
+ "--report", str(report_path),
665
+ "--roles", "eic",
666
+ "--layer1-only",
667
+ ])
668
+ assert result == cps.EXIT_PASS
669
+ assert "LAYER1-ONLY: PASS" in capsys.readouterr().out
670
+
671
+
672
+ def test_dimension_unassessed_aborts():
673
+ panel_reports = reports({
674
+ "methodology": {"D3": "abstain"},
675
+ "da": {"D3": "abstain"},
676
+ })
677
+ _, expressions = cps.load_contract(FULL_PATH)
678
+ with pytest.raises(cps.ContractError, match="DIMENSION-UNASSESSED: D3"):
679
+ cps.recompute_panel(panel_reports, FULL, expressions, [])
680
+
681
+
682
+ def test_dimension_verdict_mismatch_is_synthesis_failure():
683
+ panel_reports = reports()
684
+ text, expressions = synthesis_for(panel_reports)
685
+ text = text.replace("D1=pass", "D1=warn")
686
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
687
+ assert any("PANEL-SYNTHESIS-MISMATCH" in item for item in
688
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, []))
689
+
690
+
691
+ def test_fatal_precedence_over_repairable():
692
+ panel_reports = reports({
693
+ "methodology": {"D1": "fatal"},
694
+ "domain": {"D2": "block"},
695
+ })
696
+ text, expressions = synthesis_for(panel_reports)
697
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
698
+ assert synthesis.fired[:2] == ["F1", "F2"]
699
+ assert synthesis.decision == "editorial_decision=reject"
700
+ assert cps.layer2_check(panel_reports, FULL, expressions, synthesis, []) == []
701
+
702
+
703
+ @pytest.mark.parametrize("adjudication", ["VALIDATED", "UNRESOLVED"])
704
+ def test_da_accept_conflict_requires_counted_marker(adjudication):
705
+ panel_reports = reports(da_ids=("C1",))
706
+ text, expressions = synthesis_for(
707
+ panel_reports, {"C1": adjudication}, marker_count=1
708
+ )
709
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
710
+ assert cps.layer2_check(panel_reports, FULL, expressions, synthesis, []) == []
711
+ missing = cps.parse_synthesis(
712
+ "s.md", text.replace(
713
+ "\n[DA-CRITICAL-VS-ACCEPT: 1 validated/unresolved]", ""
714
+ ), FULL
715
+ )
716
+ assert any("MARKER" in item for item in
717
+ cps.layer2_check(panel_reports, FULL, expressions, missing, []))
718
+
719
+
720
+ def test_da_rejected_with_rationale_accepts_without_marker():
721
+ panel_reports = reports(da_ids=("C1",))
722
+ text, expressions = synthesis_for(
723
+ panel_reports,
724
+ {"C1": "REJECTED"},
725
+ rationales={"C1": "The quoted sentence does not support the claim."},
726
+ )
727
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
728
+ assert cps.layer2_check(panel_reports, FULL, expressions, synthesis, []) == []
729
+
730
+
731
+ @pytest.mark.parametrize(
732
+ "adjudications,rationales,marker,fragment",
733
+ [
734
+ ({}, {}, None, "MISMATCH"), # omitted C1
735
+ ({"C1": "REJECTED", "C3": "VALIDATED"},
736
+ {"C1": "rationale"}, 1, "MISMATCH"), # phantom C3
737
+ ({"C1": "REJECTED"}, {}, None, "RATIONALE"),
738
+ ({"C1": "VALIDATED"}, {}, 2, "MARKER"),
739
+ ],
740
+ )
741
+ def test_da_gate_negative_fixtures(
742
+ adjudications, rationales, marker, fragment
743
+ ):
744
+ panel_reports = reports(da_ids=("C1",))
745
+ text, expressions = synthesis_for(
746
+ panel_reports, adjudications, marker_count=marker,
747
+ rationales=rationales,
748
+ )
749
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
750
+ assert any(fragment in item for item in
751
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, []))
752
+
753
+
754
+ @pytest.mark.parametrize(
755
+ "mutation",
756
+ [
757
+ lambda text: text.replace("#### CRITICAL", "#### Critical", 1),
758
+ lambda text: text.replace("#### CRITICAL", "#### CRITICAL ISSUES", 1),
759
+ lambda text: text.replace(
760
+ "#### CRITICAL",
761
+ "#### CRITICAL\n"
762
+ "| # | Issue | Evidence Anchor |\n"
763
+ "|---|-------|-----------------|\n\n"
764
+ "#### CRITICAL",
765
+ 1,
766
+ ),
767
+ ],
768
+ )
769
+ def test_da_critical_section_drift_fails_closed(mutation):
770
+ da_report = next(report for report in reports() if report.role == "da")
771
+ with pytest.raises(cps.ReportError, match="exactly one #### CRITICAL"):
772
+ cps.parse_da_critical_table(mutation(da_report.text), da_report.path)
773
+
774
+
775
+ @pytest.mark.parametrize(
776
+ "mutation",
777
+ [
778
+ lambda text: text.replace("#### MAJOR", "#### Major", 1),
779
+ lambda text: text.replace("#### MAJOR", "", 1),
780
+ lambda text: text.replace(
781
+ "#### MAJOR",
782
+ "#### MAJOR\n"
783
+ "| # | Issue | Evidence Anchor |\n"
784
+ "|---|-------|-----------------|\n\n"
785
+ "#### MAJOR",
786
+ 1,
787
+ ),
788
+ ],
789
+ )
790
+ def test_da_major_section_drift_fails_in_synthesis_path(mutation):
791
+ panel_reports = reports()
792
+ da_report = next(report for report in panel_reports if report.role == "da")
793
+ da_report.text = mutation(da_report.text)
794
+ text, expressions = synthesis_for(panel_reports)
795
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
796
+ with pytest.raises(cps.ReportError, match="DA-MAJOR-PARSE"):
797
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
798
+
799
+
800
+ @pytest.mark.parametrize(
801
+ "old,new",
802
+ [
803
+ ("|---|-------|-----------------|", ""),
804
+ ("|---|-------|-----------------|", "|--|-------|-----------------|"),
805
+ ("|---|-------|-----------------|", "|---|-------|"),
806
+ ],
807
+ )
808
+ def test_da_separator_drift_fails_in_synthesis_path(old, new):
809
+ panel_reports = reports(da_ids=("C1",))
810
+ da_report = next(report for report in panel_reports if report.role == "da")
811
+ da_report.text = da_report.text.replace(old, new, 1)
812
+ text, expressions = synthesis_for(
813
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
814
+ )
815
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
816
+ with pytest.raises(cps.ReportError, match="separator"):
817
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
818
+
819
+
820
+ def test_da_trailing_row_without_outer_pipes_fails_in_synthesis_path():
821
+ panel_reports = reports(da_ids=("C1", "C2"))
822
+ da_report = next(report for report in panel_reports if report.role == "da")
823
+ da_report.text = da_report.text.replace(
824
+ '| C2 | Issue | text: "quoted evidence" p. 1 |',
825
+ 'C2 | Issue | text: "quoted evidence" p. 1',
826
+ 1,
827
+ )
828
+ synthesis_text, expressions = synthesis_for(
829
+ panel_reports, {"C1": "VALIDATED", "C2": "VALIDATED"}, marker_count=2
830
+ )
831
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
832
+ with pytest.raises(cps.ReportError, match="outer-pipe-delimited"):
833
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
834
+
835
+
836
+ def test_da_pre_table_prose_passes_in_synthesis_path():
837
+ panel_reports = reports(da_ids=("C1",))
838
+ da_report = next(report for report in panel_reports if report.role == "da")
839
+ da_report.text = da_report.text.replace(
840
+ "#### CRITICAL",
841
+ "Ordinary adversarial commentary precedes the terminal tables.\n\n"
842
+ "#### CRITICAL",
843
+ 1,
844
+ )
845
+ synthesis_text, expressions = synthesis_for(
846
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
847
+ )
848
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
849
+ assert cps.layer2_check(
850
+ panel_reports, FULL, expressions, synthesis, []
851
+ ) == []
852
+
853
+
854
+ def test_da_bare_comment_closer_passes_in_synthesis_path():
855
+ panel_reports = reports(da_ids=("C1",))
856
+ da_report = next(report for report in panel_reports if report.role == "da")
857
+ da_report.text = da_report.text.replace(
858
+ "#### CRITICAL",
859
+ "The reported N moves 41 --> 38 without explanation.\n\n"
860
+ "#### CRITICAL",
861
+ 1,
862
+ ).replace(
863
+ 'text: "quoted evidence" p. 1',
864
+ 'text: "N moves 41 --> 38" p. 1',
865
+ 1,
866
+ )
867
+ synthesis_text, expressions = synthesis_for(
868
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
869
+ )
870
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
871
+ assert cps.layer2_check(
872
+ panel_reports, FULL, expressions, synthesis, []
873
+ ) == []
874
+
875
+
876
+ def test_da_post_critical_table_prose_fails_in_synthesis_path():
877
+ panel_reports = reports()
878
+ da_report = next(report for report in panel_reports if report.role == "da")
879
+ da_report.text = da_report.text.replace(
880
+ "\n\n#### MAJOR",
881
+ "\n\n*None. Ordinary adversarial commentary.*\n\n#### MAJOR",
882
+ 1,
883
+ )
884
+ synthesis_text, expressions = synthesis_for(panel_reports)
885
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
886
+ with pytest.raises(cps.ReportError, match="issue tables are terminal"):
887
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
888
+
889
+
890
+ _DA_TERMINAL_LATE_SURFACES = (
891
+ '| C2 | Late issue | text: "late quoted evidence" p. 2 |',
892
+ "| X9 | Bogus issue | |",
893
+ (
894
+ "| # | Issue | Evidence Anchor |\n"
895
+ "|---|-------|-----------------|\n"
896
+ "| C9 | Shadow issue | |"
897
+ ),
898
+ 'C2 | Late issue | text: "late quoted evidence" p. 2',
899
+ '— | Late issue | text: "late quoted evidence"',
900
+ "# | Issue | Evidence Anchor",
901
+ "C2\nLate issue without pipes\nfigure: Figure 2",
902
+ "- C2\n- Late critical issue\n- figure: Figure 2",
903
+ "> Ordinary post-table commentary",
904
+ "##### Additional commentary",
905
+ "### Closing note\nOrdinary late prose",
906
+ )
907
+
908
+
909
+ @pytest.mark.parametrize(
910
+ "late_surface",
911
+ _DA_TERMINAL_LATE_SURFACES,
912
+ )
913
+ def test_da_post_boundary_table_surfaces_fail_in_synthesis_path(
914
+ late_surface,
915
+ ):
916
+ panel_reports = reports(da_ids=("C1",))
917
+ da_report = next(report for report in panel_reports if report.role == "da")
918
+ da_report.text = da_report.text.replace(
919
+ "\n\n#### MAJOR",
920
+ f"\n\n{late_surface}\n\n#### MAJOR",
921
+ 1,
922
+ )
923
+ synthesis_text, expressions = synthesis_for(
924
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
925
+ )
926
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
927
+ with pytest.raises(cps.ReportError, match="issue tables are terminal"):
928
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
929
+
930
+
931
+ @pytest.mark.parametrize("late_surface", _DA_TERMINAL_LATE_SURFACES)
932
+ def test_da_post_major_table_surfaces_fail_in_synthesis_path(
933
+ late_surface,
934
+ ):
935
+ panel_reports = reports(da_ids=("C1",))
936
+ da_report = next(report for report in panel_reports if report.role == "da")
937
+ da_report.text += f"\n\n{late_surface}"
938
+ synthesis_text, expressions = synthesis_for(
939
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
940
+ )
941
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
942
+ with pytest.raises(cps.ReportError, match="issue tables are terminal"):
943
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
944
+
945
+
946
+ def test_da_fenced_payload_after_major_fails_in_synthesis_path():
947
+ panel_reports = reports(da_ids=("C1",))
948
+ da_report = next(report for report in panel_reports if report.role == "da")
949
+ da_report.text += (
950
+ "\n\n```markdown\n"
951
+ '| C2 | Hidden critical issue | text: "hidden evidence" p. 2 |\n'
952
+ "```"
953
+ )
954
+ synthesis_text, expressions = synthesis_for(
955
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
956
+ )
957
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
958
+ with pytest.raises(cps.ReportError, match="issue tables are terminal"):
959
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
960
+
961
+
962
+ def test_da_html_comment_inside_fence_fails_in_synthesis_path():
963
+ panel_reports = reports()
964
+ da_report = next(report for report in panel_reports if report.role == "da")
965
+ da_report.text += "\n\n```\n<!-- hidden adjudication payload -->\n```"
966
+ synthesis_text, expressions = synthesis_for(panel_reports)
967
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
968
+ with pytest.raises(cps.ReportError, match="HTML comments are forbidden"):
969
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
970
+
971
+
972
+ def test_da_html_commented_tables_fail_in_synthesis_path():
973
+ panel_reports = reports()
974
+ da_report = next(report for report in panel_reports if report.role == "da")
975
+ da_report.text = da_report.text.replace(
976
+ "#### CRITICAL", "<!--\n#### CRITICAL", 1
977
+ )
978
+ da_report.text += "\n-->"
979
+ synthesis_text, expressions = synthesis_for(panel_reports)
980
+ synthesis = cps.parse_synthesis("s.md", synthesis_text, FULL)
981
+ with pytest.raises(cps.ReportError, match="HTML comments are forbidden"):
982
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
983
+
984
+
985
+ @pytest.mark.parametrize(
986
+ "old,new,fragment",
987
+ [
988
+ (
989
+ "| # | Issue | Evidence Anchor |",
990
+ "| # | # | Evidence Anchor |",
991
+ "exactly one #",
992
+ ),
993
+ (
994
+ "| # | Issue | Evidence Anchor |",
995
+ "| # | Evidence Anchor | Evidence Anchor |",
996
+ "exactly one #",
997
+ ),
998
+ (
999
+ "| # | Issue | Evidence Anchor |",
1000
+ "| ID | Issue | Anchor |",
1001
+ "missing table header",
1002
+ ),
1003
+ (
1004
+ "| C2 | Issue |",
1005
+ "| C1 | Issue |",
1006
+ "duplicate CRITICAL ID",
1007
+ ),
1008
+ (
1009
+ "| C2 | Issue |",
1010
+ "| X2 | Issue |",
1011
+ "invalid CRITICAL ID",
1012
+ ),
1013
+ ],
1014
+ )
1015
+ def test_da_header_and_critical_id_gates_fail_in_synthesis_path(
1016
+ old, new, fragment
1017
+ ):
1018
+ panel_reports = reports(da_ids=("C1", "C2"))
1019
+ da_report = next(report for report in panel_reports if report.role == "da")
1020
+ da_report.text = da_report.text.replace(old, new, 1)
1021
+ text, expressions = synthesis_for(
1022
+ panel_reports,
1023
+ {"C1": "VALIDATED", "C2": "VALIDATED"},
1024
+ marker_count=2,
1025
+ )
1026
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1027
+ with pytest.raises(cps.ReportError, match=fragment):
1028
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1029
+
1030
+
1031
+ def test_da_shadow_table_fails_in_synthesis_path():
1032
+ panel_reports = reports(da_ids=("C1",))
1033
+ da_report = next(report for report in panel_reports if report.role == "da")
1034
+ canonical = (
1035
+ '| # | Issue | Evidence Anchor |\n'
1036
+ '|---|-------|-----------------|\n'
1037
+ '| C1 | Issue | text: "quoted evidence" p. 1 |'
1038
+ )
1039
+ shadowed = (
1040
+ '| ID | Issue | Anchor |\n'
1041
+ '|---|-------|--------|\n'
1042
+ '| C1 | Issue | text: "quoted evidence" p. 1 |\n\n'
1043
+ '| # | Issue | Evidence Anchor |\n'
1044
+ '|---|-------|-----------------|'
1045
+ )
1046
+ da_report.text = da_report.text.replace(canonical, shadowed, 1)
1047
+ text, expressions = synthesis_for(panel_reports)
1048
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1049
+ with pytest.raises(cps.ReportError, match="first nonblank line"):
1050
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1051
+
1052
+
1053
+ def test_da_standalone_critical_fails_in_synthesis_path():
1054
+ panel_reports = reports()
1055
+ da_report = next(report for report in panel_reports if report.role == "da")
1056
+ da_report.text = da_report.text.replace(
1057
+ "#### CRITICAL",
1058
+ "### Further adversarial challenge\n"
1059
+ "- **Severity**: Critical | **Confidence**: 5 (statistics)\n\n"
1060
+ "#### CRITICAL",
1061
+ 1,
1062
+ )
1063
+ text, expressions = synthesis_for(panel_reports)
1064
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1065
+ with pytest.raises(cps.ReportError, match="standalone Severity"):
1066
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1067
+
1068
+
1069
+ @pytest.mark.parametrize("label", ("severity", "sEvErItY"))
1070
+ def test_da_case_variant_standalone_critical_fails_in_synthesis_path(label):
1071
+ panel_reports = reports()
1072
+ da_report = next(report for report in panel_reports if report.role == "da")
1073
+ da_report.text = da_report.text.replace(
1074
+ "#### CRITICAL",
1075
+ "### Further adversarial challenge\n"
1076
+ f"This is **{label}**: Critical and no revision cures it.\n\n"
1077
+ "#### CRITICAL",
1078
+ 1,
1079
+ )
1080
+ text, expressions = synthesis_for(panel_reports)
1081
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1082
+ with pytest.raises(cps.ReportError, match="standalone Severity"):
1083
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1084
+
1085
+
1086
+ def test_da_extra_issue_table_band_fails_in_synthesis_path():
1087
+ panel_reports = reports()
1088
+ da_report = next(report for report in panel_reports if report.role == "da")
1089
+ da_report.text = da_report.text.replace(
1090
+ "#### MAJOR",
1091
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1092
+ "| # | Issue | Evidence Anchor |\n"
1093
+ "|---|-------|-----------------|\n"
1094
+ '| C1 | impossible df | text: "n=41" p. 4 |\n\n'
1095
+ "#### MAJOR",
1096
+ 1,
1097
+ )
1098
+ text, expressions = synthesis_for(panel_reports)
1099
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1100
+ with pytest.raises(cps.ReportError, match="unexpected issue-table band"):
1101
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1102
+
1103
+
1104
+ @pytest.mark.parametrize(
1105
+ ("lead_in", "header"),
1106
+ (
1107
+ ("The following issues invalidate the claim:\n\n",
1108
+ "| # | Issue | Evidence Anchor |"),
1109
+ ("", "| # | Issue | evidence anchor |"),
1110
+ ("", "# | Issue | Evidence Anchor"),
1111
+ ),
1112
+ )
1113
+ def test_da_disguised_extra_issue_table_band_fails_in_synthesis_path(
1114
+ lead_in, header
1115
+ ):
1116
+ panel_reports = reports()
1117
+ da_report = next(report for report in panel_reports if report.role == "da")
1118
+ da_report.text = da_report.text.replace(
1119
+ "#### MAJOR",
1120
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1121
+ f"{lead_in}{header}\n"
1122
+ "|---|-------|-----------------|\n"
1123
+ '| C9 | impossible df | text: "n=41" p. 4 |\n\n'
1124
+ "#### MAJOR",
1125
+ 1,
1126
+ )
1127
+ text, expressions = synthesis_for(panel_reports)
1128
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1129
+ with pytest.raises(cps.ReportError, match="unexpected issue-table band"):
1130
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1131
+
1132
+
1133
+ @pytest.mark.parametrize("placement", ("preamble", "extra_h2"))
1134
+ def test_da_issue_table_outside_canonical_bands_fails_synthesis(placement):
1135
+ panel_reports = reports()
1136
+ da_report = next(report for report in panel_reports if report.role == "da")
1137
+ table = (
1138
+ "| # | Issue | Evidence Anchor |\n"
1139
+ "|---|-------|-----------------|\n"
1140
+ '| C9 | impossible df | text: "n=41" p. 4 |\n'
1141
+ )
1142
+ if placement == "preamble":
1143
+ da_report.text = da_report.text.replace(
1144
+ "#### CRITICAL", table + "\n#### CRITICAL", 1
1145
+ )
1146
+ else:
1147
+ da_report.text += "\n## Appendix\n" + table
1148
+ text, expressions = synthesis_for(panel_reports)
1149
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1150
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1151
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1152
+
1153
+
1154
+ def test_da_internal_header_whitespace_fails_in_synthesis_path():
1155
+ panel_reports = reports()
1156
+ da_report = next(report for report in panel_reports if report.role == "da")
1157
+ da_report.text = da_report.text.replace(
1158
+ "#### MAJOR",
1159
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1160
+ "# | Issue | Evidence Anchor\n"
1161
+ "---|-------|-----------------\n"
1162
+ 'C9 | impossible df | text: "n=41" p. 4\n\n'
1163
+ "#### MAJOR",
1164
+ 1,
1165
+ )
1166
+ text, expressions = synthesis_for(panel_reports)
1167
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1168
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1169
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1170
+
1171
+
1172
+ @pytest.mark.parametrize(
1173
+ "header",
1174
+ (
1175
+ "| ID | Issue | Evidence Anchor |",
1176
+ "| # | Issue | Evidence |",
1177
+ "| **#** | Issue | **Evidence Anchor** |",
1178
+ "| `#` | Issue | `Evidence Anchor` |",
1179
+ ),
1180
+ )
1181
+ def test_da_partial_or_formatted_issue_header_fails_synthesis(header):
1182
+ panel_reports = reports()
1183
+ da_report = next(report for report in panel_reports if report.role == "da")
1184
+ da_report.text = da_report.text.replace(
1185
+ "#### MAJOR",
1186
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1187
+ f"{header}\n"
1188
+ "|---|-------|-----------------|\n"
1189
+ '| C9 | impossible df | text: "n=41" p. 4 |\n\n'
1190
+ "#### MAJOR",
1191
+ 1,
1192
+ )
1193
+ text, expressions = synthesis_for(panel_reports)
1194
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1195
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1196
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1197
+
1198
+
1199
+ @pytest.mark.parametrize(
1200
+ "header",
1201
+ (
1202
+ "| ID | Issue | [Evidence Anchor][anchor] |",
1203
+ r"| \# | Issue | Evidence |",
1204
+ '| ID | Issue | <span title="x>y">Evidence Anchor</span> |',
1205
+ ),
1206
+ )
1207
+ def test_da_commonmark_visible_issue_header_fails_synthesis(header):
1208
+ panel_reports = reports()
1209
+ da_report = next(report for report in panel_reports if report.role == "da")
1210
+ da_report.text = da_report.text.replace(
1211
+ "#### MAJOR",
1212
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1213
+ f"{header}\n"
1214
+ "|---|-------|-----------------|\n"
1215
+ '| C9 | impossible df | text: "n=41" p. 4 |\n\n'
1216
+ "#### MAJOR",
1217
+ 1,
1218
+ )
1219
+ text, expressions = synthesis_for(panel_reports)
1220
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1221
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1222
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1223
+
1224
+
1225
+ def test_da_balanced_link_destination_header_fails_synthesis():
1226
+ panel_reports = reports()
1227
+ da_report = next(report for report in panel_reports if report.role == "da")
1228
+ header = (
1229
+ r"| [\#](<https://x.test/a(b)>) | Issue | "
1230
+ r"[Evidence Anchor](<https://x.test/a(b)>) |"
1231
+ )
1232
+ da_report.text = da_report.text.replace(
1233
+ "#### MAJOR",
1234
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1235
+ f"{header}\n"
1236
+ "|---|-------|-----------------|\n"
1237
+ '| C9 | impossible df | text: "n=41" p. 4 |\n\n'
1238
+ "#### MAJOR",
1239
+ 1,
1240
+ )
1241
+ text, expressions = synthesis_for(panel_reports)
1242
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1243
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1244
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1245
+
1246
+
1247
+ def test_da_typed_anchor_payload_alone_fails_synthesis():
1248
+ panel_reports = reports()
1249
+ da_report = next(report for report in panel_reports if report.role == "da")
1250
+ header = (
1251
+ r"| [\#](<https://x.test/a(b)>) | Issue | "
1252
+ r"[Evidence Anchor](<https://x.test/a(b)>) |"
1253
+ )
1254
+ da_report.text = da_report.text.replace(
1255
+ "#### MAJOR",
1256
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1257
+ f"{header}\n"
1258
+ "|---|-------|-----------------|\n"
1259
+ '| 1 | impossible df | `text: "n=41" p. 4` |\n\n'
1260
+ "#### MAJOR",
1261
+ 1,
1262
+ )
1263
+ text, expressions = synthesis_for(panel_reports)
1264
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1265
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1266
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1267
+
1268
+
1269
+ def test_da_escaped_pipe_cell_evasion_fails_synthesis():
1270
+ panel_reports = reports()
1271
+ da_report = next(report for report in panel_reports if report.role == "da")
1272
+ block = (
1273
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1274
+ r"| [\#<!--\|-->](https://x.test) | Issue | "
1275
+ r"[Evidence<!--\|--> Anchor](https://x.test) |" "\n"
1276
+ "|---|---|---|\n"
1277
+ r"| [C<!--\|-->9](https://x.test) | impossible df | "
1278
+ r'[text<!--\|-->: "n=41" p. 4](https://x.test) |' "\n\n"
1279
+ )
1280
+ da_report.text = da_report.text.replace(
1281
+ "#### MAJOR", block + "#### MAJOR", 1
1282
+ )
1283
+ text, expressions = synthesis_for(panel_reports)
1284
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1285
+ with pytest.raises(cps.ReportError, match="HTML comments are forbidden"):
1286
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1287
+
1288
+
1289
+ def test_da_canonical_rows_allow_escaped_pipes():
1290
+ text = report_text("da", da_ids=("C1",)).replace(
1291
+ "| C1 | Issue |",
1292
+ r"| C1 | Issue \| detail |",
1293
+ 1,
1294
+ )
1295
+ text += "\n" + r'| M1 | Issue \| detail | text: "quoted evidence" p. 1 |'
1296
+ critical, major = cps.parse_da_tables(text, "da.md")
1297
+ assert list(critical) == ["C1"]
1298
+ assert major == ['text: "quoted evidence" p. 1']
1299
+
1300
+
1301
+ def test_da_repeated_absence_separators_fail_in_synthesis_path():
1302
+ malformed = (
1303
+ "absence: Methods — expected ; checked appendix "
1304
+ "— expected ethics; checked supplement"
1305
+ )
1306
+ text = report_text("da", da_ids=("C1",)).replace(
1307
+ 'text: "quoted evidence" p. 1',
1308
+ malformed,
1309
+ 1,
1310
+ )
1311
+ with pytest.raises(cps.ReportError, match="ANCHOR-INVALID"):
1312
+ cps.parse_da_tables(text, "da.md")
1313
+
1314
+
1315
+ @pytest.mark.parametrize(
1316
+ "malformed",
1317
+ (
1318
+ "absence: Methods; checked appendix — expected ethics",
1319
+ '[ text: §5 "short exact quote" ]',
1320
+ "equation: Eq. ]3[",
1321
+ ),
1322
+ )
1323
+ def test_da_misordered_absence_or_padded_wrapper_fails_synthesis(malformed):
1324
+ text = report_text("da", da_ids=("C1",)).replace(
1325
+ 'text: "quoted evidence" p. 1',
1326
+ malformed,
1327
+ 1,
1328
+ )
1329
+ with pytest.raises(cps.ReportError, match="ANCHOR-INVALID"):
1330
+ cps.parse_da_tables(text, "da.md")
1331
+
1332
+
1333
+ @pytest.mark.parametrize(
1334
+ "invisible", ("\u0600", "\u200b", "\u034f", "\ufe0e", "\u3164", "\ufff0")
1335
+ )
1336
+ def test_da_invisible_issue_payload_fails_synthesis(invisible):
1337
+ panel_reports = reports()
1338
+ da_report = next(report for report in panel_reports if report.role == "da")
1339
+ block = (
1340
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1341
+ f"| #{invisible} | Issue | Evidence{invisible} Anchor |\n"
1342
+ "|---|---|---|\n"
1343
+ f'| C{invisible}9 | impossible df | text{invisible}: "n=41" p. 4 |\n\n'
1344
+ )
1345
+ da_report.text = da_report.text.replace(
1346
+ "#### MAJOR", block + "#### MAJOR", 1
1347
+ )
1348
+ text, expressions = synthesis_for(panel_reports)
1349
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1350
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1351
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1352
+
1353
+
1354
+ def test_da_fullwidth_issue_payload_fails_synthesis():
1355
+ panel_reports = reports()
1356
+ da_report = next(report for report in panel_reports if report.role == "da")
1357
+ block = (
1358
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1359
+ "| # | Issue | Evidence Anchor |\n"
1360
+ "|---|---|---|\n"
1361
+ '| C9 | impossible df | text: "n=41" p. 4 |\n\n'
1362
+ )
1363
+ da_report.text = da_report.text.replace(
1364
+ "#### MAJOR", block + "#### MAJOR", 1
1365
+ )
1366
+ text, expressions = synthesis_for(panel_reports)
1367
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1368
+ with pytest.raises(cps.ReportError, match="unexpected issue-table"):
1369
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1370
+
1371
+
1372
+ def test_da_raw_html_issue_table_fails_synthesis():
1373
+ panel_reports = reports()
1374
+ da_report = next(report for report in panel_reports if report.role == "da")
1375
+ block = (
1376
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1377
+ "<table><tr><th>ID</th><th>Evidence</th></tr>"
1378
+ "<tr><td>C9</td><td>text: n=41</td></tr></table>\n\n"
1379
+ )
1380
+ da_report.text = da_report.text.replace(
1381
+ "#### MAJOR", block + "#### MAJOR", 1
1382
+ )
1383
+ text, expressions = synthesis_for(panel_reports)
1384
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1385
+ with pytest.raises(cps.ReportError, match="raw HTML issue-table"):
1386
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1387
+
1388
+
1389
+ def test_da_nested_html_issue_table_in_canonical_row_fails_synthesis():
1390
+ panel_reports = reports()
1391
+ da_report = next(report for report in panel_reports if report.role == "da")
1392
+ nested = (
1393
+ "real issue <table><tr><th>#</th><th>Evidence Anchor</th></tr>"
1394
+ '<tr><td>C9</td><td>text: "impossible df" p. 4</td></tr></table>'
1395
+ )
1396
+ da_report.text = da_report.text.replace(
1397
+ "#### MAJOR\n"
1398
+ "| # | Issue | Evidence Anchor |\n"
1399
+ "|---|-------|-----------------|",
1400
+ "#### MAJOR\n"
1401
+ "| # | Issue | Evidence Anchor |\n"
1402
+ "|---|-------|-----------------|\n"
1403
+ f'| M1 | {nested} | text: "quote" p. 1 |',
1404
+ 1,
1405
+ )
1406
+ text, expressions = synthesis_for(panel_reports)
1407
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1408
+ with pytest.raises(cps.ReportError, match="raw HTML issue-table"):
1409
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1410
+
1411
+
1412
+ def test_da_bare_html_row_fails_synthesis():
1413
+ panel_reports = reports()
1414
+ da_report = next(report for report in panel_reports if report.role == "da")
1415
+ block = (
1416
+ "#### ADDITIONAL CRITICAL FINDINGS\n"
1417
+ "<tr><td>C9</td><td>text: n=41</td></tr>\n\n"
1418
+ )
1419
+ da_report.text = da_report.text.replace(
1420
+ "#### MAJOR", block + "#### MAJOR", 1
1421
+ )
1422
+ text, expressions = synthesis_for(panel_reports)
1423
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1424
+ with pytest.raises(cps.ReportError, match="raw HTML issue-table"):
1425
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1426
+
1427
+
1428
+ def test_da_empty_major_id_fails_in_synthesis_path():
1429
+ panel_reports = reports()
1430
+ da_report = next(report for report in panel_reports if report.role == "da")
1431
+ marker = "|---|-------|-----------------|"
1432
+ before, trailing = da_report.text.rsplit(marker, 1)
1433
+ da_report.text = (
1434
+ before + marker + '\n| | Issue | text: "quote" |' + trailing
1435
+ )
1436
+ text, expressions = synthesis_for(panel_reports)
1437
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1438
+ with pytest.raises(
1439
+ (cps.ReportError, cps.SynthesisError), match="empty MAJOR # cell"
1440
+ ):
1441
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1442
+
1443
+
1444
+ def test_da_empty_critical_anchor_fails_in_synthesis_path():
1445
+ panel_reports = reports(da_ids=("C1",))
1446
+ da_report = next(report for report in panel_reports if report.role == "da")
1447
+ da_report.text = da_report.text.replace(
1448
+ '| C1 | Issue | text: "quoted evidence" p. 1 |',
1449
+ "| C1 | Issue | |",
1450
+ 1,
1451
+ )
1452
+ text, expressions = synthesis_for(
1453
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
1454
+ )
1455
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1456
+ with pytest.raises(cps.ReportError, match="ANCHOR-MISSING"):
1457
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1458
+
1459
+
1460
+ @pytest.mark.parametrize(
1461
+ "anchor,fragment",
1462
+ [
1463
+ ("", "ANCHOR-MISSING"),
1464
+ ("see page 3", "ANCHOR-INVALID"),
1465
+ ],
1466
+ )
1467
+ def test_da_major_anchor_fails_in_synthesis_path(anchor, fragment):
1468
+ panel_reports = reports()
1469
+ da_report = next(report for report in panel_reports if report.role == "da")
1470
+ marker = "|---|-------|-----------------|"
1471
+ before, trailing = da_report.text.rsplit(marker, 1)
1472
+ da_report.text = (
1473
+ before + marker + f"\n| M1 | Issue | {anchor} |" + trailing
1474
+ )
1475
+ text, expressions = synthesis_for(panel_reports)
1476
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1477
+ with pytest.raises(cps.ReportError, match=fragment):
1478
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, [])
1479
+
1480
+
1481
+ def test_da_valid_major_anchor_passes_in_synthesis_path():
1482
+ panel_reports = reports()
1483
+ da_report = next(report for report in panel_reports if report.role == "da")
1484
+ marker = "|---|-------|-----------------|"
1485
+ before, trailing = da_report.text.rsplit(marker, 1)
1486
+ da_report.text = (
1487
+ before + marker
1488
+ + '\n| M1 | Issue | text: "short quote" |'
1489
+ + trailing
1490
+ )
1491
+ text, expressions = synthesis_for(panel_reports)
1492
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1493
+ assert cps.layer2_check(
1494
+ panel_reports, FULL, expressions, synthesis, []
1495
+ ) == []
1496
+
1497
+
1498
+ def test_marker_forbidden_under_nonaccept():
1499
+ panel_reports = reports({"methodology": {"D1": "warn"}}, da_ids=("C1",))
1500
+ text, expressions = synthesis_for(
1501
+ panel_reports, {"C1": "VALIDATED"}, marker_count=1
1502
+ )
1503
+ synthesis = cps.parse_synthesis("s.md", text, FULL)
1504
+ assert synthesis.decision == "editorial_decision=minor_revision"
1505
+ assert any("forbidden" in item for item in
1506
+ cps.layer2_check(panel_reports, FULL, expressions, synthesis, []))
1507
+
1508
+
1509
+ def _evaluate_profile(contract, expressions, assessed):
1510
+ fired = [
1511
+ condition["condition_id"]
1512
+ for condition in contract["failure_conditions"]
1513
+ if cps.evaluate_expression(
1514
+ expressions[condition["condition_id"]],
1515
+ assessed,
1516
+ condition["cross_reviewer_quantifier"],
1517
+ [],
1518
+ )
1519
+ ]
1520
+ return fired, cps.resolve_decision(
1521
+ contract["failure_conditions"], set(fired)
1522
+ )
1523
+
1524
+
1525
+ def test_full_contract_exhaustive_13824_profiles():
1526
+ contract, expressions = cps.load_contract(FULL_PATH)
1527
+ mandatory_single = ("pass", "warn", "block", "fatal")
1528
+ nonmandatory_single = ("pass", "warn", "block")
1529
+ d3_states = [
1530
+ pair for pair in itertools.product(
1531
+ ("pass", "warn", "block", "fatal", "abstain"), repeat=2
1532
+ ) if pair != ("abstain", "abstain")
1533
+ ]
1534
+ count = 0
1535
+ decisions = set()
1536
+ for d1, d2, d6, d3, d4, d5 in itertools.product(
1537
+ mandatory_single, mandatory_single, mandatory_single, d3_states,
1538
+ nonmandatory_single, nonmandatory_single,
1539
+ ):
1540
+ assessed = {
1541
+ "D1": [state(d1)],
1542
+ "D2": [state(d2)],
1543
+ "D3": [state(value) for value in d3 if value != "abstain"],
1544
+ "D4": [state(d4)],
1545
+ "D5": [state(d5)],
1546
+ "D6": [state(d6)],
1547
+ }
1548
+ fired, decision = _evaluate_profile(contract, expressions, assessed)
1549
+ assert fired
1550
+ assert decision in cps.ACTION_ENUM
1551
+ decisions.add(decision)
1552
+ count += 1
1553
+ assert count == 13_824
1554
+ assert decisions == cps.ACTION_ENUM
1555
+
1556
+
1557
+ def test_methodology_focus_exhaustive_12_profiles():
1558
+ contract, expressions = cps.load_contract(MF_PATH)
1559
+ count = 0
1560
+ decisions = set()
1561
+ for d1, d2 in itertools.product(
1562
+ ("pass", "warn", "block", "fatal"),
1563
+ ("pass", "warn", "block"),
1564
+ ):
1565
+ fired, decision = _evaluate_profile(
1566
+ contract, expressions, {"D1": [state(d1)], "D2": [state(d2)]}
1567
+ )
1568
+ assert fired
1569
+ decisions.add(decision)
1570
+ count += 1
1571
+ assert count == 12
1572
+ assert decisions == cps.ACTION_ENUM
1573
+
1574
+
1575
+ def test_methodology_focus_d1_warn_is_major_revision():
1576
+ contract, expressions = cps.load_contract(MF_PATH)
1577
+ fired, decision = _evaluate_profile(
1578
+ contract,
1579
+ expressions,
1580
+ {"D1": [state("warn")], "D2": [state("pass")]},
1581
+ )
1582
+ assert fired == ["F3"]
1583
+ assert decision == "editorial_decision=major_revision"
1584
+
1585
+
1586
+ def test_methodology_focus_layer2_has_empty_da_gate():
1587
+ contract, expressions = cps.load_contract(MF_PATH)
1588
+ panel_reports = []
1589
+ for role in ("eic", "methodology"):
1590
+ lines = [f"contract_role: {role}", "", "## Dimension Scores", ""]
1591
+ for dim in contract["acceptance_dimensions"]:
1592
+ lines += [
1593
+ f"### {dim['id']}: {dim['name']}",
1594
+ "score: pass" if role in dim["eligible_roles"]
1595
+ else "score: not_assessed",
1596
+ "",
1597
+ ]
1598
+ lines += ["## Review Body", "", "No scored findings.", ""]
1599
+ panel_reports.append(cps.parse_report(
1600
+ f"{role}.md", "\n".join(lines), contract
1601
+ ))
1602
+ synthesis = cps.parse_synthesis(
1603
+ "s.md",
1604
+ "dimension_verdicts: [D1=pass, D2=pass]\n"
1605
+ "fired_conditions: [F0]\n"
1606
+ "da_critical_adjudications: []\n"
1607
+ "editorial_decision=accept\n",
1608
+ contract,
1609
+ )
1610
+ assert cps.layer2_check(
1611
+ panel_reports, contract, expressions, synthesis, []
1612
+ ) == []
1613
+
1614
+
1615
+ def test_boundary_decisions_and_d3_split_dynamic_majority():
1616
+ contract, expressions = cps.load_contract(FULL_PATH)
1617
+ base = {did: [state("pass")] for did in ("D1", "D2", "D4", "D5", "D6")}
1618
+ base["D3"] = [state("pass"), state("pass")]
1619
+
1620
+ one_warn = {**base, "D1": [state("warn")]}
1621
+ assert _evaluate_profile(contract, expressions, one_warn)[1] == \
1622
+ "editorial_decision=minor_revision"
1623
+
1624
+ normal_block = {**base, "D5": [state("block")]}
1625
+ assert _evaluate_profile(contract, expressions, normal_block)[1] == \
1626
+ "editorial_decision=minor_revision"
1627
+
1628
+ high_block = {**base, "D4": [state("block")]}
1629
+ assert _evaluate_profile(contract, expressions, high_block)[1] == \
1630
+ "editorial_decision=major_revision"
1631
+
1632
+ fatal_venue = {**base, "D6": [state("fatal")]}
1633
+ assert _evaluate_profile(contract, expressions, fatal_venue)[1] == \
1634
+ "editorial_decision=reject"
1635
+
1636
+ split = {**base, "D3": [state("block"), state("pass")]}
1637
+ fired, _ = _evaluate_profile(contract, expressions, split)
1638
+ assert "F2" in fired and "F3" not in fired
1639
+
1640
+ for assessed_d3 in ([state("warn")], [state("pass")]):
1641
+ dynamic = {**base, "D3": assessed_d3}
1642
+ fired, _ = _evaluate_profile(contract, expressions, dynamic)
1643
+ assert ("F5" in fired) == (assessed_d3[0].score == "warn")
1644
+
1645
+
1646
+ def test_n2_majority_split_cannot_harden_the_decision():
1647
+ contract, expressions = cps.load_contract(FULL_PATH)
1648
+ assessed = {
1649
+ "D1": [state("warn")],
1650
+ "D2": [state("pass")],
1651
+ "D3": [state("warn"), state("pass")],
1652
+ "D4": [state("pass")],
1653
+ "D5": [state("pass")],
1654
+ "D6": [state("pass")],
1655
+ }
1656
+ fired, decision = _evaluate_profile(contract, expressions, assessed)
1657
+ assert fired == ["F5"]
1658
+ assert decision == "editorial_decision=minor_revision"