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,1925 @@
1
+ #!/usr/bin/env python3
2
+ """Bounded mutation tests for the hermetic revision-claim-drift v2 guard (#679)."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import copy
7
+ import hashlib
8
+ import json
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+ import pytest
14
+
15
+ from scripts import check_revision_claim_drift_suite_v2 as guard
16
+ from scripts.check_heldout_measurement_report import validate_report
17
+
18
+
19
+ REPO_ROOT = Path(__file__).resolve().parents[1]
20
+ SUITE = Path(guard.SUITE_REL)
21
+ FIXTURES = Path("scripts/fixtures/revision_claim_drift_v2")
22
+ DESIGN = Path("docs/design/2026-08-10-679-revision-claim-drift-suite-v2-spec.md")
23
+ MEASUREMENT_SCHEMA = Path("evals/heldout/measurement_report.schema.json")
24
+ EXECUTION_SCHEMA = Path("evals/heldout/execution_manifest.schema.json")
25
+ LADDER = Path("shared/references/claim_strength_ladder.md")
26
+ LAUNCHER_SCHEMA = SUITE / "subject_launcher_config.schema.json"
27
+ CALL_PLAN_SCHEMA = SUITE / "subject_call_plan.schema.json"
28
+
29
+
30
+ def _copy_file(root: Path, relative: Path | str) -> None:
31
+ relative_path = Path(relative)
32
+ destination = root / relative_path
33
+ destination.parent.mkdir(parents=True, exist_ok=True)
34
+ shutil.copyfile(REPO_ROOT / relative_path, destination)
35
+
36
+
37
+ def _mirror(tmp_path: Path) -> Path:
38
+ """Copy only the repository surfaces inspected by ``run_checks``."""
39
+ root = tmp_path / "repo"
40
+ shutil.copytree(REPO_ROOT / SUITE, root / SUITE)
41
+ shutil.copytree(REPO_ROOT / FIXTURES, root / FIXTURES)
42
+ _copy_file(root, DESIGN)
43
+ _copy_file(root, LADDER)
44
+ return root
45
+
46
+
47
+ def _read_json(path: Path) -> dict[str, Any]:
48
+ value = json.loads(path.read_text(encoding="utf-8"))
49
+ assert isinstance(value, dict)
50
+ return value
51
+
52
+
53
+ def _write_json(path: Path, value: object) -> None:
54
+ path.parent.mkdir(parents=True, exist_ok=True)
55
+ path.write_text(
56
+ json.dumps(value, ensure_ascii=False, sort_keys=True, indent=2) + "\n",
57
+ encoding="utf-8",
58
+ )
59
+
60
+
61
+ def _digest(path: Path) -> str:
62
+ return hashlib.sha256(path.read_bytes()).hexdigest()
63
+
64
+
65
+ def _canonical_object_digest(value: dict[str, Any]) -> str:
66
+ raw = json.dumps(
67
+ value,
68
+ ensure_ascii=False,
69
+ sort_keys=True,
70
+ separators=(",", ":"),
71
+ ).encode("utf-8")
72
+ return hashlib.sha256(raw).hexdigest()
73
+
74
+
75
+ def _replace(path: Path, old: str, new: str) -> None:
76
+ text = path.read_text(encoding="utf-8")
77
+ assert old in text
78
+ path.write_text(text.replace(old, new, 1), encoding="utf-8")
79
+
80
+
81
+ def _sync_v2_rubric(root: Path, monkeypatch: pytest.MonkeyPatch) -> None:
82
+ """Re-pin a deliberate rubric mutation so semantic guards are exercised."""
83
+ rubric = root / SUITE / "adjudication_rubric_v2.md"
84
+ digest = _digest(rubric)
85
+ monkeypatch.setattr(guard, "V2_RUBRIC_SHA256", digest)
86
+ ledger_path = root / SUITE / "rubric_amendments.json"
87
+ ledger = _read_json(ledger_path)
88
+ ledger["rubrics"][1]["sha256"] = digest
89
+ ledger["amendments"][0]["to_sha256"] = digest
90
+ _write_json(ledger_path, ledger)
91
+
92
+
93
+ def _sync_subject_schema(root: Path, monkeypatch: pytest.MonkeyPatch) -> None:
94
+ schema_path = root / SUITE / "subject_context_record.schema.json"
95
+ monkeypatch.setattr(guard, "SUBJECT_SCHEMA_SHA256", _digest(schema_path))
96
+
97
+
98
+ def _schema() -> dict[str, Any]:
99
+ return _read_json(REPO_ROOT / SUITE / "subject_context_record.schema.json")
100
+
101
+
102
+ def _fixture(name: str) -> dict[str, Any]:
103
+ return _read_json(REPO_ROOT / FIXTURES / name)
104
+
105
+
106
+ def test_current_repository_passes_all_679_guards() -> None:
107
+ assert guard.run_checks(REPO_ROOT) == [
108
+ "historical bytes/tree and no-new-measurement boundary",
109
+ "v2 rubric and closed amendment ledger",
110
+ "subject-context/launcher/call-plan schemas and four synthetic fixtures",
111
+ "README/design prospective protocol",
112
+ "prospective heldout-measurement/1.1 context replay",
113
+ ]
114
+
115
+
116
+ def test_unmutated_minimal_mirror_passes(tmp_path: Path) -> None:
117
+ assert len(guard.run_checks(_mirror(tmp_path))) == 5
118
+
119
+
120
+ def test_protected_historical_file_byte_drift_fails(tmp_path: Path) -> None:
121
+ root = _mirror(tmp_path)
122
+ path = root / SUITE / "heldout_set.json"
123
+ path.write_bytes(path.read_bytes() + b"\n")
124
+ with pytest.raises(guard.ContractError, match="protected historical byte drift"):
125
+ guard.run_checks(root)
126
+
127
+
128
+ @pytest.mark.parametrize("mutation", ["add", "delete", "byte_drift"])
129
+ def test_historical_run_tree_inventory_is_write_once(
130
+ tmp_path: Path, mutation: str
131
+ ) -> None:
132
+ root = _mirror(tmp_path)
133
+ tree = root / guard.HISTORICAL_TREE_REL
134
+ files = sorted(path for path in tree.rglob("*") if path.is_file())
135
+ assert files
136
+ if mutation == "add":
137
+ (tree / "unauthorized-addition.txt").write_text("drift\n", encoding="utf-8")
138
+ elif mutation == "delete":
139
+ files[0].unlink()
140
+ else:
141
+ files[0].write_bytes(files[0].read_bytes() + b"\n")
142
+ with pytest.raises(guard.ContractError, match="protected historical run-tree drift"):
143
+ guard.run_checks(root)
144
+
145
+
146
+ def test_679_cannot_create_a_measurement_row(tmp_path: Path) -> None:
147
+ root = _mirror(tmp_path)
148
+ _write_json(root / SUITE / "measurement-2099-01-01.json", {})
149
+ with pytest.raises(guard.ContractError, match="creates no measurement row"):
150
+ guard.run_checks(root)
151
+
152
+
153
+ def test_v2_rubric_hash_is_load_bearing(tmp_path: Path) -> None:
154
+ root = _mirror(tmp_path)
155
+ rubric = root / SUITE / "adjudication_rubric_v2.md"
156
+ rubric.write_text(rubric.read_text(encoding="utf-8") + "\n", encoding="utf-8")
157
+ with pytest.raises(guard.ContractError, match="rubric byte identity"):
158
+ guard._check_rubric(root)
159
+
160
+
161
+ @pytest.mark.parametrize("mutation", ["c9_authority", "canonical_anchor", "ladder_copy"])
162
+ def test_v2_rubric_semantics_survive_rehashing_attacks(
163
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch, mutation: str
164
+ ) -> None:
165
+ root = _mirror(tmp_path)
166
+ rubric = root / SUITE / "adjudication_rubric_v2.md"
167
+ if mutation == "c9_authority":
168
+ _replace(
169
+ rubric,
170
+ "### C9 — Non-control citation-attachment violation",
171
+ "### C9 — Citation-token conservation",
172
+ )
173
+ expected = "C9 title/authority drift"
174
+ elif mutation == "canonical_anchor":
175
+ _replace(
176
+ rubric,
177
+ "#what-counts-as-a-move-and-what-does-not",
178
+ "#unfrozen-local-summary",
179
+ )
180
+ expected = "missing or duplicates frozen marker"
181
+ else:
182
+ rubric.write_text(
183
+ rubric.read_text(encoding="utf-8") + "\nhedged → asserted\n",
184
+ encoding="utf-8",
185
+ )
186
+ expected = "must point to, not copy"
187
+ _sync_v2_rubric(root, monkeypatch)
188
+ with pytest.raises(guard.ContractError, match=expected):
189
+ guard._check_rubric(root)
190
+
191
+
192
+ def test_closed_amendment_ledger_rejects_mutation(tmp_path: Path) -> None:
193
+ root = _mirror(tmp_path)
194
+ path = root / SUITE / "rubric_amendments.json"
195
+ ledger = _read_json(path)
196
+ ledger["amendments"][0]["historical_effect"] = "rescore"
197
+ _write_json(path, ledger)
198
+ with pytest.raises(guard.ContractError, match="closed amendment"):
199
+ guard._check_rubric(root)
200
+
201
+
202
+ @pytest.mark.parametrize(
203
+ "payload",
204
+ [
205
+ '{"schema_version":"x","schema_version":"y"}',
206
+ '{"schema_version":"x","score":NaN}',
207
+ '\ufeff{"schema_version":"x"}',
208
+ ],
209
+ ids=["duplicate-key", "nonfinite", "utf8-bom"],
210
+ )
211
+ def test_new_contract_json_is_parsed_strictly(
212
+ tmp_path: Path, payload: str
213
+ ) -> None:
214
+ root = _mirror(tmp_path)
215
+ (root / SUITE / "historical_artifacts.lock.json").write_text(
216
+ payload, encoding="utf-8"
217
+ )
218
+ with pytest.raises(guard.ContractError, match="duplicate JSON key|non-finite|strict JSON"):
219
+ guard.run_checks(root)
220
+
221
+
222
+ def test_subject_context_schema_hash_is_load_bearing(tmp_path: Path) -> None:
223
+ root = _mirror(tmp_path)
224
+ path = root / SUITE / "subject_context_record.schema.json"
225
+ path.write_text(path.read_text(encoding="utf-8") + "\n", encoding="utf-8")
226
+ with pytest.raises(guard.ContractError, match="schema byte identity"):
227
+ guard._check_subject_assets(root)
228
+
229
+
230
+ @pytest.mark.parametrize(
231
+ ("fixture_name", "container"),
232
+ [
233
+ ("subject_context_machine_supported.json", "execution_manifest"),
234
+ ("subject_context_machine_supported.json", "neutral_cwd"),
235
+ ("subject_context_machine_supported.json", "cli"),
236
+ ("subject_context_machine_supported.json", "instruction_visibility"),
237
+ ("subject_context_machine_supported.json", "context_probe"),
238
+ ("subject_context_machine_supported.json", "data_minimization"),
239
+ ("subject_context_attested_only.json", "attestation"),
240
+ ],
241
+ )
242
+ def test_subject_context_nested_branches_are_closed(
243
+ fixture_name: str, container: str
244
+ ) -> None:
245
+ record = _fixture(fixture_name)
246
+ assert isinstance(record[container], dict)
247
+ record[container]["raw_secret"] = "must-not-be-stored"
248
+ with pytest.raises(guard.ContractError):
249
+ guard.validate_subject_context(record, _schema())
250
+
251
+
252
+ @pytest.mark.parametrize("mutation", ["add", "delete", "byte_drift"])
253
+ def test_fixture_inventory_and_bytes_are_frozen(
254
+ tmp_path: Path, mutation: str
255
+ ) -> None:
256
+ root = _mirror(tmp_path)
257
+ fixture_dir = root / FIXTURES
258
+ if mutation == "add":
259
+ _write_json(fixture_dir / "extra.json", {})
260
+ expected = "fixture inventory drift"
261
+ elif mutation == "delete":
262
+ (fixture_dir / "subject_context_unknown.json").unlink()
263
+ expected = "fixture inventory drift"
264
+ else:
265
+ path = fixture_dir / "subject_context_unknown.json"
266
+ path.write_bytes(path.read_bytes() + b"\n")
267
+ expected = "fixture byte drift"
268
+ with pytest.raises(guard.ContractError, match=expected):
269
+ guard._check_subject_assets(root)
270
+
271
+
272
+ @pytest.mark.parametrize("relation", ["inside_repository", "repository_visible"])
273
+ def test_derived_not_isolated_relations_are_load_bearing(
274
+ tmp_path: Path,
275
+ monkeypatch: pytest.MonkeyPatch,
276
+ relation: str,
277
+ ) -> None:
278
+ root = _mirror(tmp_path)
279
+ path = root / SUITE / "subject_context_record.schema.json"
280
+ schema = _read_json(path)
281
+ branches = schema["$defs"]["notIsolatedRecord"]["anyOf"]
282
+ if relation == "inside_repository":
283
+ branches[2]["properties"]["neutral_cwd"]["properties"][
284
+ "repo_membership_probe"
285
+ ]["const"] = "outside_suite_repository"
286
+ expected = "derived inside-repository record"
287
+ else:
288
+ branches[1]["properties"]["instruction_visibility"]["properties"][
289
+ "repository_instructions"
290
+ ]["const"] = "not_detected"
291
+ expected = "derived repository-visible record"
292
+ _write_json(path, schema)
293
+ _sync_subject_schema(root, monkeypatch)
294
+ with pytest.raises(guard.ContractError, match=expected):
295
+ guard._check_subject_assets(root)
296
+
297
+
298
+ @pytest.mark.parametrize("surface", ["README", "design"])
299
+ def test_protocol_document_markers_are_load_bearing(
300
+ tmp_path: Path, surface: str
301
+ ) -> None:
302
+ root = _mirror(tmp_path)
303
+ if surface == "README":
304
+ path = root / SUITE / "README.md"
305
+ _replace(path, "negative probe is evidence, not proof", "negative probe proves isolation")
306
+ expected = "README missing"
307
+ else:
308
+ path = root / DESIGN
309
+ _replace(path, "DESIGN-FROZEN / PROSPECTIVE-ONLY", "DRAFT")
310
+ expected = "design missing"
311
+ with pytest.raises(guard.ContractError, match=expected):
312
+ guard._check_docs(root)
313
+
314
+
315
+ @pytest.mark.parametrize(
316
+ "relative",
317
+ [
318
+ "runs/future-window/hidden-row.json",
319
+ "future-contract-record.JSON",
320
+ "archive/nonstandard-name.json",
321
+ ],
322
+ )
323
+ def test_contract_row_discovery_is_recursive_and_filename_independent(
324
+ tmp_path: Path, relative: str
325
+ ) -> None:
326
+ root = _mirror(tmp_path)
327
+ _write_json(
328
+ root / SUITE / relative,
329
+ {
330
+ "measurement_contract": "heldout-measurement/1.1",
331
+ "suite": "revision_claim_drift",
332
+ },
333
+ )
334
+ with pytest.raises(guard.ContractError, match="contract-marked measurement row"):
335
+ guard._check_history(root)
336
+
337
+
338
+ def test_escaped_contract_marker_is_discovered(tmp_path: Path) -> None:
339
+ root = _mirror(tmp_path)
340
+ path = root / SUITE / "runs/future-window/escaped.json"
341
+ path.parent.mkdir(parents=True, exist_ok=True)
342
+ path.write_text(
343
+ '{"measurement\\u005fcontract":"heldout-measurement/1.1",'
344
+ '"suite":"revision_claim_drift"}\n',
345
+ encoding="utf-8",
346
+ )
347
+ with pytest.raises(guard.ContractError, match="contract-marked measurement row"):
348
+ guard._check_history(root)
349
+
350
+
351
+ @pytest.mark.parametrize("mutation", ["delete", "hash"])
352
+ def test_canonical_claim_ladder_target_is_required(
353
+ tmp_path: Path, mutation: str
354
+ ) -> None:
355
+ root = _mirror(tmp_path)
356
+ ladder = root / LADDER
357
+ if mutation == "delete":
358
+ ladder.unlink()
359
+ expected = "canonical claim-strength ladder: missing"
360
+ else:
361
+ ladder.write_bytes(ladder.read_bytes() + b"\n")
362
+ expected = "ladder target hash drifted"
363
+ with pytest.raises(guard.ContractError, match=expected):
364
+ guard._check_rubric(root)
365
+
366
+
367
+ def test_canonical_claim_ladder_headings_are_load_bearing(
368
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
369
+ ) -> None:
370
+ root = _mirror(tmp_path)
371
+ ladder = root / LADDER
372
+ _replace(ladder, "## The ladder", "## Local ladder summary")
373
+ old_hash = guard.CLAIM_LADDER_SHA256
374
+ new_hash = _digest(ladder)
375
+ monkeypatch.setattr(guard, "CLAIM_LADDER_SHA256", new_hash)
376
+ rubric = root / SUITE / "adjudication_rubric_v2.md"
377
+ _replace(rubric, old_hash, new_hash)
378
+ _sync_v2_rubric(root, monkeypatch)
379
+ with pytest.raises(guard.ContractError, match="ladder target headings drifted"):
380
+ guard._check_rubric(root)
381
+
382
+
383
+
384
+
385
+ def _future_bundle(
386
+ tmp_path: Path, status: str = "machine_supported"
387
+ ) -> tuple[Path, dict[str, Any], Path, Path]:
388
+ """Create a fully joined synthetic future row without executing an eval."""
389
+ root = tmp_path / f"future-{status}"
390
+ for relative in (
391
+ MEASUREMENT_SCHEMA,
392
+ EXECUTION_SCHEMA,
393
+ SUITE / "subject_context_record.schema.json",
394
+ LAUNCHER_SCHEMA,
395
+ CALL_PLAN_SCHEMA,
396
+ SUITE / "heldout_set.json",
397
+ ):
398
+ _copy_file(root, relative)
399
+
400
+ run_id = "future-ni" if status == "not_isolated" else f"future-{status.replace('_', '-')}"
401
+ commit = "a" * 40
402
+ subject_model_id = "synthetic-subject/not-executed"
403
+ run_rel = SUITE / "runs" / run_id
404
+ context_ref = (run_rel / "subject-context.json").as_posix()
405
+ launcher_ref = (run_rel / "launcher-config.json").as_posix()
406
+ plan_ref = (run_rel / "subject-call-plan.json").as_posix()
407
+ manifest_ref = (run_rel / "execution-manifest.json").as_posix()
408
+ context_path = root / context_ref
409
+ launcher_path = root / launcher_ref
410
+ plan_path = root / plan_ref
411
+ manifest_path = root / manifest_ref
412
+
413
+ fixture_by_status = {
414
+ "machine_supported": "subject_context_machine_supported.json",
415
+ "attested_only": "subject_context_attested_only.json",
416
+ "not_isolated": "subject_context_not_isolated.json",
417
+ "unknown": "subject_context_unknown.json",
418
+ }
419
+ context = _fixture(fixture_by_status[status])
420
+ context["run_id"] = run_id
421
+ context["suite_commit"] = commit
422
+ context["execution_manifest"]["ref"] = manifest_ref
423
+ context["recorded_at"] = "2026-08-10T01:00:04Z"
424
+ if context["context_probe"]["status"] != "not_run":
425
+ context["context_probe"]["started_at"] = "2026-08-10T01:00:00Z"
426
+ context["context_probe"]["completed_at"] = "2026-08-10T01:00:02Z"
427
+ if context["attestation"] is not None:
428
+ context["attestation"]["attested_at"] = "2026-08-10T01:00:03Z"
429
+
430
+ policy_by_membership = {
431
+ "outside_suite_repository": "fresh_outside_suite_repository",
432
+ "inside_suite_repository": "inside_suite_repository",
433
+ "unresolved": "unresolved",
434
+ }
435
+ launcher = {
436
+ "schema_version": "revision-claim-drift-launcher-config/1.0",
437
+ "suite": "revision_claim_drift",
438
+ "run_id": run_id,
439
+ "sealed_at": "2026-08-10T00:59:40Z",
440
+ "applies_to": ["context_probe", "subject_fleet"],
441
+ "launcher": {
442
+ "client_id": "synthetic-cli",
443
+ "client_version": "0.0-test",
444
+ "mode": context["cli"]["mode"],
445
+ "bare_requested": context["cli"]["bare_requested"],
446
+ "bare_used": context["cli"]["bare_used"],
447
+ "authentication_result": context["cli"]["authentication_result"],
448
+ },
449
+ "working_directory": {
450
+ "policy": policy_by_membership[
451
+ context["neutral_cwd"]["repo_membership_probe"]
452
+ ],
453
+ "pwd_p_sha256": context["neutral_cwd"]["pwd_p_sha256"],
454
+ },
455
+ "instruction_loading": {
456
+ "repository_instructions": "disabled",
457
+ "global_instructions": "enabled",
458
+ },
459
+ "invocation_sha256": "0" * 64,
460
+ "data_minimization": {
461
+ "raw_command_stored": False,
462
+ "raw_environment_stored": False,
463
+ "raw_physical_cwd_stored": False,
464
+ "raw_instruction_content_stored": False,
465
+ },
466
+ }
467
+ launcher["invocation_sha256"] = _canonical_object_digest(
468
+ {
469
+ key: launcher[key]
470
+ for key in ("launcher", "working_directory", "instruction_loading")
471
+ }
472
+ )
473
+ _write_json(launcher_path, launcher)
474
+ launcher_binding = {"ref": launcher_ref, "sha256": _digest(launcher_path)}
475
+ context["cli"]["launcher_config"] = copy.deepcopy(launcher_binding)
476
+
477
+ item_ids = [f"rp-{index:02d}" for index in range(1, 9)]
478
+ control_ids = {"rp-07", "rp-08"}
479
+ subject_specs = [
480
+ {
481
+ "item_id": item_id,
482
+ "item_replicate_id": f"{item_id}.single.r{replicate_index}",
483
+ "replicate_index": replicate_index,
484
+ "arm_id": "single",
485
+ "control_item": item_id in control_ids,
486
+ }
487
+ for item_id in item_ids
488
+ for replicate_index in (1, 2)
489
+ ]
490
+ judge_specs = [
491
+ {
492
+ "judge_id": judge_id,
493
+ "model_id": f"{judge_id}/not-executed",
494
+ "model_family": judge_id,
495
+ "blinded_to": ["arm_identity", "control_status", "mechanism_state"],
496
+ }
497
+ for judge_id in ("judge-a", "judge-b")
498
+ ]
499
+ call_specs = [
500
+ {
501
+ **subject,
502
+ "call_id": f"subject.{subject['item_replicate_id']}",
503
+ "role": "subject",
504
+ "judge_id": None,
505
+ }
506
+ for subject in subject_specs
507
+ ] + [
508
+ {
509
+ **subject,
510
+ "call_id": f"judge.{judge_id}.{subject['item_replicate_id']}",
511
+ "role": "judge",
512
+ "judge_id": judge_id,
513
+ }
514
+ for judge_id in ("judge-a", "judge-b")
515
+ for subject in subject_specs
516
+ ]
517
+ planned_calls: list[dict[str, Any]] = []
518
+ raw_paths = [context_ref, launcher_ref, plan_ref, manifest_ref]
519
+ plan_judges: list[dict[str, Any]] = []
520
+ for judge in judge_specs:
521
+ template_ref = (
522
+ run_rel / "raw" / f"judge.{judge['judge_id']}.template.txt"
523
+ ).as_posix()
524
+ template_path = root / template_ref
525
+ template_path.parent.mkdir(parents=True, exist_ok=True)
526
+ template_path.write_text(
527
+ f"synthetic frozen template for {judge['judge_id']}\n",
528
+ encoding="utf-8",
529
+ )
530
+ raw_paths.append(template_ref)
531
+ plan_judges.append(
532
+ {
533
+ **judge,
534
+ "prompt_template": {
535
+ "ref": template_ref,
536
+ "sha256": _digest(template_path),
537
+ },
538
+ }
539
+ )
540
+ output_hashes: list[str] = []
541
+ prompt_hashes: list[str] = []
542
+ judge_plan_by_id = {judge["judge_id"]: judge for judge in plan_judges}
543
+ for index, spec in enumerate(call_specs, start=1):
544
+ call_id = spec["call_id"]
545
+ role = spec["role"]
546
+ prompt_ref = (run_rel / "raw" / f"{call_id}.prompt.txt").as_posix()
547
+ output_ref = (run_rel / "raw" / f"{call_id}.output.txt").as_posix()
548
+ prompt_path = root / prompt_ref
549
+ output_path = root / output_ref
550
+ prompt_path.parent.mkdir(parents=True, exist_ok=True)
551
+ if role == "subject":
552
+ prompt_path.write_text(
553
+ f"synthetic {role} prompt {index}\n", encoding="utf-8"
554
+ )
555
+ prompt_binding: dict[str, Any] = {
556
+ "ref": prompt_ref,
557
+ "sha256": _digest(prompt_path),
558
+ }
559
+ else:
560
+ plan_judge = judge_plan_by_id[spec["judge_id"]]
561
+ template_ref = plan_judge["prompt_template"]["ref"]
562
+ subject_output_ref = (
563
+ run_rel
564
+ / "raw"
565
+ / f"subject.{spec['item_replicate_id']}.output.txt"
566
+ ).as_posix()
567
+ subject_prompt_ref = (
568
+ run_rel
569
+ / "raw"
570
+ / f"subject.{spec['item_replicate_id']}.prompt.txt"
571
+ ).as_posix()
572
+ prompt_path.write_bytes(
573
+ (root / template_ref).read_bytes()
574
+ + guard.JUDGE_SUBJECT_INPUT_SEPARATOR
575
+ + (root / subject_prompt_ref).read_bytes()
576
+ + guard.JUDGE_SUBJECT_OUTPUT_SEPARATOR
577
+ + (root / subject_output_ref).read_bytes()
578
+ )
579
+ prompt_binding = {
580
+ "ref": prompt_ref,
581
+ "sha256": None,
582
+ "composition": "template_then_subject_input_then_subject_output/1.0",
583
+ "template_ref": template_ref,
584
+ "subject_prompt_ref": subject_prompt_ref,
585
+ "subject_output_ref": subject_output_ref,
586
+ }
587
+ output_path.write_text(f"synthetic {role} output {index}\n", encoding="utf-8")
588
+ raw_paths.extend((prompt_ref, output_ref))
589
+ prompt_hashes.append(_digest(prompt_path))
590
+ output_hashes.append(_digest(output_path))
591
+ planned_calls.append(
592
+ {
593
+ "call_id": call_id,
594
+ "sequence_index": index,
595
+ "role": role,
596
+ "judge_id": spec["judge_id"],
597
+ "item_id": spec["item_id"],
598
+ "item_replicate_id": spec["item_replicate_id"],
599
+ "replicate_index": spec["replicate_index"],
600
+ "arm_id": spec["arm_id"],
601
+ "control_item": spec["control_item"],
602
+ "prompt": prompt_binding,
603
+ "output_ref": output_ref,
604
+ }
605
+ )
606
+
607
+ plan = {
608
+ "schema_version": "revision-claim-drift-subject-call-plan/1.0",
609
+ "suite": "revision_claim_drift",
610
+ "run_id": run_id,
611
+ "suite_commit": commit,
612
+ "subject_model_id": subject_model_id,
613
+ "created_at": "2026-08-10T00:59:50Z",
614
+ "launcher_config": copy.deepcopy(launcher_binding),
615
+ "heldout_set": {
616
+ "ref": f"{guard.SUITE_REL}/heldout_set.json",
617
+ "sha256": guard.HISTORICAL_FILES[
618
+ f"{guard.SUITE_REL}/heldout_set.json"
619
+ ],
620
+ },
621
+ "arm_ids": ["single"],
622
+ "judges": plan_judges,
623
+ "calls": planned_calls,
624
+ "data_minimization": {
625
+ "prompt_content_embedded": False,
626
+ "output_content_embedded": False,
627
+ },
628
+ }
629
+ _write_json(plan_path, plan)
630
+ plan_binding = {"ref": plan_ref, "sha256": _digest(plan_path)}
631
+ context["subject_call_plan"] = copy.deepcopy(plan_binding)
632
+ _write_json(context_path, context)
633
+
634
+ timings = [
635
+ (
636
+ f"2026-08-10T01:01:{index:02d}.000Z",
637
+ f"2026-08-10T01:01:{index:02d}.100Z",
638
+ )
639
+ for index in range(1, len(planned_calls) + 1)
640
+ ]
641
+ manifest_calls = []
642
+ for planned, prompt_hash, output_hash, (started, completed) in zip(
643
+ planned_calls, prompt_hashes, output_hashes, timings, strict=True
644
+ ):
645
+ manifest_calls.append(
646
+ {
647
+ "call_id": planned["call_id"],
648
+ "sequence_index": planned["sequence_index"],
649
+ "started_at": started,
650
+ "completed_at": completed,
651
+ "prompt_sha256": prompt_hash,
652
+ "output_sha256": output_hash,
653
+ "attempt": 1,
654
+ "concurrency_group": None,
655
+ }
656
+ )
657
+ manifest = {
658
+ "schema_version": "heldout-execution-manifest/1.0",
659
+ "suite": "revision_claim_drift",
660
+ "created_at": "2026-08-10T01:02:01Z",
661
+ "write_once": True,
662
+ "execution_window": {
663
+ "window_id": run_id,
664
+ "started_at": "2026-08-10T01:01:00Z",
665
+ "completed_at": "2026-08-10T01:01:59Z",
666
+ },
667
+ "calls": manifest_calls,
668
+ }
669
+ _write_json(manifest_path, manifest)
670
+
671
+ row: dict[str, Any] = {
672
+ "measurement_contract": "heldout-measurement/1.1",
673
+ "suite": "revision_claim_drift",
674
+ "suite_class": "llm_judged",
675
+ "measurement_date": "2026-08-10",
676
+ "decision_relevant": True,
677
+ "subject": {
678
+ "model_id": subject_model_id,
679
+ "config": {
680
+ "suite_commit": commit,
681
+ "subject_context": {
682
+ "ref": context_ref,
683
+ "sha256": _digest(context_path),
684
+ "status": status,
685
+ },
686
+ "launcher_config": copy.deepcopy(launcher_binding),
687
+ "subject_call_plan": copy.deepcopy(plan_binding),
688
+ },
689
+ },
690
+ "judge_plan": {"exception": "none"},
691
+ "judges": [],
692
+ "aggregate": {
693
+ "headline": {
694
+ "metric_name": "claim_strength_hedge_drift_rate",
695
+ "value": 0,
696
+ "construction_rule": (
697
+ "Confirmed C1/C2 item-replicate flags divided by evaluated "
698
+ "item-replicates; flags-only adjudication makes this a lower bound."
699
+ ),
700
+ "estimand_status": "lower_bound",
701
+ },
702
+ "agreement": {
703
+ "rate": 1.0,
704
+ "divergent_items": [],
705
+ "note": "Two synthetic fixture judges agree; no calls were made.",
706
+ },
707
+ },
708
+ "replicates": {
709
+ "per_item": 2,
710
+ "rule_ref": "prospective-only",
711
+ "spread": None,
712
+ },
713
+ "adjudication": {
714
+ "applies": True,
715
+ "rubric_ref": f"{guard.SUITE_REL}/adjudication_rubric_v2.md",
716
+ "rubric_sha256": guard.V2_RUBRIC_SHA256,
717
+ "rubric_precommitted": True,
718
+ "blinded_to": [],
719
+ "overrides": [],
720
+ "raw_published": True,
721
+ "resolution_direction": "flags_only",
722
+ "resolution_rule_ref": "adjudication_rubric_v2.md#resolution",
723
+ },
724
+ "attempts": {
725
+ "atomicity": "Synthetic fixture only; no dispatch occurred.",
726
+ "partial_published": False,
727
+ "blocked_runs": [],
728
+ },
729
+ "raw_outputs": {"retained": True, "paths": raw_paths},
730
+ "preregistration": {
731
+ "plan_ref": plan_binding["ref"],
732
+ "plan_sha256": plan_binding["sha256"],
733
+ "rubric_ref": f"{guard.SUITE_REL}/adjudication_rubric_v2.md",
734
+ "rubric_sha256": guard.V2_RUBRIC_SHA256,
735
+ "frozen_commit": commit,
736
+ "frozen_before_dispatch": True,
737
+ "rubric_and_plan_frozen_together": True,
738
+ "judge_template_version": "synthetic-v1",
739
+ "amendments_append_only": True,
740
+ "amendments": [],
741
+ },
742
+ "execution_manifest": {
743
+ "ref": manifest_ref,
744
+ "sha256": _digest(manifest_path),
745
+ "write_once": True,
746
+ "claims": ["same_window", "ordering"],
747
+ },
748
+ "results": {
749
+ "design": "prospective synthetic contract replay",
750
+ "arm_roles": {
751
+ "treatment_or_cohort_arms": ["single"],
752
+ "variant_packet_arms": [],
753
+ },
754
+ "revision_claim_drift_v2": {
755
+ "rubric_version": "2.0",
756
+ "claim_strength_headline_criteria": ["C1", "C2"],
757
+ "deterministic_token_criterion": "C6",
758
+ "arm_ids": ["single"],
759
+ "citation_attachment": {
760
+ "criterion": "C9",
761
+ "scope": "all_items_including_non_controls",
762
+ "reported_separately": True,
763
+ "evaluated_item_replicates": sorted(
764
+ subject["item_replicate_id"] for subject in subject_specs
765
+ ),
766
+ "control_item_replicates": sorted(
767
+ subject["item_replicate_id"]
768
+ for subject in subject_specs
769
+ if subject["control_item"]
770
+ ),
771
+ "finding_count": 0,
772
+ "decisions": [],
773
+ "findings": [],
774
+ },
775
+ },
776
+ "subject_context_claim": guard.STATUS_CLAIMS[status],
777
+ },
778
+ "verdict": "Synthetic prospective row; no result was measured.",
779
+ "caveats": [
780
+ "Flags-only adjudication means any headline is a lower bound; this "
781
+ "prospective synthetic replay measured no result."
782
+ ],
783
+ }
784
+ for plan_judge in plan_judges:
785
+ row["judges"].append(
786
+ {
787
+ "judge_id": plan_judge["judge_id"],
788
+ "model_id": plan_judge["model_id"],
789
+ "model_family": plan_judge["model_family"],
790
+ "prompt_ref": plan_judge["prompt_template"]["ref"],
791
+ "evidence_provided": "synthetic contract fixture only",
792
+ "judging_budget": "zero live calls; fixture replay only",
793
+ "blinded_to": plan_judge["blinded_to"],
794
+ "per_item": [
795
+ {
796
+ "item_id": subject["item_replicate_id"],
797
+ "flag": False,
798
+ "citation_attachment": {"criterion": "C9", "flag": False},
799
+ }
800
+ for subject in subject_specs
801
+ ],
802
+ }
803
+ )
804
+ return root, row, context_path, manifest_path
805
+
806
+
807
+ def _sync_context(row: dict[str, Any], context_path: Path) -> None:
808
+ row["subject"]["config"]["subject_context"]["sha256"] = _digest(context_path)
809
+
810
+
811
+ def _sync_manifest(row: dict[str, Any], manifest_path: Path) -> None:
812
+ row["execution_manifest"]["sha256"] = _digest(manifest_path)
813
+
814
+
815
+ def _bound_path(root: Path, row: dict[str, Any], key: str) -> Path:
816
+ return root / row["subject"]["config"][key]["ref"]
817
+
818
+
819
+ def _rewrite_plan(root: Path, row: dict[str, Any], plan: dict[str, Any]) -> Path:
820
+ plan_path = _bound_path(root, row, "subject_call_plan")
821
+ _write_json(plan_path, plan)
822
+ digest = _digest(plan_path)
823
+ row["subject"]["config"]["subject_call_plan"]["sha256"] = digest
824
+ row["preregistration"]["plan_ref"] = row["subject"]["config"][
825
+ "subject_call_plan"
826
+ ]["ref"]
827
+ row["preregistration"]["plan_sha256"] = digest
828
+ context_path = root / row["subject"]["config"]["subject_context"]["ref"]
829
+ context = _read_json(context_path)
830
+ context["subject_call_plan"]["sha256"] = digest
831
+ _write_json(context_path, context)
832
+ _sync_context(row, context_path)
833
+ return plan_path
834
+
835
+
836
+ def _rewrite_launcher(
837
+ root: Path, row: dict[str, Any], launcher: dict[str, Any]
838
+ ) -> Path:
839
+ launcher_path = _bound_path(root, row, "launcher_config")
840
+ _write_json(launcher_path, launcher)
841
+ binding = {
842
+ "ref": row["subject"]["config"]["launcher_config"]["ref"],
843
+ "sha256": _digest(launcher_path),
844
+ }
845
+ row["subject"]["config"]["launcher_config"] = copy.deepcopy(binding)
846
+
847
+ plan_path = _bound_path(root, row, "subject_call_plan")
848
+ plan = _read_json(plan_path)
849
+ plan["launcher_config"] = copy.deepcopy(binding)
850
+ _write_json(plan_path, plan)
851
+ plan_digest = _digest(plan_path)
852
+ row["subject"]["config"]["subject_call_plan"]["sha256"] = plan_digest
853
+ row["preregistration"]["plan_ref"] = row["subject"]["config"][
854
+ "subject_call_plan"
855
+ ]["ref"]
856
+ row["preregistration"]["plan_sha256"] = plan_digest
857
+
858
+ context_path = root / row["subject"]["config"]["subject_context"]["ref"]
859
+ context = _read_json(context_path)
860
+ context["cli"]["launcher_config"] = copy.deepcopy(binding)
861
+ context["subject_call_plan"]["sha256"] = plan_digest
862
+ _write_json(context_path, context)
863
+ _sync_context(row, context_path)
864
+ return launcher_path
865
+
866
+
867
+ def _add_c9_finding(root: Path, row: dict[str, Any]) -> Path:
868
+ run_prefix = Path(row["subject"]["config"]["subject_context"]["ref"]).parent
869
+ finding_id = "C9-F-001"
870
+ item_replicate_id = "rp-01.single.r1"
871
+ evidence_ref = (run_prefix / "c9" / f"{finding_id}.json").as_posix()
872
+ evidence_path = root / evidence_ref
873
+ attachment_contents = {
874
+ "citation_tokens": "[Smith, 2024]\n",
875
+ "original_attachment": "Original proposition <- [Smith, 2024]\n",
876
+ "revised_attachment": "Different proposition <- [Smith, 2024]\n",
877
+ }
878
+ attachment_suffixes = {
879
+ "citation_tokens": "citation-tokens.txt",
880
+ "original_attachment": "original-attachment.txt",
881
+ "revised_attachment": "revised-attachment.txt",
882
+ }
883
+ bindings: dict[str, dict[str, str]] = {}
884
+ for field, content in attachment_contents.items():
885
+ ref = (run_prefix / "c9" / f"{finding_id}.{attachment_suffixes[field]}").as_posix()
886
+ path = root / ref
887
+ path.parent.mkdir(parents=True, exist_ok=True)
888
+ path.write_text(content, encoding="utf-8")
889
+ bindings[field] = {"ref": ref, "sha256": _digest(path)}
890
+ _write_json(
891
+ evidence_path,
892
+ {
893
+ "schema_version": "revision-claim-drift-c9-evidence/1.0",
894
+ "suite": "revision_claim_drift",
895
+ "run_id": run_prefix.name,
896
+ "finding_id": finding_id,
897
+ "item_replicate_id": item_replicate_id,
898
+ "criterion": "C9",
899
+ "raw_flags": [{"judge_id": "judge-a", "criterion": "C9", "flag": True}],
900
+ "adjudication": {
901
+ "disposition": "confirmed",
902
+ "authorization": "unauthorized_under_C3",
903
+ },
904
+ "citation_tokens": bindings["citation_tokens"],
905
+ "original_attachment": bindings["original_attachment"],
906
+ "revised_attachment": bindings["revised_attachment"],
907
+ "data_minimization": {"raw_rationale_stored": False},
908
+ },
909
+ )
910
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
911
+ layer["finding_count"] = 1
912
+ layer["decisions"] = [
913
+ {
914
+ "decision_id": f"c9d.judge-a.{item_replicate_id}",
915
+ "judge_id": "judge-a",
916
+ "item_replicate_id": item_replicate_id,
917
+ "raw_flag": True,
918
+ "disposition": "confirmed",
919
+ "criterion_ref": "C9",
920
+ "reason_code": "violation_confirmed",
921
+ "finding_id": finding_id,
922
+ }
923
+ ]
924
+ layer["findings"] = [
925
+ {
926
+ "finding_id": finding_id,
927
+ "item_replicate_id": item_replicate_id,
928
+ "criterion": "C9",
929
+ "authorization": "unauthorized_under_C3",
930
+ "citation_tokens_ref": bindings["citation_tokens"]["ref"],
931
+ "citation_tokens_sha256": bindings["citation_tokens"]["sha256"],
932
+ "original_attachment_ref": bindings["original_attachment"]["ref"],
933
+ "original_attachment_sha256": bindings["original_attachment"]["sha256"],
934
+ "revised_attachment_ref": bindings["revised_attachment"]["ref"],
935
+ "revised_attachment_sha256": bindings["revised_attachment"]["sha256"],
936
+ "evidence_ref": evidence_ref,
937
+ "evidence_sha256": _digest(evidence_path),
938
+ "raw_flag_judge_ids": ["judge-a"],
939
+ "adjudication_disposition": "confirmed",
940
+ }
941
+ ]
942
+ row["judges"][0]["per_item"][0]["citation_attachment"]["flag"] = True
943
+ row["raw_outputs"]["paths"].extend(
944
+ [binding["ref"] for binding in bindings.values()] + [evidence_ref]
945
+ )
946
+ return evidence_path
947
+
948
+
949
+ @pytest.mark.parametrize(
950
+ "status", ["machine_supported", "attested_only", "not_isolated", "unknown"]
951
+ )
952
+ def test_future_1_1_context_replay_accepts_supported_statuses(
953
+ tmp_path: Path, status: str
954
+ ) -> None:
955
+ root, row, _, _ = _future_bundle(tmp_path, status)
956
+ errors, warnings = validate_report(row)
957
+ assert errors == []
958
+ assert warnings == []
959
+ guard.validate_prospective_measurement(row, root)
960
+
961
+
962
+ @pytest.mark.parametrize(
963
+ ("mutation", "expected"),
964
+ [
965
+ ("missing", "missing subject.config.subject_context"),
966
+ ("ref", "must end in subject-context.json"),
967
+ ("hash", "row hash mismatch"),
968
+ ("status", "binding status differs"),
969
+ ("raw_path", "appear verbatim in raw_outputs.paths"),
970
+ ],
971
+ )
972
+ def test_future_context_binding_fails_closed(
973
+ tmp_path: Path, mutation: str, expected: str
974
+ ) -> None:
975
+ root, row, context_path, _ = _future_bundle(tmp_path)
976
+ binding = row["subject"]["config"]["subject_context"]
977
+ if mutation == "missing":
978
+ del row["subject"]["config"]["subject_context"]
979
+ elif mutation == "ref":
980
+ bad_ref = context_path.with_name("context.json").relative_to(root).as_posix()
981
+ shutil.copyfile(context_path, root / bad_ref)
982
+ binding["ref"] = bad_ref
983
+ binding["sha256"] = _digest(root / bad_ref)
984
+ row["raw_outputs"]["paths"] = [bad_ref]
985
+ elif mutation == "hash":
986
+ binding["sha256"] = "0" * 64
987
+ elif mutation == "status":
988
+ binding["status"] = "unknown"
989
+ else:
990
+ row["raw_outputs"]["paths"] = []
991
+ with pytest.raises(guard.ContractError, match=expected):
992
+ guard.validate_prospective_measurement(row, root)
993
+
994
+
995
+ def test_future_context_run_id_must_match_parent_path(tmp_path: Path) -> None:
996
+ root, row, context_path, _ = _future_bundle(tmp_path)
997
+ context = _read_json(context_path)
998
+ context["run_id"] = "different-window"
999
+ _write_json(context_path, context)
1000
+ _sync_context(row, context_path)
1001
+ with pytest.raises(guard.ContractError, match="not the canonical run sibling"):
1002
+ guard.validate_prospective_measurement(row, root)
1003
+
1004
+
1005
+ @pytest.mark.parametrize("mutation", ["ref", "hash"])
1006
+ def test_future_manifest_ref_and_hash_are_bound(
1007
+ tmp_path: Path, mutation: str
1008
+ ) -> None:
1009
+ root, row, _, _ = _future_bundle(tmp_path)
1010
+ if mutation == "ref":
1011
+ row["execution_manifest"]["ref"] = (
1012
+ f"{guard.RUNS_PREFIX}other-run/execution-manifest.json"
1013
+ )
1014
+ expected = "row/context execution_manifest ref mismatch"
1015
+ else:
1016
+ row["execution_manifest"]["sha256"] = "0" * 64
1017
+ expected = "execution-manifest hash mismatch"
1018
+ with pytest.raises(guard.ContractError, match=expected):
1019
+ guard.validate_prospective_measurement(row, root)
1020
+
1021
+
1022
+ def test_context_record_must_precede_first_scored_call(tmp_path: Path) -> None:
1023
+ root, row, context_path, _ = _future_bundle(tmp_path)
1024
+ context = _read_json(context_path)
1025
+ context["recorded_at"] = "2026-08-10T01:01:02Z"
1026
+ _write_json(context_path, context)
1027
+ _sync_context(row, context_path)
1028
+ with pytest.raises(guard.ContractError, match="gate was not sealed before"):
1029
+ guard.validate_prospective_measurement(row, root)
1030
+
1031
+
1032
+ def test_probe_completion_cannot_follow_context_record(tmp_path: Path) -> None:
1033
+ root, row, context_path, _ = _future_bundle(tmp_path)
1034
+ context = _read_json(context_path)
1035
+ context["context_probe"]["completed_at"] = "2026-08-10T01:00:05Z"
1036
+ _write_json(context_path, context)
1037
+ _sync_context(row, context_path)
1038
+ with pytest.raises(guard.ContractError, match="probe timestamps"):
1039
+ guard.validate_prospective_measurement(row, root)
1040
+
1041
+
1042
+ def test_attestation_cannot_precede_completed_probe(tmp_path: Path) -> None:
1043
+ root, row, context_path, _ = _future_bundle(tmp_path, "attested_only")
1044
+ context = _read_json(context_path)
1045
+ context["attestation"]["attested_at"] = "2026-08-10T00:59:59Z"
1046
+ _write_json(context_path, context)
1047
+ _sync_context(row, context_path)
1048
+ with pytest.raises(guard.ContractError, match="attestation precedes"):
1049
+ guard.validate_prospective_measurement(row, root)
1050
+
1051
+
1052
+ @pytest.mark.parametrize("mutation", ["row_suite", "config_commit", "frozen_commit"])
1053
+ def test_future_suite_and_frozen_commit_bindings(
1054
+ tmp_path: Path, mutation: str
1055
+ ) -> None:
1056
+ root, row, _, _ = _future_bundle(tmp_path)
1057
+ if mutation == "row_suite":
1058
+ row["suite"] = "other_suite"
1059
+ expected = "row suite mismatch"
1060
+ elif mutation == "config_commit":
1061
+ row["subject"]["config"]["suite_commit"] = "b" * 40
1062
+ expected = "suite_commit differs"
1063
+ else:
1064
+ row["preregistration"]["frozen_commit"] = "b" * 40
1065
+ expected = "frozen_commit differs"
1066
+ with pytest.raises(guard.ContractError, match=expected):
1067
+ guard.validate_prospective_measurement(row, root)
1068
+
1069
+
1070
+ def test_launcher_config_row_hash_replays_exactly(tmp_path: Path) -> None:
1071
+ root, row, _, _ = _future_bundle(tmp_path)
1072
+ row["subject"]["config"]["launcher_config"]["sha256"] = "9" * 64
1073
+ with pytest.raises(guard.ContractError, match="launcher_config binding mismatch"):
1074
+ guard.validate_prospective_measurement(row, root)
1075
+
1076
+
1077
+ def test_future_adjudication_is_flags_only(tmp_path: Path) -> None:
1078
+ root, row, _, _ = _future_bundle(tmp_path)
1079
+ row["adjudication"]["resolution_direction"] = "bidirectional"
1080
+ with pytest.raises(guard.ContractError, match="must be flags_only"):
1081
+ guard.validate_prospective_measurement(row, root)
1082
+
1083
+
1084
+ @pytest.mark.parametrize("mutation", ["criterion", "scope", "separation", "extra"])
1085
+ def test_future_c9_result_layer_is_closed_and_separate(
1086
+ tmp_path: Path, mutation: str
1087
+ ) -> None:
1088
+ root, row, _, _ = _future_bundle(tmp_path)
1089
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1090
+ if mutation == "criterion":
1091
+ layer["criterion"] = "C8"
1092
+ elif mutation == "scope":
1093
+ layer["scope"] = "non_controls_only"
1094
+ elif mutation == "separation":
1095
+ layer["reported_separately"] = False
1096
+ else:
1097
+ layer["affects_headline"] = True
1098
+ with pytest.raises(guard.ContractError, match="closed separate C9"):
1099
+ guard.validate_prospective_measurement(row, root)
1100
+
1101
+
1102
+ def test_c9_cannot_be_smuggled_into_the_generic_aggregate_headline(
1103
+ tmp_path: Path,
1104
+ ) -> None:
1105
+ root, row, _, _ = _future_bundle(tmp_path)
1106
+ row["aggregate"]["headline"]["metric_name"] = "C9_citation_attachment_rate"
1107
+ row["aggregate"]["headline"]["construction_rule"] = (
1108
+ "C9 citation-attachment flags-only adjudication defines this lower bound."
1109
+ )
1110
+ with pytest.raises(guard.ContractError):
1111
+ guard.validate_prospective_measurement(row, root)
1112
+
1113
+
1114
+ @pytest.mark.parametrize(
1115
+ "wording",
1116
+ [
1117
+ "The subject ran in a clean context.",
1118
+ "The subject was fully isolated.",
1119
+ "Prompt isolation was verified.",
1120
+ "Repository-instruction isolation was achieved.",
1121
+ ],
1122
+ )
1123
+ def test_unqualified_isolation_language_is_rejected(
1124
+ tmp_path: Path, wording: str
1125
+ ) -> None:
1126
+ root, row, _, _ = _future_bundle(tmp_path)
1127
+ row["verdict"] = wording
1128
+ with pytest.raises(
1129
+ guard.ContractError,
1130
+ match="isolation wording is allowed only",
1131
+ ):
1132
+ guard.validate_prospective_measurement(row, root)
1133
+
1134
+
1135
+ def test_status_claim_ceiling_is_exact_for_unknown_status(tmp_path: Path) -> None:
1136
+ root, row, _, _ = _future_bundle(tmp_path, "unknown")
1137
+ row["results"]["subject_context_claim"] = (
1138
+ "repository-instruction isolated (machine-supported)"
1139
+ )
1140
+ with pytest.raises(guard.ContractError, match="exact status-derived ceiling"):
1141
+ guard.validate_prospective_measurement(row, root)
1142
+
1143
+
1144
+ @pytest.mark.parametrize(
1145
+ "claim_key",
1146
+ ["repository_instruction_isolation_confirmed", "clean_context"],
1147
+ )
1148
+ def test_typed_boolean_keys_cannot_publish_an_unsupported_isolation_claim(
1149
+ tmp_path: Path, claim_key: str
1150
+ ) -> None:
1151
+ root, row, _, _ = _future_bundle(tmp_path, "unknown")
1152
+ row["results"][claim_key] = True
1153
+ with pytest.raises(guard.ContractError, match="claim-shaped isolation keys are forbidden"):
1154
+ guard.validate_prospective_measurement(row, root)
1155
+
1156
+
1157
+ def test_manifest_window_id_must_equal_context_run_id(tmp_path: Path) -> None:
1158
+ root, row, _, manifest_path = _future_bundle(tmp_path)
1159
+ manifest = _read_json(manifest_path)
1160
+ manifest["execution_window"]["window_id"] = "different-window"
1161
+ _write_json(manifest_path, manifest)
1162
+ _sync_manifest(row, manifest_path)
1163
+ with pytest.raises(guard.ContractError, match="window ID.*run_id mismatch"):
1164
+ guard.validate_prospective_measurement(row, root)
1165
+
1166
+
1167
+ @pytest.mark.parametrize(
1168
+ ("schema_name", "expected"),
1169
+ [
1170
+ ("subject_launcher_config.schema.json", "launcher-config schema byte identity"),
1171
+ ("subject_call_plan.schema.json", "call-plan schema byte identity"),
1172
+ ],
1173
+ )
1174
+ def test_prospective_companion_schema_hashes_are_load_bearing(
1175
+ tmp_path: Path, schema_name: str, expected: str
1176
+ ) -> None:
1177
+ root = _mirror(tmp_path)
1178
+ path = root / SUITE / schema_name
1179
+ path.write_bytes(path.read_bytes() + b"\n")
1180
+ with pytest.raises(guard.ContractError, match=expected):
1181
+ guard._check_subject_assets(root)
1182
+
1183
+
1184
+ @pytest.mark.parametrize(
1185
+ ("mutation", "expected"),
1186
+ [
1187
+ ("missing", "subject.config: keys mismatch"),
1188
+ ("ref", "launcher_config binding mismatch"),
1189
+ ("hash", "launcher-config artifact hash mismatch"),
1190
+ ("raw", "launcher-config ref must appear"),
1191
+ ("schema", "launcher-config artifact fails schema"),
1192
+ ("provenance", "working-directory policy mismatch"),
1193
+ ("invocation_hash", "launcher-config invocation hash mismatch"),
1194
+ ],
1195
+ )
1196
+ def test_launcher_config_binding_is_canonical_and_replayed(
1197
+ tmp_path: Path, mutation: str, expected: str
1198
+ ) -> None:
1199
+ root, row, _, _ = _future_bundle(tmp_path)
1200
+ config = row["subject"]["config"]
1201
+ launcher_path = _bound_path(root, row, "launcher_config")
1202
+ if mutation == "missing":
1203
+ del config["launcher_config"]
1204
+ elif mutation == "ref":
1205
+ config["launcher_config"]["ref"] = (
1206
+ f"{guard.RUNS_PREFIX}other/launcher-config.json"
1207
+ )
1208
+ elif mutation == "hash":
1209
+ launcher_path.write_bytes(launcher_path.read_bytes() + b"\n")
1210
+ elif mutation == "raw":
1211
+ row["raw_outputs"]["paths"].remove(config["launcher_config"]["ref"])
1212
+ else:
1213
+ launcher = _read_json(launcher_path)
1214
+ if mutation == "schema":
1215
+ launcher["raw_command"] = "forbidden"
1216
+ elif mutation == "invocation_hash":
1217
+ launcher["invocation_sha256"] = "0" * 64
1218
+ else:
1219
+ launcher["working_directory"]["policy"] = "inside_suite_repository"
1220
+ launcher["invocation_sha256"] = _canonical_object_digest(
1221
+ {
1222
+ key: launcher[key]
1223
+ for key in (
1224
+ "launcher",
1225
+ "working_directory",
1226
+ "instruction_loading",
1227
+ )
1228
+ }
1229
+ )
1230
+ _rewrite_launcher(root, row, launcher)
1231
+ with pytest.raises(guard.ContractError, match=expected):
1232
+ guard.validate_prospective_measurement(row, root)
1233
+
1234
+
1235
+ @pytest.mark.parametrize(
1236
+ ("mutation", "expected"),
1237
+ [
1238
+ ("missing", "subject.config: keys mismatch"),
1239
+ ("ref", "subject_call_plan binding mismatch"),
1240
+ ("hash", "subject-call-plan artifact hash mismatch"),
1241
+ ("raw", "subject-call-plan ref must appear"),
1242
+ ("schema", "subject-call-plan artifact fails schema"),
1243
+ ("provenance", "provenance differs"),
1244
+ ("subject_model", "provenance differs"),
1245
+ ("late", "not frozen before probe/preflight"),
1246
+ ],
1247
+ )
1248
+ def test_subject_call_plan_binding_is_canonical_and_precommitted(
1249
+ tmp_path: Path, mutation: str, expected: str
1250
+ ) -> None:
1251
+ root, row, _, _ = _future_bundle(tmp_path)
1252
+ config = row["subject"]["config"]
1253
+ plan_path = _bound_path(root, row, "subject_call_plan")
1254
+ if mutation == "missing":
1255
+ del config["subject_call_plan"]
1256
+ elif mutation == "ref":
1257
+ config["subject_call_plan"]["ref"] = (
1258
+ f"{guard.RUNS_PREFIX}other/subject-call-plan.json"
1259
+ )
1260
+ elif mutation == "hash":
1261
+ plan_path.write_bytes(plan_path.read_bytes() + b"\n")
1262
+ elif mutation == "raw":
1263
+ row["raw_outputs"]["paths"].remove(config["subject_call_plan"]["ref"])
1264
+ else:
1265
+ plan = _read_json(plan_path)
1266
+ if mutation == "schema":
1267
+ plan["uncommitted_calls"] = []
1268
+ elif mutation == "provenance":
1269
+ plan["suite_commit"] = "b" * 40
1270
+ elif mutation == "subject_model":
1271
+ plan["subject_model_id"] = "different/subject"
1272
+ else:
1273
+ plan["created_at"] = "2026-08-10T01:00:05Z"
1274
+ _rewrite_plan(root, row, plan)
1275
+ with pytest.raises(guard.ContractError, match=expected):
1276
+ guard.validate_prospective_measurement(row, root)
1277
+
1278
+
1279
+ @pytest.mark.parametrize(
1280
+ ("mutation", "expected"),
1281
+ [
1282
+ ("missing_sealed", "launcher-config artifact fails schema"),
1283
+ ("sealed_after_probe", "not sealed before probe/preflight"),
1284
+ ("sealed_after_plan", "not sealed before the subject-call plan"),
1285
+ ],
1286
+ )
1287
+ def test_launcher_and_call_plan_are_sealed_in_preflight_order(
1288
+ tmp_path: Path, mutation: str, expected: str
1289
+ ) -> None:
1290
+ root, row, _, _ = _future_bundle(tmp_path)
1291
+ launcher = _read_json(_bound_path(root, row, "launcher_config"))
1292
+ if mutation == "missing_sealed":
1293
+ del launcher["sealed_at"]
1294
+ elif mutation == "sealed_after_probe":
1295
+ launcher["sealed_at"] = "2026-08-10T01:00:01Z"
1296
+ else:
1297
+ launcher["sealed_at"] = "2026-08-10T00:59:55Z"
1298
+ _rewrite_launcher(root, row, launcher)
1299
+ with pytest.raises(guard.ContractError, match=expected):
1300
+ guard.validate_prospective_measurement(row, root)
1301
+
1302
+
1303
+ @pytest.mark.parametrize(
1304
+ ("mutation", "expected"),
1305
+ [
1306
+ ("plan_order", "same 2..8 sorted judges"),
1307
+ ("row_identity", "published judge identity/template differs"),
1308
+ ("template_ref", "prompt-template ref is not canonical"),
1309
+ ("template_hash", "prompt-template hash mismatch"),
1310
+ ("template_raw", "prompt-template ref must appear"),
1311
+ ("closed_schema", "subject-call-plan artifact fails schema"),
1312
+ ("one_family", "at least two judge model families"),
1313
+ ("decision_relevant", "decision-relevant with no judge exception"),
1314
+ ("judge_exception", "decision-relevant with no judge exception"),
1315
+ ],
1316
+ )
1317
+ def test_judge_roster_identity_templates_and_decision_authority_are_frozen(
1318
+ tmp_path: Path, mutation: str, expected: str
1319
+ ) -> None:
1320
+ root, row, _, _ = _future_bundle(tmp_path)
1321
+ plan = _read_json(_bound_path(root, row, "subject_call_plan"))
1322
+ template_ref = plan["judges"][0]["prompt_template"]["ref"]
1323
+ if mutation == "plan_order":
1324
+ plan["judges"].reverse()
1325
+ _rewrite_plan(root, row, plan)
1326
+ elif mutation == "row_identity":
1327
+ row["judges"][0]["model_id"] = "different/model"
1328
+ elif mutation == "template_ref":
1329
+ alternate_ref = template_ref.replace(".template.txt", ".alternate.txt")
1330
+ alternate_path = root / alternate_ref
1331
+ alternate_path.write_text("alternate frozen template\n", encoding="utf-8")
1332
+ row["raw_outputs"]["paths"].append(alternate_ref)
1333
+ plan["judges"][0]["prompt_template"] = {
1334
+ "ref": alternate_ref,
1335
+ "sha256": _digest(alternate_path),
1336
+ }
1337
+ row["judges"][0]["prompt_ref"] = alternate_ref
1338
+ _rewrite_plan(root, row, plan)
1339
+ elif mutation == "template_hash":
1340
+ (root / template_ref).write_bytes((root / template_ref).read_bytes() + b"drift")
1341
+ elif mutation == "template_raw":
1342
+ row["raw_outputs"]["paths"].remove(template_ref)
1343
+ elif mutation == "closed_schema":
1344
+ plan["judges"][0]["unfrozen_prompt"] = True
1345
+ _rewrite_plan(root, row, plan)
1346
+ elif mutation == "one_family":
1347
+ row["judges"][1]["model_family"] = row["judges"][0]["model_family"]
1348
+ plan["judges"][1]["model_family"] = plan["judges"][0]["model_family"]
1349
+ _rewrite_plan(root, row, plan)
1350
+ elif mutation == "decision_relevant":
1351
+ row["decision_relevant"] = False
1352
+ else:
1353
+ row["judge_plan"] = {
1354
+ "exception": "legacy_comparability",
1355
+ "legacy_baseline_ref": "measurement-historical.json",
1356
+ }
1357
+ with pytest.raises(guard.ContractError, match=expected):
1358
+ guard.validate_prospective_measurement(row, root)
1359
+
1360
+
1361
+ @pytest.mark.parametrize("field", ["plan_ref", "plan_sha256"])
1362
+ def test_preregistration_exactly_binds_the_subject_call_plan(
1363
+ tmp_path: Path, field: str
1364
+ ) -> None:
1365
+ root, row, _, _ = _future_bundle(tmp_path)
1366
+ row["preregistration"][field] = "0" * 64 if field.endswith("sha256") else "other"
1367
+ with pytest.raises(guard.ContractError, match="preregistration plan binding differs"):
1368
+ guard.validate_prospective_measurement(row, root)
1369
+
1370
+
1371
+ @pytest.mark.parametrize(
1372
+ ("mutation", "expected"),
1373
+ [
1374
+ ("delete_judge", "exactly cover judge x item-replicate"),
1375
+ ("reindex", "sequence indexes must be ordered"),
1376
+ ("role", "exactly cover item x arm x replicate"),
1377
+ ("judge_item", "judge-call roster differs from the frozen run design"),
1378
+ ],
1379
+ )
1380
+ def test_call_plan_call_roster_role_and_index_are_load_bearing(
1381
+ tmp_path: Path, mutation: str, expected: str
1382
+ ) -> None:
1383
+ root, row, _, _ = _future_bundle(tmp_path)
1384
+ plan_path = _bound_path(root, row, "subject_call_plan")
1385
+ plan = _read_json(plan_path)
1386
+ if mutation == "delete_judge":
1387
+ plan["calls"].pop()
1388
+ elif mutation == "reindex":
1389
+ plan["calls"][1]["sequence_index"] = 3
1390
+ plan["calls"][2]["sequence_index"] = 2
1391
+ elif mutation == "role":
1392
+ call = plan["calls"][0]
1393
+ subject_prompt_ref = call["prompt"]["ref"]
1394
+ call["role"] = "judge"
1395
+ call["judge_id"] = "judge-a"
1396
+ call["prompt"] = {
1397
+ "ref": subject_prompt_ref,
1398
+ "sha256": None,
1399
+ "composition": "template_then_subject_input_then_subject_output/1.0",
1400
+ "template_ref": plan["judges"][0]["prompt_template"]["ref"],
1401
+ "subject_prompt_ref": subject_prompt_ref,
1402
+ "subject_output_ref": call["output_ref"],
1403
+ }
1404
+ else:
1405
+ plan["calls"][16]["item_id"] = "other-item"
1406
+ _rewrite_plan(root, row, plan)
1407
+ with pytest.raises(guard.ContractError, match=expected):
1408
+ guard.validate_prospective_measurement(row, root)
1409
+
1410
+
1411
+ @pytest.mark.parametrize(
1412
+ ("mutation", "expected"),
1413
+ [
1414
+ ("prompt_drift", "subject prompt hash mismatch"),
1415
+ ("prompt_missing", "missing/unreadable path"),
1416
+ ("output_drift", "output hash differs"),
1417
+ ("output_missing", "missing/unreadable path"),
1418
+ ("prompt_raw", "planned prompt/output ref must be retained raw"),
1419
+ ("output_raw", "planned prompt/output ref must be retained raw"),
1420
+ ],
1421
+ )
1422
+ def test_every_call_prompt_and_output_is_hashed_and_retained(
1423
+ tmp_path: Path, mutation: str, expected: str
1424
+ ) -> None:
1425
+ root, row, _, _ = _future_bundle(tmp_path)
1426
+ plan = _read_json(_bound_path(root, row, "subject_call_plan"))
1427
+ prompt_ref = plan["calls"][0]["prompt"]["ref"]
1428
+ output_ref = plan["calls"][-1 if mutation == "output_drift" else 0]["output_ref"]
1429
+ if mutation == "prompt_drift":
1430
+ (root / prompt_ref).write_bytes((root / prompt_ref).read_bytes() + b"drift")
1431
+ elif mutation == "prompt_missing":
1432
+ (root / prompt_ref).unlink()
1433
+ elif mutation == "output_drift":
1434
+ (root / output_ref).write_bytes((root / output_ref).read_bytes() + b"drift")
1435
+ elif mutation == "output_missing":
1436
+ (root / output_ref).unlink()
1437
+ elif mutation == "prompt_raw":
1438
+ row["raw_outputs"]["paths"].remove(prompt_ref)
1439
+ else:
1440
+ row["raw_outputs"]["paths"].remove(output_ref)
1441
+ with pytest.raises(guard.ContractError, match=expected):
1442
+ guard.validate_prospective_measurement(row, root)
1443
+
1444
+
1445
+ @pytest.mark.parametrize(
1446
+ ("mutation", "expected"),
1447
+ [
1448
+ ("composition", "subject-call-plan artifact fails schema"),
1449
+ ("template_ref", "judge prompt dependency differs"),
1450
+ ("subject_prompt_ref", "judge prompt dependency differs"),
1451
+ ("subject_output_ref", "judge prompt dependency differs"),
1452
+ ("materialized_hash", "subject-call-plan artifact fails schema"),
1453
+ ("bytes", "judge prompt bytes do not replay"),
1454
+ ],
1455
+ )
1456
+ def test_judge_prompts_are_deferred_and_replay_frozen_dependencies(
1457
+ tmp_path: Path, mutation: str, expected: str
1458
+ ) -> None:
1459
+ root, row, _, _ = _future_bundle(tmp_path)
1460
+ plan = _read_json(_bound_path(root, row, "subject_call_plan"))
1461
+ judge_call = plan["calls"][16]
1462
+ if mutation == "composition":
1463
+ judge_call["prompt"]["composition"] = "free_form/1.0"
1464
+ _rewrite_plan(root, row, plan)
1465
+ elif mutation == "template_ref":
1466
+ judge_call["prompt"]["template_ref"] = plan["judges"][1][
1467
+ "prompt_template"
1468
+ ]["ref"]
1469
+ _rewrite_plan(root, row, plan)
1470
+ elif mutation == "subject_prompt_ref":
1471
+ judge_call["prompt"]["subject_prompt_ref"] = plan["calls"][1]["prompt"][
1472
+ "ref"
1473
+ ]
1474
+ _rewrite_plan(root, row, plan)
1475
+ elif mutation == "subject_output_ref":
1476
+ judge_call["prompt"]["subject_output_ref"] = plan["calls"][1]["output_ref"]
1477
+ _rewrite_plan(root, row, plan)
1478
+ elif mutation == "materialized_hash":
1479
+ judge_call["prompt"]["sha256"] = "0" * 64
1480
+ _rewrite_plan(root, row, plan)
1481
+ else:
1482
+ prompt_path = root / judge_call["prompt"]["ref"]
1483
+ prompt_path.write_bytes(prompt_path.read_bytes() + b"drift")
1484
+ with pytest.raises(guard.ContractError, match=expected):
1485
+ guard.validate_prospective_measurement(row, root)
1486
+
1487
+
1488
+ @pytest.mark.parametrize(
1489
+ ("mutation", "expected"),
1490
+ [
1491
+ ("delete", "does not exactly cover the call plan"),
1492
+ ("reindex", "sequence indexes must be ordered"),
1493
+ ("call_id", "differs from precommitted call plan"),
1494
+ ("prompt_hash", "differs from precommitted call plan"),
1495
+ ],
1496
+ )
1497
+ def test_execution_manifest_exactly_joins_the_call_plan(
1498
+ tmp_path: Path, mutation: str, expected: str
1499
+ ) -> None:
1500
+ root, row, _, manifest_path = _future_bundle(tmp_path)
1501
+ manifest = _read_json(manifest_path)
1502
+ if mutation == "delete":
1503
+ manifest["calls"].pop()
1504
+ elif mutation == "reindex":
1505
+ manifest["calls"][1]["sequence_index"] = 3
1506
+ manifest["calls"][2]["sequence_index"] = 2
1507
+ elif mutation == "call_id":
1508
+ manifest["calls"][0]["call_id"] = "judge-disguised-as-subject"
1509
+ else:
1510
+ manifest["calls"][0]["prompt_sha256"] = "9" * 64
1511
+ _write_json(manifest_path, manifest)
1512
+ _sync_manifest(row, manifest_path)
1513
+ with pytest.raises(guard.ContractError, match=expected):
1514
+ guard.validate_prospective_measurement(row, root)
1515
+
1516
+
1517
+ @pytest.mark.parametrize(
1518
+ ("mutation", "expected"),
1519
+ [
1520
+ ("created_before_call", "recorded before its final call completed"),
1521
+ ("created_before_window_end", "recorded before its window ended"),
1522
+ ("window_excludes_call", "execution window does not contain all calls"),
1523
+ ],
1524
+ )
1525
+ def test_manifest_created_and_window_ordering_is_load_bearing(
1526
+ tmp_path: Path, mutation: str, expected: str
1527
+ ) -> None:
1528
+ root, row, _, manifest_path = _future_bundle(tmp_path)
1529
+ manifest = _read_json(manifest_path)
1530
+ if mutation == "created_before_call":
1531
+ manifest["created_at"] = "2026-08-10T01:01:40Z"
1532
+ elif mutation == "created_before_window_end":
1533
+ manifest["execution_window"]["completed_at"] = "2026-08-10T01:04:00Z"
1534
+ else:
1535
+ manifest["execution_window"]["started_at"] = "2026-08-10T01:01:05Z"
1536
+ _write_json(manifest_path, manifest)
1537
+ _sync_manifest(row, manifest_path)
1538
+ with pytest.raises(guard.ContractError, match=expected):
1539
+ guard.validate_prospective_measurement(row, root)
1540
+
1541
+
1542
+ def test_context_gate_precedes_every_scored_call_even_without_ordering_claim(
1543
+ tmp_path: Path,
1544
+ ) -> None:
1545
+ root, row, _, manifest_path = _future_bundle(tmp_path)
1546
+ manifest = _read_json(manifest_path)
1547
+ manifest["execution_window"]["started_at"] = "2026-08-10T00:59:00Z"
1548
+ manifest["calls"][16]["started_at"] = "2026-08-10T00:59:10Z"
1549
+ manifest["calls"][16]["completed_at"] = "2026-08-10T00:59:20Z"
1550
+ row["execution_manifest"]["claims"].remove("ordering")
1551
+ _write_json(manifest_path, manifest)
1552
+ _sync_manifest(row, manifest_path)
1553
+ with pytest.raises(guard.ContractError):
1554
+ guard.validate_prospective_measurement(row, root)
1555
+
1556
+
1557
+ @pytest.mark.parametrize(
1558
+ ("mutation", "expected"),
1559
+ [
1560
+ ("plan_chronology", "not chronological by plan order"),
1561
+ ("judge_overlap", "judge calls began before the subject fleet completed"),
1562
+ ],
1563
+ )
1564
+ def test_manifest_call_times_follow_plan_order_and_separate_judge_dispatch(
1565
+ tmp_path: Path, mutation: str, expected: str
1566
+ ) -> None:
1567
+ root, row, _, manifest_path = _future_bundle(tmp_path)
1568
+ manifest = _read_json(manifest_path)
1569
+ if mutation == "plan_chronology":
1570
+ manifest["calls"][1]["started_at"] = "2026-08-10T01:01:00.500Z"
1571
+ manifest["calls"][1]["completed_at"] = "2026-08-10T01:01:00.600Z"
1572
+ else:
1573
+ manifest["calls"][16]["started_at"] = "2026-08-10T01:01:16.050Z"
1574
+ manifest["calls"][16]["completed_at"] = "2026-08-10T01:01:16.150Z"
1575
+ _write_json(manifest_path, manifest)
1576
+ _sync_manifest(row, manifest_path)
1577
+ with pytest.raises(guard.ContractError, match=expected):
1578
+ guard.validate_prospective_measurement(row, root)
1579
+
1580
+
1581
+ def test_c9_zero_finding_layer_still_covers_the_subject_roster(tmp_path: Path) -> None:
1582
+ root, row, _, _ = _future_bundle(tmp_path)
1583
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1584
+ assert len(layer["evaluated_item_replicates"]) == 16
1585
+ assert layer["control_item_replicates"] == [
1586
+ "rp-07.single.r1",
1587
+ "rp-07.single.r2",
1588
+ "rp-08.single.r1",
1589
+ "rp-08.single.r2",
1590
+ ]
1591
+ assert layer["finding_count"] == 0
1592
+ assert layer["decisions"] == []
1593
+ assert layer["findings"] == []
1594
+ guard.validate_prospective_measurement(row, root)
1595
+
1596
+
1597
+ @pytest.mark.parametrize("mutation", ["missing", "extra", "control"])
1598
+ def test_c9_roster_is_derived_from_precommitted_subject_calls(
1599
+ tmp_path: Path, mutation: str
1600
+ ) -> None:
1601
+ root, row, _, _ = _future_bundle(tmp_path)
1602
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1603
+ if mutation == "missing":
1604
+ layer["evaluated_item_replicates"] = []
1605
+ elif mutation == "extra":
1606
+ layer["evaluated_item_replicates"].append("unplanned-r9")
1607
+ else:
1608
+ layer["control_item_replicates"] = ["rp-07.single.r1"]
1609
+ with pytest.raises(guard.ContractError):
1610
+ guard.validate_prospective_measurement(row, root)
1611
+
1612
+
1613
+ def test_c9_well_formed_finding_with_bound_evidence_passes(tmp_path: Path) -> None:
1614
+ root, row, _, _ = _future_bundle(tmp_path)
1615
+ _add_c9_finding(root, row)
1616
+ guard.validate_prospective_measurement(row, root)
1617
+
1618
+
1619
+ @pytest.mark.parametrize(
1620
+ ("mutation", "expected"),
1621
+ [
1622
+ ("item", "unevaluated item-replicate"),
1623
+ ("criterion", "finding authority"),
1624
+ ("authorization", "finding authority"),
1625
+ ("evidence_hash", "evidence artifact hash mismatch"),
1626
+ ("evidence_ref", "evidence_ref is not the canonical run-local path"),
1627
+ ("raw", "evidence_ref must appear"),
1628
+ ("count", "finding_count must equal"),
1629
+ ],
1630
+ )
1631
+ def test_c9_finding_authority_evidence_and_count_fail_closed(
1632
+ tmp_path: Path, mutation: str, expected: str
1633
+ ) -> None:
1634
+ root, row, _, _ = _future_bundle(tmp_path)
1635
+ evidence_path = _add_c9_finding(root, row)
1636
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1637
+ finding = layer["findings"][0]
1638
+ if mutation == "item":
1639
+ finding["item_replicate_id"] = "unplanned-r9"
1640
+ elif mutation == "criterion":
1641
+ finding["criterion"] = "C8"
1642
+ elif mutation == "authorization":
1643
+ finding["authorization"] = "authorized_under_C3"
1644
+ elif mutation == "evidence_hash":
1645
+ finding["evidence_sha256"] = "0" * 64
1646
+ elif mutation == "evidence_ref":
1647
+ finding["evidence_ref"] = "evals/heldout/other/evidence.json"
1648
+ elif mutation == "raw":
1649
+ row["raw_outputs"]["paths"].remove(evidence_path.relative_to(root).as_posix())
1650
+ else:
1651
+ layer["finding_count"] = 0
1652
+ with pytest.raises(guard.ContractError, match=expected):
1653
+ guard.validate_prospective_measurement(row, root)
1654
+
1655
+
1656
+ def test_generic_non_c9_judge_flags_do_not_create_a_c9_finding(
1657
+ tmp_path: Path,
1658
+ ) -> None:
1659
+ root, row, _, _ = _future_bundle(tmp_path)
1660
+ for judge in row["judges"]:
1661
+ judge["per_item"][0]["flag"] = True
1662
+ guard.validate_prospective_measurement(row, root)
1663
+
1664
+
1665
+ def test_published_c9_finding_requires_typed_raw_flag_authority(
1666
+ tmp_path: Path,
1667
+ ) -> None:
1668
+ root, row, _, _ = _future_bundle(tmp_path)
1669
+ _add_c9_finding(root, row)
1670
+ finding = row["results"]["revision_claim_drift_v2"]["citation_attachment"][
1671
+ "findings"
1672
+ ][0]
1673
+ del finding["raw_flag_judge_ids"]
1674
+ with pytest.raises(guard.ContractError):
1675
+ guard.validate_prospective_measurement(row, root)
1676
+
1677
+
1678
+ def test_generic_true_flag_cannot_override_typed_false_c9_verdict(
1679
+ tmp_path: Path,
1680
+ ) -> None:
1681
+ root, row, _, _ = _future_bundle(tmp_path)
1682
+ _add_c9_finding(root, row)
1683
+ raw_row = row["judges"][0]["per_item"][0]
1684
+ raw_row["flag"] = True
1685
+ raw_row["citation_attachment"]["flag"] = False
1686
+ with pytest.raises(guard.ContractError, match="exactly resolve every typed raw true flag"):
1687
+ guard.validate_prospective_measurement(row, root)
1688
+
1689
+
1690
+ def test_typed_raw_true_c9_flag_cannot_be_omitted_from_decisions(
1691
+ tmp_path: Path,
1692
+ ) -> None:
1693
+ root, row, _, _ = _future_bundle(tmp_path)
1694
+ row["judges"][0]["per_item"][0]["citation_attachment"]["flag"] = True
1695
+ with pytest.raises(guard.ContractError, match="exactly resolve every typed raw true"):
1696
+ guard.validate_prospective_measurement(row, root)
1697
+
1698
+
1699
+ def test_c5_cannot_reject_a_noncontrol_c9_raw_flag(tmp_path: Path) -> None:
1700
+ root, row, _, _ = _future_bundle(tmp_path)
1701
+ item_replicate_id = "rp-01.single.r1"
1702
+ row["judges"][0]["per_item"][0]["citation_attachment"]["flag"] = True
1703
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1704
+ layer["decisions"] = [
1705
+ {
1706
+ "decision_id": f"c9d.judge-a.{item_replicate_id}",
1707
+ "judge_id": "judge-a",
1708
+ "item_replicate_id": item_replicate_id,
1709
+ "raw_flag": True,
1710
+ "disposition": "rejected",
1711
+ "criterion_ref": "C5",
1712
+ "reason_code": "authorized_under_C3",
1713
+ "finding_id": None,
1714
+ }
1715
+ ]
1716
+ with pytest.raises(guard.ContractError, match="invalid closed reason"):
1717
+ guard.validate_prospective_measurement(row, root)
1718
+
1719
+
1720
+ def test_generic_override_cannot_route_c9_or_citation_attachment(
1721
+ tmp_path: Path,
1722
+ ) -> None:
1723
+ root, row, _, _ = _future_bundle(tmp_path)
1724
+ row["adjudication"]["overrides"] = [
1725
+ {
1726
+ "item_id": "rp-01.single.r1",
1727
+ "judge_id": "judge-a",
1728
+ "raw": "citation_attachment C9=true",
1729
+ "adjudicated": "citation_attachment=false",
1730
+ "criterion_ref": "C5",
1731
+ }
1732
+ ]
1733
+ with pytest.raises(guard.ContractError, match="cannot be routed through generic overrides"):
1734
+ guard.validate_prospective_measurement(row, root)
1735
+
1736
+
1737
+ @pytest.mark.parametrize("mutation", ["missing_finding", "wrong_reason", "wrong_id"])
1738
+ def test_confirmed_c9_decision_mapping_is_closed(
1739
+ tmp_path: Path, mutation: str
1740
+ ) -> None:
1741
+ root, row, _, _ = _future_bundle(tmp_path)
1742
+ _add_c9_finding(root, row)
1743
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1744
+ decision = layer["decisions"][0]
1745
+ if mutation == "missing_finding":
1746
+ decision["finding_id"] = "C9-F-missing"
1747
+ elif mutation == "wrong_reason":
1748
+ decision["reason_code"] = "authorized_under_C3"
1749
+ else:
1750
+ decision["decision_id"] = "noncanonical"
1751
+ with pytest.raises(guard.ContractError):
1752
+ guard.validate_prospective_measurement(row, root)
1753
+
1754
+
1755
+ def test_confirmed_c9_decision_cannot_be_relabelled_to_another_item(
1756
+ tmp_path: Path,
1757
+ ) -> None:
1758
+ root, row, _, _ = _future_bundle(tmp_path)
1759
+ evidence_path = _add_c9_finding(root, row)
1760
+ item_b = "rp-01.single.r2"
1761
+ row["judges"][0]["per_item"][1]["citation_attachment"]["flag"] = True
1762
+ layer = row["results"]["revision_claim_drift_v2"]["citation_attachment"]
1763
+ layer["decisions"].append(
1764
+ {
1765
+ "decision_id": f"c9d.judge-a.{item_b}",
1766
+ "judge_id": "judge-a",
1767
+ "item_replicate_id": item_b,
1768
+ "raw_flag": True,
1769
+ "disposition": "rejected",
1770
+ "criterion_ref": "C9",
1771
+ "reason_code": "no_citation_attachment_violation",
1772
+ "finding_id": None,
1773
+ }
1774
+ )
1775
+ finding = layer["findings"][0]
1776
+ finding["item_replicate_id"] = item_b
1777
+ evidence = _read_json(evidence_path)
1778
+ evidence["item_replicate_id"] = item_b
1779
+ _write_json(evidence_path, evidence)
1780
+ finding["evidence_sha256"] = _digest(evidence_path)
1781
+ with pytest.raises(guard.ContractError, match="confirmed decisions"):
1782
+ guard.validate_prospective_measurement(row, root)
1783
+
1784
+
1785
+ def test_report_replicate_count_must_match_precommitted_subject_roster(
1786
+ tmp_path: Path,
1787
+ ) -> None:
1788
+ root, row, _, _ = _future_bundle(tmp_path)
1789
+ row["replicates"]["per_item"] = 3
1790
+ with pytest.raises(guard.ContractError):
1791
+ guard.validate_prospective_measurement(row, root)
1792
+
1793
+
1794
+ def test_extra_unjudged_subject_call_is_rejected(tmp_path: Path) -> None:
1795
+ root, row, _, _ = _future_bundle(tmp_path)
1796
+ plan = _read_json(_bound_path(root, row, "subject_call_plan"))
1797
+ extra = copy.deepcopy(plan["calls"][0])
1798
+ extra["call_id"] = "subject-unjudged-002"
1799
+ extra["sequence_index"] = 4
1800
+ extra["item_id"] = "item-002"
1801
+ extra["item_replicate_id"] = "item-002-r1"
1802
+ extra["prompt"] = copy.deepcopy(plan["calls"][1]["prompt"])
1803
+ extra["output_ref"] = plan["calls"][1]["output_ref"]
1804
+ plan["calls"].append(extra)
1805
+ _rewrite_plan(root, row, plan)
1806
+ with pytest.raises(guard.ContractError):
1807
+ guard.validate_prospective_measurement(row, root)
1808
+
1809
+
1810
+ def test_c9_evidence_cannot_alias_an_arbitrary_retained_artifact(tmp_path: Path) -> None:
1811
+ root, row, _, _ = _future_bundle(tmp_path)
1812
+ _add_c9_finding(root, row)
1813
+ finding = row["results"]["revision_claim_drift_v2"]["citation_attachment"][
1814
+ "findings"
1815
+ ][0]
1816
+ context_ref = row["subject"]["config"]["subject_context"]["ref"]
1817
+ finding["evidence_ref"] = context_ref
1818
+ finding["evidence_sha256"] = _digest(root / context_ref)
1819
+ with pytest.raises(guard.ContractError):
1820
+ guard.validate_prospective_measurement(row, root)
1821
+
1822
+
1823
+ def test_c9_evidence_cannot_use_unreplayed_placeholder_hashes(tmp_path: Path) -> None:
1824
+ root, row, _, _ = _future_bundle(tmp_path)
1825
+ _add_c9_finding(root, row)
1826
+ finding = row["results"]["revision_claim_drift_v2"]["citation_attachment"][
1827
+ "findings"
1828
+ ][0]
1829
+ finding["citation_tokens_sha256"] = "0" * 64
1830
+ finding["original_attachment_sha256"] = "0" * 64
1831
+ finding["revised_attachment_sha256"] = "0" * 64
1832
+ with pytest.raises(guard.ContractError):
1833
+ guard.validate_prospective_measurement(row, root)
1834
+
1835
+
1836
+ def test_boolean_finding_count_is_not_an_integer_count(tmp_path: Path) -> None:
1837
+ root, row, _, _ = _future_bundle(tmp_path)
1838
+ _add_c9_finding(root, row)
1839
+ row["results"]["revision_claim_drift_v2"]["citation_attachment"][
1840
+ "finding_count"
1841
+ ] = True
1842
+ with pytest.raises(guard.ContractError):
1843
+ guard.validate_prospective_measurement(row, root)
1844
+
1845
+
1846
+ @pytest.mark.parametrize(
1847
+ ("field", "mutation"),
1848
+ [
1849
+ (field, mutation)
1850
+ for field in (
1851
+ "citation_tokens",
1852
+ "original_attachment",
1853
+ "revised_attachment",
1854
+ )
1855
+ for mutation in ("ref", "hash", "raw", "empty")
1856
+ ],
1857
+ )
1858
+ def test_c9_attachment_artifacts_are_canonical_hashed_nonempty_and_retained(
1859
+ tmp_path: Path, field: str, mutation: str
1860
+ ) -> None:
1861
+ root, row, _, _ = _future_bundle(tmp_path)
1862
+ _add_c9_finding(root, row)
1863
+ finding = row["results"]["revision_claim_drift_v2"]["citation_attachment"][
1864
+ "findings"
1865
+ ][0]
1866
+ ref_key = f"{field}_ref"
1867
+ hash_key = f"{field}_sha256"
1868
+ ref = finding[ref_key]
1869
+ if mutation == "ref":
1870
+ finding[ref_key] = ref.replace(".txt", ".other.txt")
1871
+ elif mutation == "hash":
1872
+ finding[hash_key] = "0" * 64
1873
+ elif mutation == "raw":
1874
+ row["raw_outputs"]["paths"].remove(ref)
1875
+ else:
1876
+ (root / ref).write_bytes(b"")
1877
+ finding[hash_key] = _digest(root / ref)
1878
+ with pytest.raises(guard.ContractError):
1879
+ guard.validate_prospective_measurement(row, root)
1880
+
1881
+
1882
+ @pytest.mark.parametrize("mutation", ["missing", "overlap", "unsorted"])
1883
+ def test_published_arm_roles_exactly_partition_call_plan_arms(
1884
+ tmp_path: Path, mutation: str
1885
+ ) -> None:
1886
+ root, row, _, _ = _future_bundle(tmp_path)
1887
+ roles = row["results"]["arm_roles"]
1888
+ if mutation == "missing":
1889
+ roles["treatment_or_cohort_arms"] = []
1890
+ elif mutation == "overlap":
1891
+ roles["variant_packet_arms"] = ["single"]
1892
+ else:
1893
+ roles["treatment_or_cohort_arms"] = ["single", "alpha"]
1894
+ roles["variant_packet_arms"] = []
1895
+ with pytest.raises(guard.ContractError, match="arm roles do not exactly partition"):
1896
+ guard.validate_prospective_measurement(row, root)
1897
+
1898
+
1899
+ def test_call_plan_binds_exact_frozen_heldout_set(tmp_path: Path) -> None:
1900
+ root, row, _, _ = _future_bundle(tmp_path)
1901
+ plan = _read_json(_bound_path(root, row, "subject_call_plan"))
1902
+ plan["heldout_set"]["sha256"] = "0" * 64
1903
+ _rewrite_plan(root, row, plan)
1904
+ with pytest.raises(guard.ContractError, match="bind the frozen held-out set"):
1905
+ guard.validate_prospective_measurement(row, root)
1906
+
1907
+
1908
+ @pytest.mark.parametrize("replicates", [1, 11, True])
1909
+ def test_future_resource_grammar_bounds_replicates(
1910
+ tmp_path: Path, replicates: int | bool
1911
+ ) -> None:
1912
+ root, row, _, _ = _future_bundle(tmp_path)
1913
+ row["replicates"]["per_item"] = replicates
1914
+ with pytest.raises(
1915
+ guard.ContractError,
1916
+ match="2..10 replicates|not of type 'integer'",
1917
+ ):
1918
+ guard.validate_prospective_measurement(row, root)
1919
+
1920
+
1921
+ def test_future_resource_grammar_requires_at_least_two_judges(tmp_path: Path) -> None:
1922
+ root, row, _, _ = _future_bundle(tmp_path)
1923
+ row["judges"].pop()
1924
+ with pytest.raises(guard.ContractError, match="same 2..8 sorted judges"):
1925
+ guard.validate_prospective_measurement(row, root)