psyclaw 0.27.23 → 0.28.1

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 (1069) hide show
  1. package/README.md +11 -5
  2. package/agents/recommended/catalog.json +99 -0
  3. package/dist/apps/panel/index.html +5 -5
  4. package/dist/src/adapters/pi/extension.js +339 -94
  5. package/dist/src/adapters/pi/extension.js.map +1 -1
  6. package/dist/src/adapters/pi/rpc.d.ts +2 -0
  7. package/dist/src/adapters/pi/rpc.js +9 -2
  8. package/dist/src/adapters/pi/rpc.js.map +1 -1
  9. package/dist/src/agents/import.js +44 -32
  10. package/dist/src/agents/import.js.map +1 -1
  11. package/dist/src/agents/recommended-personas.d.ts +42 -0
  12. package/dist/src/agents/recommended-personas.js +135 -0
  13. package/dist/src/agents/recommended-personas.js.map +1 -0
  14. package/dist/src/analysis/hooks.d.ts +1 -0
  15. package/dist/src/analysis/hooks.js +20 -1
  16. package/dist/src/analysis/hooks.js.map +1 -1
  17. package/dist/src/ars/bridge.d.ts +20 -0
  18. package/dist/src/ars/bridge.js +132 -0
  19. package/dist/src/ars/bridge.js.map +1 -0
  20. package/dist/src/ars/contracts.d.ts +55 -0
  21. package/dist/src/ars/contracts.js +2 -0
  22. package/dist/src/ars/contracts.js.map +1 -0
  23. package/dist/src/ars/panel-plan.d.ts +4 -0
  24. package/dist/src/ars/panel-plan.js +11 -0
  25. package/dist/src/ars/panel-plan.js.map +1 -0
  26. package/dist/src/ars/pi-panel-executor.d.ts +30 -0
  27. package/dist/src/ars/pi-panel-executor.js +140 -0
  28. package/dist/src/ars/pi-panel-executor.js.map +1 -0
  29. package/dist/src/ars/profile.d.ts +36 -0
  30. package/dist/src/ars/profile.js +119 -0
  31. package/dist/src/ars/profile.js.map +1 -0
  32. package/dist/src/ars/re-review.d.ts +22 -0
  33. package/dist/src/ars/re-review.js +172 -0
  34. package/dist/src/ars/re-review.js.map +1 -0
  35. package/dist/src/branding.d.ts +2 -4
  36. package/dist/src/branding.js +3 -5
  37. package/dist/src/branding.js.map +1 -1
  38. package/dist/src/bundled-tools.d.ts +3 -0
  39. package/dist/src/bundled-tools.js +21 -0
  40. package/dist/src/bundled-tools.js.map +1 -0
  41. package/dist/src/chat.js +6 -5
  42. package/dist/src/chat.js.map +1 -1
  43. package/dist/src/cli.js +6 -3
  44. package/dist/src/cli.js.map +1 -1
  45. package/dist/src/creation/contracts.d.ts +41 -0
  46. package/dist/src/creation/contracts.js +2 -0
  47. package/dist/src/creation/contracts.js.map +1 -0
  48. package/dist/src/creation/service.d.ts +7 -0
  49. package/dist/src/creation/service.js +208 -0
  50. package/dist/src/creation/service.js.map +1 -0
  51. package/dist/src/index.d.ts +11 -0
  52. package/dist/src/index.js +11 -0
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/install/installer.js +32 -10
  55. package/dist/src/install/installer.js.map +1 -1
  56. package/dist/src/orchestration/bundled-personas.d.ts +16 -0
  57. package/dist/src/orchestration/bundled-personas.js +101 -0
  58. package/dist/src/orchestration/bundled-personas.js.map +1 -0
  59. package/dist/src/orchestration/effects.d.ts +8 -0
  60. package/dist/src/orchestration/effects.js +39 -0
  61. package/dist/src/orchestration/effects.js.map +1 -0
  62. package/dist/src/orchestration/personas.d.ts +16 -0
  63. package/dist/src/orchestration/personas.js +64 -0
  64. package/dist/src/orchestration/personas.js.map +1 -0
  65. package/dist/src/orchestration/pi-executor.d.ts +9 -4
  66. package/dist/src/orchestration/pi-executor.js +55 -22
  67. package/dist/src/orchestration/pi-executor.js.map +1 -1
  68. package/dist/src/orchestration/research-agents.d.ts +3 -7
  69. package/dist/src/orchestration/research-agents.js +5 -69
  70. package/dist/src/orchestration/research-agents.js.map +1 -1
  71. package/dist/src/panel/server.js +19 -4
  72. package/dist/src/panel/server.js.map +1 -1
  73. package/dist/src/project/paths.d.ts +3 -0
  74. package/dist/src/project/paths.js +7 -0
  75. package/dist/src/project/paths.js.map +1 -1
  76. package/dist/src/rules/user-rules.d.ts +8 -0
  77. package/dist/src/rules/user-rules.js +36 -0
  78. package/dist/src/rules/user-rules.js.map +1 -0
  79. package/dist/src/skills/contracts.d.ts +4 -4
  80. package/dist/src/skills/recommended.js +1 -1
  81. package/dist/src/skills/registry.js +49 -28
  82. package/dist/src/skills/registry.js.map +1 -1
  83. package/dist/src/style/cli-ui.d.ts +14 -0
  84. package/dist/src/style/cli-ui.js +45 -1
  85. package/dist/src/style/cli-ui.js.map +1 -1
  86. package/dist/src/tui/skill-manager.js +1 -1
  87. package/dist/src/tui/skill-manager.js.map +1 -1
  88. package/dist/src/updates/update.js +9 -3
  89. package/dist/src/updates/update.js.map +1 -1
  90. package/package.json +15 -3
  91. package/scripts/rebrand-pi.mjs +6 -0
  92. package/skills/recommended/catalog.json +2 -11
  93. package/vendor/ars/.claude/CLAUDE.md +371 -0
  94. package/vendor/ars/.command-invariants.toml +24 -0
  95. package/vendor/ars/CITATION.cff +35 -0
  96. package/vendor/ars/LICENSE +417 -0
  97. package/vendor/ars/MODE_REGISTRY.md +76 -0
  98. package/vendor/ars/NOTICE.md +26 -0
  99. package/vendor/ars/POSITIONING.md +99 -0
  100. package/vendor/ars/PSYCLAW_SOURCE.json +10 -0
  101. package/vendor/ars/README.md +751 -0
  102. package/vendor/ars/SECURITY.md +52 -0
  103. package/vendor/ars/THIRD_PARTY.md +70 -0
  104. package/vendor/ars/academic-paper/SKILL.md +542 -0
  105. package/vendor/ars/academic-paper/agents/abstract_bilingual_agent.md +171 -0
  106. package/vendor/ars/academic-paper/agents/argument_builder_agent.md +276 -0
  107. package/vendor/ars/academic-paper/agents/citation_compliance_agent.md +422 -0
  108. package/vendor/ars/academic-paper/agents/draft_writer_agent.md +656 -0
  109. package/vendor/ars/academic-paper/agents/formatter_agent.md +999 -0
  110. package/vendor/ars/academic-paper/agents/intake_agent.md +393 -0
  111. package/vendor/ars/academic-paper/agents/literature_strategist_agent.md +626 -0
  112. package/vendor/ars/academic-paper/agents/peer_reviewer_agent.md +516 -0
  113. package/vendor/ars/academic-paper/agents/revision_coach_agent.md +334 -0
  114. package/vendor/ars/academic-paper/agents/socratic_mentor_agent.md +527 -0
  115. package/vendor/ars/academic-paper/agents/structure_architect_agent.md +401 -0
  116. package/vendor/ars/academic-paper/agents/visualization_agent.md +441 -0
  117. package/vendor/ars/academic-paper/examples/chinese_paper_example.md +278 -0
  118. package/vendor/ars/academic-paper/examples/clinical_citation_verification_checklist.md +95 -0
  119. package/vendor/ars/academic-paper/examples/clinical_epistemic_status_example.md +100 -0
  120. package/vendor/ars/academic-paper/examples/commitment_ledger_example.md +147 -0
  121. package/vendor/ars/academic-paper/examples/imrad_hei_example.md +234 -0
  122. package/vendor/ars/academic-paper/examples/literature_review_example.md +260 -0
  123. package/vendor/ars/academic-paper/examples/plan_mode_guided_writing.md +600 -0
  124. package/vendor/ars/academic-paper/examples/revision_mode_example.md +344 -0
  125. package/vendor/ars/academic-paper/examples/revision_recovery_example.md +506 -0
  126. package/vendor/ars/academic-paper/examples/version_family_reconciliation_example.md +89 -0
  127. package/vendor/ars/academic-paper/references/abstract_writing_guide.md +169 -0
  128. package/vendor/ars/academic-paper/references/academic_writing_style.md +188 -0
  129. package/vendor/ars/academic-paper/references/anti_leakage_protocol.md +83 -0
  130. package/vendor/ars/academic-paper/references/apa7_chinese_citation_guide.md +364 -0
  131. package/vendor/ars/academic-paper/references/apa7_extended_guide.md +198 -0
  132. package/vendor/ars/academic-paper/references/changelog.md +11 -0
  133. package/vendor/ars/academic-paper/references/citation_format_switcher.md +228 -0
  134. package/vendor/ars/academic-paper/references/committee_correspondence_protocol.md +158 -0
  135. package/vendor/ars/academic-paper/references/credit_authorship_guide.md +308 -0
  136. package/vendor/ars/academic-paper/references/disclosure_mode_protocol.md +478 -0
  137. package/vendor/ars/academic-paper/references/domain_evidence_profiles.md +38 -0
  138. package/vendor/ars/academic-paper/references/failure_paths.md +349 -0
  139. package/vendor/ars/academic-paper/references/funding_statement_guide.md +319 -0
  140. package/vendor/ars/academic-paper/references/hei_domain_glossary.md +169 -0
  141. package/vendor/ars/academic-paper/references/intro_title_rhetoric_guide.md +114 -0
  142. package/vendor/ars/academic-paper/references/journal_submission_guide.md +249 -0
  143. package/vendor/ars/academic-paper/references/latex_template_reference.md +378 -0
  144. package/vendor/ars/academic-paper/references/mode_selection_guide.md +378 -0
  145. package/vendor/ars/academic-paper/references/paper_structure_patterns.md +330 -0
  146. package/vendor/ars/academic-paper/references/plan_mode_protocol.md +112 -0
  147. package/vendor/ars/academic-paper/references/policy_anchor_disclosure_protocol.md +200 -0
  148. package/vendor/ars/academic-paper/references/policy_anchor_table.md +157 -0
  149. package/vendor/ars/academic-paper/references/revision_patch_protocol.md +173 -0
  150. package/vendor/ars/academic-paper/references/statistical_visualization_standards.md +750 -0
  151. package/vendor/ars/academic-paper/references/venue_disclosure_policies.md +259 -0
  152. package/vendor/ars/academic-paper/references/vlm_figure_verification.md +126 -0
  153. package/vendor/ars/academic-paper/references/workflow_phase_details.md +135 -0
  154. package/vendor/ars/academic-paper/references/writing_judgment_framework.md +59 -0
  155. package/vendor/ars/academic-paper/references/writing_quality_check.md +173 -0
  156. package/vendor/ars/academic-paper/templates/bilingual_abstract_template.md +78 -0
  157. package/vendor/ars/academic-paper/templates/case_study_template.md +129 -0
  158. package/vendor/ars/academic-paper/templates/conference_paper_template.md +108 -0
  159. package/vendor/ars/academic-paper/templates/credit_statement_template.md +132 -0
  160. package/vendor/ars/academic-paper/templates/funding_statement_template.md +290 -0
  161. package/vendor/ars/academic-paper/templates/imrad_template.md +183 -0
  162. package/vendor/ars/academic-paper/templates/latex_article_template.tex +199 -0
  163. package/vendor/ars/academic-paper/templates/literature_review_template.md +135 -0
  164. package/vendor/ars/academic-paper/templates/policy_brief_template.md +139 -0
  165. package/vendor/ars/academic-paper/templates/revision_tracking_template.md +199 -0
  166. package/vendor/ars/academic-paper/templates/theoretical_paper_template.md +119 -0
  167. package/vendor/ars/academic-paper-reviewer/SKILL.md +491 -0
  168. package/vendor/ars/academic-paper-reviewer/agents/devils_advocate_reviewer_agent.md +443 -0
  169. package/vendor/ars/academic-paper-reviewer/agents/domain_reviewer_agent.md +412 -0
  170. package/vendor/ars/academic-paper-reviewer/agents/editorial_synthesizer_agent.md +478 -0
  171. package/vendor/ars/academic-paper-reviewer/agents/eic_agent.md +339 -0
  172. package/vendor/ars/academic-paper-reviewer/agents/field_analyst_agent.md +221 -0
  173. package/vendor/ars/academic-paper-reviewer/agents/methodology_reviewer_agent.md +449 -0
  174. package/vendor/ars/academic-paper-reviewer/agents/perspective_reviewer_agent.md +427 -0
  175. package/vendor/ars/academic-paper-reviewer/examples/hei_paper_review_example.md +391 -0
  176. package/vendor/ars/academic-paper-reviewer/examples/interdisciplinary_review_example.md +299 -0
  177. package/vendor/ars/academic-paper-reviewer/examples/subclaim_decomposition_example.md +80 -0
  178. package/vendor/ars/academic-paper-reviewer/references/calibration_mode_protocol.md +256 -0
  179. package/vendor/ars/academic-paper-reviewer/references/changelog.md +10 -0
  180. package/vendor/ars/academic-paper-reviewer/references/editorial_decision_standards.md +236 -0
  181. package/vendor/ars/academic-paper-reviewer/references/guided_mode_protocol.md +34 -0
  182. package/vendor/ars/academic-paper-reviewer/references/integration_guide.md +15 -0
  183. package/vendor/ars/academic-paper-reviewer/references/quality_rubrics.md +84 -0
  184. package/vendor/ars/academic-paper-reviewer/references/re_review_mode_protocol.md +340 -0
  185. package/vendor/ars/academic-paper-reviewer/references/review_criteria_framework.md +98 -0
  186. package/vendor/ars/academic-paper-reviewer/references/review_panel_provenance_protocol.md +197 -0
  187. package/vendor/ars/academic-paper-reviewer/references/review_quality_thinking.md +58 -0
  188. package/vendor/ars/academic-paper-reviewer/references/reviewer_sprint_prompt_source.md +324 -0
  189. package/vendor/ars/academic-paper-reviewer/references/sprint_contract_protocol.md +296 -0
  190. package/vendor/ars/academic-paper-reviewer/references/statistical_reporting_standards.md +505 -0
  191. package/vendor/ars/academic-paper-reviewer/references/top_journals_by_field.md +206 -0
  192. package/vendor/ars/academic-paper-reviewer/templates/editorial_decision_template.md +235 -0
  193. package/vendor/ars/academic-paper-reviewer/templates/peer_review_report_template.md +305 -0
  194. package/vendor/ars/academic-paper-reviewer/templates/revision_response_template.md +248 -0
  195. package/vendor/ars/academic-pipeline/SKILL.md +736 -0
  196. package/vendor/ars/academic-pipeline/agents/claim_ref_alignment_audit_agent.md +382 -0
  197. package/vendor/ars/academic-pipeline/agents/collaboration_depth_agent.md +164 -0
  198. package/vendor/ars/academic-pipeline/agents/integrity_verification_agent.md +870 -0
  199. package/vendor/ars/academic-pipeline/agents/pipeline_orchestrator_agent.md +1379 -0
  200. package/vendor/ars/academic-pipeline/agents/state_tracker_agent.md +622 -0
  201. package/vendor/ars/academic-pipeline/examples/full_pipeline_example.md +482 -0
  202. package/vendor/ars/academic-pipeline/examples/integrity_failure_recovery.md +389 -0
  203. package/vendor/ars/academic-pipeline/examples/mid_entry_example.md +414 -0
  204. package/vendor/ars/academic-pipeline/references/adapters/.gitkeep +0 -0
  205. package/vendor/ars/academic-pipeline/references/adapters/overview.md +153 -0
  206. package/vendor/ars/academic-pipeline/references/ai_research_failure_modes.md +185 -0
  207. package/vendor/ars/academic-pipeline/references/changelog.md +14 -0
  208. package/vendor/ars/academic-pipeline/references/claim_audit_calibration_protocol.md +175 -0
  209. package/vendor/ars/academic-pipeline/references/claim_verification_protocol.md +282 -0
  210. package/vendor/ars/academic-pipeline/references/external_review_protocol.md +131 -0
  211. package/vendor/ars/academic-pipeline/references/integrity_review_protocol.md +110 -0
  212. package/vendor/ars/academic-pipeline/references/literature_corpus_consumers.md +193 -0
  213. package/vendor/ars/academic-pipeline/references/mode_advisor.md +135 -0
  214. package/vendor/ars/academic-pipeline/references/passport_as_reset_boundary.md +132 -0
  215. package/vendor/ars/academic-pipeline/references/pipeline_state_machine.md +405 -0
  216. package/vendor/ars/academic-pipeline/references/plagiarism_detection_protocol.md +239 -0
  217. package/vendor/ars/academic-pipeline/references/process_summary_protocol.md +209 -0
  218. package/vendor/ars/academic-pipeline/references/progress_dashboard_template.md +38 -0
  219. package/vendor/ars/academic-pipeline/references/reinforcement_content.md +15 -0
  220. package/vendor/ars/academic-pipeline/references/reproducibility_audit.md +55 -0
  221. package/vendor/ars/academic-pipeline/references/score_trajectory_protocol.md +78 -0
  222. package/vendor/ars/academic-pipeline/references/team_collaboration_protocol.md +261 -0
  223. package/vendor/ars/academic-pipeline/references/two_stage_review_protocol.md +27 -0
  224. package/vendor/ars/academic-pipeline/templates/pipeline_status_template.md +146 -0
  225. package/vendor/ars/agents/report_compiler_agent.md +341 -0
  226. package/vendor/ars/agents/research_architect_agent.md +298 -0
  227. package/vendor/ars/agents/synthesis_agent.md +356 -0
  228. package/vendor/ars/commands/ars-3w.md +10 -0
  229. package/vendor/ars/commands/ars-abstract.md +10 -0
  230. package/vendor/ars/commands/ars-cache-invalidate.md +20 -0
  231. package/vendor/ars/commands/ars-citation-check.md +10 -0
  232. package/vendor/ars/commands/ars-disclosure.md +10 -0
  233. package/vendor/ars/commands/ars-format-convert.md +10 -0
  234. package/vendor/ars/commands/ars-full.md +9 -0
  235. package/vendor/ars/commands/ars-lit-review.md +12 -0
  236. package/vendor/ars/commands/ars-mark-read.md +18 -0
  237. package/vendor/ars/commands/ars-outline.md +10 -0
  238. package/vendor/ars/commands/ars-plan.md +10 -0
  239. package/vendor/ars/commands/ars-rebuttal-audit.md +12 -0
  240. package/vendor/ars/commands/ars-reviewer.md +9 -0
  241. package/vendor/ars/commands/ars-revision-coach.md +9 -0
  242. package/vendor/ars/commands/ars-revision.md +10 -0
  243. package/vendor/ars/commands/ars-unmark-read.md +16 -0
  244. package/vendor/ars/deep-research/SKILL.md +600 -0
  245. package/vendor/ars/deep-research/agents/bibliography_agent.md +473 -0
  246. package/vendor/ars/deep-research/agents/devils_advocate_agent.md +192 -0
  247. package/vendor/ars/deep-research/agents/editor_in_chief_agent.md +167 -0
  248. package/vendor/ars/deep-research/agents/ethics_review_agent.md +267 -0
  249. package/vendor/ars/deep-research/agents/meta_analysis_agent.md +325 -0
  250. package/vendor/ars/deep-research/agents/monitoring_agent.md +209 -0
  251. package/vendor/ars/deep-research/agents/report_compiler_agent.md +341 -0
  252. package/vendor/ars/deep-research/agents/research_architect_agent.md +298 -0
  253. package/vendor/ars/deep-research/agents/research_question_agent.md +216 -0
  254. package/vendor/ars/deep-research/agents/risk_of_bias_agent.md +231 -0
  255. package/vendor/ars/deep-research/agents/socratic_mentor_agent.md +764 -0
  256. package/vendor/ars/deep-research/agents/source_verification_agent.md +219 -0
  257. package/vendor/ars/deep-research/agents/synthesis_agent.md +356 -0
  258. package/vendor/ars/deep-research/agents/timeline_extraction_agent.md +99 -0
  259. package/vendor/ars/deep-research/examples/exploratory_research.md +157 -0
  260. package/vendor/ars/deep-research/examples/fact_check_mode.md +173 -0
  261. package/vendor/ars/deep-research/examples/handoff_to_paper.md +318 -0
  262. package/vendor/ars/deep-research/examples/idea_diversity_coverage_gap_advisory.md +64 -0
  263. package/vendor/ars/deep-research/examples/policy_analysis.md +161 -0
  264. package/vendor/ars/deep-research/examples/review_mode.md +253 -0
  265. package/vendor/ars/deep-research/examples/socratic_guided_research.md +331 -0
  266. package/vendor/ars/deep-research/examples/systematic_review.md +133 -0
  267. package/vendor/ars/deep-research/references/apa7_style_guide.md +162 -0
  268. package/vendor/ars/deep-research/references/argumentation_reasoning_framework.md +68 -0
  269. package/vendor/ars/deep-research/references/arxiv_api_protocol.md +76 -0
  270. package/vendor/ars/deep-research/references/changelog.md +22 -0
  271. package/vendor/ars/deep-research/references/chinese_literature_api_protocol.md +317 -0
  272. package/vendor/ars/deep-research/references/cross_agent_quality_definitions.md +14 -0
  273. package/vendor/ars/deep-research/references/crossref_api_protocol.md +84 -0
  274. package/vendor/ars/deep-research/references/equator_reporting_guidelines.md +482 -0
  275. package/vendor/ars/deep-research/references/ethics_checklist.md +282 -0
  276. package/vendor/ars/deep-research/references/failure_paths.md +355 -0
  277. package/vendor/ars/deep-research/references/interdisciplinary_bridges.md +292 -0
  278. package/vendor/ars/deep-research/references/irb_decision_tree.md +315 -0
  279. package/vendor/ars/deep-research/references/literature_monitoring_strategies.md +263 -0
  280. package/vendor/ars/deep-research/references/logical_fallacies.md +192 -0
  281. package/vendor/ars/deep-research/references/methodology_patterns.md +462 -0
  282. package/vendor/ars/deep-research/references/mode_selection_guide.md +331 -0
  283. package/vendor/ars/deep-research/references/openalex_api_protocol.md +82 -0
  284. package/vendor/ars/deep-research/references/preregistration_guide.md +324 -0
  285. package/vendor/ars/deep-research/references/semantic_scholar_api_protocol.md +107 -0
  286. package/vendor/ars/deep-research/references/socratic_mode_protocol.md +99 -0
  287. package/vendor/ars/deep-research/references/socratic_questioning_framework.md +232 -0
  288. package/vendor/ars/deep-research/references/source_quality_hierarchy.md +188 -0
  289. package/vendor/ars/deep-research/references/systematic_review_protocol.md +95 -0
  290. package/vendor/ars/deep-research/references/systematic_review_toolkit.md +353 -0
  291. package/vendor/ars/deep-research/templates/evidence_assessment_template.md +127 -0
  292. package/vendor/ars/deep-research/templates/literature_matrix_template.md +85 -0
  293. package/vendor/ars/deep-research/templates/preregistration_template.md +318 -0
  294. package/vendor/ars/deep-research/templates/prisma_protocol_template.md +248 -0
  295. package/vendor/ars/deep-research/templates/prisma_report_template.md +415 -0
  296. package/vendor/ars/deep-research/templates/research_brief_template.md +93 -0
  297. package/vendor/ars/package.json +24 -0
  298. package/vendor/ars/pi/README.md +161 -0
  299. package/vendor/ars/pi/package.json +26 -0
  300. package/vendor/ars/pi/wrapper.js +193 -0
  301. package/vendor/ars/pi/wrapper.test.mjs +201 -0
  302. package/vendor/ars/pyproject.toml +2 -0
  303. package/vendor/ars/requirements-pdf-content-classifier.txt +5 -0
  304. package/vendor/ars/scripts/_block_parser.py +396 -0
  305. package/vendor/ars/scripts/_ci_pytest_manifest.toml +661 -0
  306. package/vendor/ars/scripts/_claim_audit_constants.py +268 -0
  307. package/vendor/ars/scripts/_e4_evidence.py +110 -0
  308. package/vendor/ars/scripts/_eval_threshold_gate.py +73 -0
  309. package/vendor/ars/scripts/_markdown_lint_util.py +224 -0
  310. package/vendor/ars/scripts/_next_verified_at_ms.py +176 -0
  311. package/vendor/ars/scripts/_passport_yaml.py +53 -0
  312. package/vendor/ars/scripts/_skill_lint.py +254 -0
  313. package/vendor/ars/scripts/_text_similarity.py +141 -0
  314. package/vendor/ars/scripts/adapters/README.md +89 -0
  315. package/vendor/ars/scripts/adapters/_common.py +209 -0
  316. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_passport.yaml +25 -0
  317. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_rejection_log.yaml +18 -0
  318. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Chen2024_AIAssessment.pdf +0 -0
  319. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Wang_2023_formative_feedback.pdf +0 -0
  320. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/paper1.pdf +0 -0
  321. 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
  322. package/vendor/ars/scripts/adapters/examples/obsidian/expected_passport.yaml +40 -0
  323. package/vendor/ars/scripts/adapters/examples/obsidian/expected_rejection_log.yaml +13 -0
  324. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.gitkeep +0 -0
  325. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.obsidian/app.json +1 -0
  326. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/_templates/tmpl.md +7 -0
  327. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/chen2024ai.md +13 -0
  328. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/invalid.md +1 -0
  329. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/wang2023formative.md +10 -0
  330. package/vendor/ars/scripts/adapters/examples/zotero/expected_passport.yaml +34 -0
  331. package/vendor/ars/scripts/adapters/examples/zotero/expected_rejection_log.yaml +34 -0
  332. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/.gitkeep +0 -0
  333. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/export.json +43 -0
  334. package/vendor/ars/scripts/adapters/folder_scan.py +214 -0
  335. package/vendor/ars/scripts/adapters/obsidian.py +336 -0
  336. package/vendor/ars/scripts/adapters/tests/.gitkeep +0 -0
  337. package/vendor/ars/scripts/adapters/tests/conftest.py +77 -0
  338. package/vendor/ars/scripts/adapters/tests/test_check_corpus_consumer_protocol.py +632 -0
  339. package/vendor/ars/scripts/adapters/tests/test_check_literature_corpus_schema.py +631 -0
  340. package/vendor/ars/scripts/adapters/tests/test_common.py +365 -0
  341. package/vendor/ars/scripts/adapters/tests/test_conftest.py +96 -0
  342. package/vendor/ars/scripts/adapters/tests/test_folder_scan.py +260 -0
  343. package/vendor/ars/scripts/adapters/tests/test_literature_corpus_entry_schema.py +745 -0
  344. package/vendor/ars/scripts/adapters/tests/test_obsidian.py +357 -0
  345. package/vendor/ars/scripts/adapters/tests/test_rejection_log_schema.py +271 -0
  346. package/vendor/ars/scripts/adapters/tests/test_sync_adapter_docs.py +88 -0
  347. package/vendor/ars/scripts/adapters/tests/test_zotero.py +454 -0
  348. package/vendor/ars/scripts/adapters/zotero.py +318 -0
  349. package/vendor/ars/scripts/adjudication_activity.py +1592 -0
  350. package/vendor/ars/scripts/announce-ars-loaded.sh +144 -0
  351. package/vendor/ars/scripts/ars_anchorize_draft.py +170 -0
  352. package/vendor/ars/scripts/ars_apply_revision_patch.py +912 -0
  353. package/vendor/ars/scripts/ars_cache_invalidate.py +40 -0
  354. package/vendor/ars/scripts/ars_mark_read.py +521 -0
  355. package/vendor/ars/scripts/ars_phase_scope_manifest.json +33 -0
  356. package/vendor/ars/scripts/ars_update_check.sh +215 -0
  357. package/vendor/ars/scripts/ars_write_scope_guard.py +506 -0
  358. package/vendor/ars/scripts/arxiv_client.py +222 -0
  359. package/vendor/ars/scripts/audit_snapshot.py +572 -0
  360. package/vendor/ars/scripts/bibliographic_integrity_signals.py +800 -0
  361. package/vendor/ars/scripts/bootstrap_timeline_yaml.py +146 -0
  362. package/vendor/ars/scripts/build_claim_standing_candidate_ledger.py +1238 -0
  363. package/vendor/ars/scripts/build_claim_standing_query_plan.py +643 -0
  364. package/vendor/ars/scripts/build_content_coverage_advisory.py +1205 -0
  365. package/vendor/ars/scripts/build_cross_document_consistency_advisory.py +2332 -0
  366. package/vendor/ars/scripts/build_review_pathway_rule_trace.py +830 -0
  367. package/vendor/ars/scripts/build_submission_packet_manifest.py +2310 -0
  368. package/vendor/ars/scripts/check_215_field_norm.py +173 -0
  369. package/vendor/ars/scripts/check_216_surface_form.py +250 -0
  370. package/vendor/ars/scripts/check_268_nested_commitment_ledger.py +180 -0
  371. package/vendor/ars/scripts/check_390_revision_patch_discipline.py +296 -0
  372. package/vendor/ars/scripts/check_392_citation_verification_intake.py +126 -0
  373. package/vendor/ars/scripts/check_394_submission_policy.py +178 -0
  374. package/vendor/ars/scripts/check_439_format_profile.py +307 -0
  375. package/vendor/ars/scripts/check_619_disclosure_closeout.py +237 -0
  376. package/vendor/ars/scripts/check_630_codex_subscription_transport.py +456 -0
  377. package/vendor/ars/scripts/check_669_review_pathway_rule_trace.py +662 -0
  378. package/vendor/ars/scripts/check_670_revision_roadmap_integration.py +518 -0
  379. package/vendor/ars/scripts/check_673_adjudication_activity.py +684 -0
  380. package/vendor/ars/scripts/check_684_review_criteria_binding.py +557 -0
  381. package/vendor/ars/scripts/check_agents_mirror_sync.py +115 -0
  382. package/vendor/ars/scripts/check_audit_artifact_consistency.py +2313 -0
  383. package/vendor/ars/scripts/check_benchmark_report.py +79 -0
  384. package/vendor/ars/scripts/check_bibliographic_integrity_signals.py +831 -0
  385. package/vendor/ars/scripts/check_calibration_tiers.py +235 -0
  386. package/vendor/ars/scripts/check_changelog_covers_merges.py +289 -0
  387. package/vendor/ars/scripts/check_ci_pytest_manifest.py +204 -0
  388. package/vendor/ars/scripts/check_claim_audit_consistency.py +1664 -0
  389. package/vendor/ars/scripts/check_claim_standing_candidate_ledger_integration.py +500 -0
  390. package/vendor/ars/scripts/check_claim_standing_freshness.py +253 -0
  391. package/vendor/ars/scripts/check_claim_standing_transmissions.py +449 -0
  392. package/vendor/ars/scripts/check_collaboration_depth_rubric.py +180 -0
  393. package/vendor/ars/scripts/check_command_frontmatter_name.py +116 -0
  394. package/vendor/ars/scripts/check_committee_correspondence.py +333 -0
  395. package/vendor/ars/scripts/check_compliance_report.py +108 -0
  396. package/vendor/ars/scripts/check_content_coverage_advisory_integration.py +796 -0
  397. package/vendor/ars/scripts/check_control_availability.py +172 -0
  398. package/vendor/ars/scripts/check_corpus_consumer_protocol.py +404 -0
  399. package/vendor/ars/scripts/check_cross_document_consistency_advisory_integration.py +1191 -0
  400. package/vendor/ars/scripts/check_cross_model_handoff_contract.py +234 -0
  401. package/vendor/ars/scripts/check_cross_model_verification_sync.py +261 -0
  402. package/vendor/ars/scripts/check_data_access_level.py +131 -0
  403. package/vendor/ars/scripts/check_data_flows.py +252 -0
  404. package/vendor/ars/scripts/check_decision_contract.py +464 -0
  405. package/vendor/ars/scripts/check_degradation_registry.py +326 -0
  406. package/vendor/ars/scripts/check_distribution_surface_claims.py +226 -0
  407. package/vendor/ars/scripts/check_domain_evidence_profile.py +538 -0
  408. package/vendor/ars/scripts/check_e4_promotion.py +195 -0
  409. package/vendor/ars/scripts/check_evals_gold_set.py +279 -0
  410. package/vendor/ars/scripts/check_evidence_row_integration.py +396 -0
  411. package/vendor/ars/scripts/check_experiment_provenance.py +117 -0
  412. package/vendor/ars/scripts/check_field_norm_severity.py +144 -0
  413. package/vendor/ars/scripts/check_firm_rules_sync.py +375 -0
  414. package/vendor/ars/scripts/check_heldout_measurement_report.py +1179 -0
  415. package/vendor/ars/scripts/check_human_subjects_output_contract.py +139 -0
  416. package/vendor/ars/scripts/check_human_subjects_reference_migration.py +844 -0
  417. package/vendor/ars/scripts/check_indirect_prompt_injection_no_call.py +328 -0
  418. package/vendor/ars/scripts/check_instruction_data_boundary.py +236 -0
  419. package/vendor/ars/scripts/check_judge_prompt_version.py +125 -0
  420. package/vendor/ars/scripts/check_literature_corpus_schema.py +402 -0
  421. package/vendor/ars/scripts/check_model_tiering.py +223 -0
  422. package/vendor/ars/scripts/check_panel_synthesis.py +1331 -0
  423. package/vendor/ars/scripts/check_passport_reset_contract.py +214 -0
  424. package/vendor/ars/scripts/check_pattern_eval_manifest.py +422 -0
  425. package/vendor/ars/scripts/check_persuasion_invariance_fixtures.py +637 -0
  426. package/vendor/ars/scripts/check_phase_conformance.py +2180 -0
  427. package/vendor/ars/scripts/check_pipeline_boundary_semantics.py +600 -0
  428. package/vendor/ars/scripts/check_pipeline_integrity.py +340 -0
  429. package/vendor/ars/scripts/check_policy_anchor_protocol.py +159 -0
  430. package/vendor/ars/scripts/check_policy_anchor_table.py +286 -0
  431. package/vendor/ars/scripts/check_preprint_venues_consistency.py +123 -0
  432. package/vendor/ars/scripts/check_prisma_trAIce_freshness.py +84 -0
  433. package/vendor/ars/scripts/check_promotion_bakeoff_preregistration.py +1303 -0
  434. package/vendor/ars/scripts/check_ranking_lift.py +323 -0
  435. package/vendor/ars/scripts/check_re_review_synthesis.py +2719 -0
  436. package/vendor/ars/scripts/check_receipt_enum_sync.py +203 -0
  437. package/vendor/ars/scripts/check_repro_lock.py +85 -0
  438. package/vendor/ars/scripts/check_review_pathway_output.py +276 -0
  439. package/vendor/ars/scripts/check_reviewer_data_fences.py +224 -0
  440. package/vendor/ars/scripts/check_reviewer_finding_contract.py +783 -0
  441. package/vendor/ars/scripts/check_reviewer_role_label.py +447 -0
  442. package/vendor/ars/scripts/check_reviewer_scoring_honesty.py +292 -0
  443. package/vendor/ars/scripts/check_reviewer_sprint_prompt_sync.py +409 -0
  444. package/vendor/ars/scripts/check_revision_claim_drift_suite_v2.py +1622 -0
  445. package/vendor/ars/scripts/check_revision_token_conservation.py +263 -0
  446. package/vendor/ars/scripts/check_risk_register.py +280 -0
  447. package/vendor/ars/scripts/check_role_scoped_contract.py +702 -0
  448. package/vendor/ars/scripts/check_rq_framing_patterns.py +184 -0
  449. package/vendor/ars/scripts/check_rubric_weight_consistency.py +32 -0
  450. package/vendor/ars/scripts/check_seeded_defect_fixtures.py +425 -0
  451. package/vendor/ars/scripts/check_setup_cross_model_parity.py +139 -0
  452. package/vendor/ars/scripts/check_spec_consistency.py +1249 -0
  453. package/vendor/ars/scripts/check_sprint_contract.py +371 -0
  454. package/vendor/ars/scripts/check_stage_capability_matrix.py +784 -0
  455. package/vendor/ars/scripts/check_submission_packet_manifest_integration.py +358 -0
  456. package/vendor/ars/scripts/check_surface_form_parity.py +445 -0
  457. package/vendor/ars/scripts/check_task_type.py +22 -0
  458. package/vendor/ars/scripts/check_tools_allowlist.py +538 -0
  459. package/vendor/ars/scripts/check_tortured_phrase_screening_integration.py +1974 -0
  460. package/vendor/ars/scripts/check_v3_10_134_write_scope.py +286 -0
  461. package/vendor/ars/scripts/check_v3_10_policy.py +656 -0
  462. package/vendor/ars/scripts/check_v3_6_6_ab_manifest.py +364 -0
  463. package/vendor/ars/scripts/check_v3_6_7_pattern_protection.py +1366 -0
  464. package/vendor/ars/scripts/check_v3_6_8_audit_scope_block.py +464 -0
  465. package/vendor/ars/scripts/check_v3_6_8_cite_provenance_pipeline.py +231 -0
  466. package/vendor/ars/scripts/check_v3_6_8_frontmatter_trust_schema.py +248 -0
  467. package/vendor/ars/scripts/check_v3_6_8_mark_read_commands.py +79 -0
  468. package/vendor/ars/scripts/check_v3_6_8_pattern_protection.py +941 -0
  469. package/vendor/ars/scripts/check_v3_7_3_three_layer_citation.py +318 -0
  470. package/vendor/ars/scripts/check_v3_8_annotation_literal_sync.py +228 -0
  471. package/vendor/ars/scripts/check_v3_9_0_triangulation.py +366 -0
  472. package/vendor/ars/scripts/check_v3_9_2_phase_boundary.py +270 -0
  473. package/vendor/ars/scripts/check_v3_9_4_temporal_verification.py +139 -0
  474. package/vendor/ars/scripts/check_venue_disclosure_policies.py +63 -0
  475. package/vendor/ars/scripts/check_version_consistency.py +826 -0
  476. package/vendor/ars/scripts/check_workflow_classification.py +223 -0
  477. package/vendor/ars/scripts/chinese_literature_client.py +1938 -0
  478. package/vendor/ars/scripts/citation_verification_summary.py +85 -0
  479. package/vendor/ars/scripts/claim_audit_calibration.py +517 -0
  480. package/vendor/ars/scripts/claim_audit_finalizer.py +456 -0
  481. package/vendor/ars/scripts/claim_audit_pipeline.py +1594 -0
  482. package/vendor/ars/scripts/claim_registry_coverage.py +493 -0
  483. package/vendor/ars/scripts/claim_standing_discovery.py +784 -0
  484. package/vendor/ars/scripts/claim_standing_stance_runner.py +758 -0
  485. package/vendor/ars/scripts/claim_standing_stance_scorer.py +239 -0
  486. package/vendor/ars/scripts/claim_strength_drift_disposition.py +666 -0
  487. package/vendor/ars/scripts/contamination_signals.py +689 -0
  488. package/vendor/ars/scripts/corpus_consumer_manifest.json +19 -0
  489. package/vendor/ars/scripts/cross_model_codex_transport.py +1374 -0
  490. package/vendor/ars/scripts/cross_model_codex_verify.sh +6 -0
  491. package/vendor/ars/scripts/cross_model_handoff.py +359 -0
  492. package/vendor/ars/scripts/cross_model_smoke_test.sh +183 -0
  493. package/vendor/ars/scripts/cross_model_smoke_test_codex.sh +35 -0
  494. package/vendor/ars/scripts/cross_model_verification/gemini_is_grounded.jq +45 -0
  495. package/vendor/ars/scripts/cross_model_verification/gemini_sources.jq +45 -0
  496. package/vendor/ars/scripts/cross_model_verification/normalize_compat_verdict.py +57 -0
  497. package/vendor/ars/scripts/cross_model_verification/openai_has_completed_web_search.jq +15 -0
  498. package/vendor/ars/scripts/cross_model_verification/openai_sources.jq +17 -0
  499. package/vendor/ars/scripts/cross_model_verification/openai_text.jq +11 -0
  500. package/vendor/ars/scripts/crossref_client.py +225 -0
  501. package/vendor/ars/scripts/dispatch_e4_panel.py +2731 -0
  502. package/vendor/ars/scripts/evidence_rows.py +2043 -0
  503. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3.json +32 -0
  504. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_input.json +27 -0
  505. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime.json +32 -0
  506. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime_input.json +27 -0
  507. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override.json +50 -0
  508. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override_action.json +14 -0
  509. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_pass.json +44 -0
  510. package/vendor/ars/scripts/fixtures/adjudication_activity/explicit_user_request_log.json +26 -0
  511. package/vendor/ars/scripts/fixtures/adjudication_activity/mandatory_checkpoint_log.json +116 -0
  512. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/README.md +56 -0
  513. 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
  514. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  515. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  516. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  517. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a7_orphan_completion/2026-04-30T15-22-04Z-d8f3.jsonl +3 -0
  518. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +26 -0
  519. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  520. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  521. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  522. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +24 -0
  523. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  524. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  525. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.verdict.yaml +12 -0
  526. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction.json +46 -0
  527. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction_check_attestation.json +44 -0
  528. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase.json +44 -0
  529. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_abstract_missing.json +107 -0
  530. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_detected.json +124 -0
  531. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/expected_outcomes.json +77 -0
  532. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/manifest.yaml +37 -0
  533. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/001-valid-doi-test.json +20 -0
  534. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/002-valid-arxiv-test.json +19 -0
  535. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/003-fabricated-test.json +20 -0
  536. package/vendor/ars/scripts/fixtures/claim_audit_calibration/gold_set.json +344 -0
  537. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/query_plan.json +108 -0
  538. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/retrieval_input.json +179 -0
  539. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/concern_tracker.json +129 -0
  540. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/response_skeleton.md +19 -0
  541. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/source_letter.txt +9 -0
  542. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_draft.json +48 -0
  543. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_inventory.json +38 -0
  544. package/vendor/ars/scripts/fixtures/content_coverage_advisory/packet/consent.txt +1 -0
  545. package/vendor/ars/scripts/fixtures/content_coverage_advisory/session_sources.json +3 -0
  546. package/vendor/ars/scripts/fixtures/cross_document_consistency/README.md +6 -0
  547. package/vendor/ars/scripts/fixtures/cross_document_consistency/accepted_draft.md +35 -0
  548. package/vendor/ars/scripts/fixtures/cross_document_consistency/cases.json +75 -0
  549. package/vendor/ars/scripts/fixtures/cross_document_consistency/preregistration.md +5 -0
  550. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/forbidden_event.jsonl +4 -0
  551. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/grounded_verified.jsonl +3 -0
  552. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/malformed.jsonl +3 -0
  553. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/missing_search.jsonl +2 -0
  554. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/multiple_finals.jsonl +4 -0
  555. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/not_found.jsonl +3 -0
  556. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/unbound_source.jsonl +3 -0
  557. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/wrong_search_shape.jsonl +3 -0
  558. package/vendor/ars/scripts/fixtures/evidence_rows/phase_e_inputs.json +114 -0
  559. package/vendor/ars/scripts/fixtures/evidence_rows/session_sources.json +5 -0
  560. package/vendor/ars/scripts/fixtures/human_subjects_authority/cross-border-us-tw-gdpr.json +71 -0
  561. package/vendor/ars/scripts/fixtures/human_subjects_authority/gdpr-member-state-unresolved.json +62 -0
  562. package/vendor/ars/scripts/fixtures/human_subjects_authority/missing-data-axis.json +45 -0
  563. package/vendor/ars/scripts/fixtures/human_subjects_authority/no-profile.json +33 -0
  564. package/vendor/ars/scripts/fixtures/human_subjects_authority/tw-gdpr-two-axis.json +74 -0
  565. package/vendor/ars/scripts/fixtures/human_subjects_authority/us-gdpr-two-axis.json +74 -0
  566. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/lint-near-misses.json +72 -0
  567. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/no-profile-request.json +18 -0
  568. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/tw-candidates-request.json +63 -0
  569. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/us-candidates-request.json +77 -0
  570. package/vendor/ars/scripts/fixtures/review_target_context/exact-declaration.json +24 -0
  571. package/vendor/ars/scripts/fixtures/review_target_context/field-general-declaration.json +24 -0
  572. package/vendor/ars/scripts/fixtures/review_target_context/msr-2027-technical-full-declaration.json +24 -0
  573. package/vendor/ars/scripts/fixtures/review_target_context/synthetic-registry.json +92 -0
  574. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/README.md +21 -0
  575. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_attested_only.json +55 -0
  576. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_machine_supported.json +49 -0
  577. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_not_isolated.json +56 -0
  578. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_unknown.json +49 -0
  579. package/vendor/ars/scripts/fixtures/submission_package/clean/paper.md +16 -0
  580. package/vendor/ars/scripts/fixtures/submission_package/clean/references.bib +13 -0
  581. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/paper.md +11 -0
  582. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/references.bib +13 -0
  583. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/paper.tex +9 -0
  584. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/references.bib +13 -0
  585. package/vendor/ars/scripts/fixtures/submission_package/marker_no_join/paper.md +7 -0
  586. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/paper.md +8 -0
  587. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/references.bib +6 -0
  588. package/vendor/ars/scripts/fixtures/submission_package/passports/corpus_only.yaml +9 -0
  589. package/vendor/ars/scripts/fixtures/submission_package/passports/summary_join.yaml +16 -0
  590. package/vendor/ars/scripts/fixtures/submission_package/profiles/full.yaml +15 -0
  591. package/vendor/ars/scripts/fixtures/submission_package/profiles/tight.yaml +15 -0
  592. package/vendor/ars/scripts/fixtures/submission_package/summary_join/paper.md +7 -0
  593. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/paper.md +9 -0
  594. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/references.bib +13 -0
  595. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/paper.md +26 -0
  596. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/references.bib +13 -0
  597. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/paper.md +20 -0
  598. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/references.bib +13 -0
  599. package/vendor/ars/scripts/fixtures/submission_packet_manifest/base_inventory.json +101 -0
  600. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/consent-materials.txt +3 -0
  601. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/training-certificate.txt +2 -0
  602. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/tw-consent-materials.txt +3 -0
  603. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/corpus_input.yaml +30 -0
  604. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.md +36 -0
  605. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.tex +21 -0
  606. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/seed_expectations.json +218 -0
  607. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot.json +164 -0
  608. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot_manifest.json +29 -0
  609. package/vendor/ars/scripts/fixtures/transport_bodies/README.md +55 -0
  610. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/empty_feed.xml +10 -0
  611. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/error_5xx.html +7 -0
  612. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/id_hit.xml +26 -0
  613. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/README.md +69 -0
  614. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/cnki_landing_page.html +13 -0
  615. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/error_5xx.html +2 -0
  616. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_ambiguous.json +16 -0
  617. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_hit.json +16 -0
  618. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_zero.json +14 -0
  619. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_hit.json +15 -0
  620. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_zero.json +13 -0
  621. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_hit.json +43 -0
  622. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_issn_mismatch.json +31 -0
  623. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_no_doi.json +31 -0
  624. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_unknown_ra.json +34 -0
  625. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_year_mismatch.json +31 -0
  626. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_absent.json +4 -0
  627. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_exists.json +16 -0
  628. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_internal_error.json +4 -0
  629. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_hit.json +25 -0
  630. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_other_title.json +18 -0
  631. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_cnki.json +6 -0
  632. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_crossref.json +6 -0
  633. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_istic.json +6 -0
  634. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_unknown_prefix.json +6 -0
  635. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/doi_hit.json +24 -0
  636. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/error_5xx.html +7 -0
  637. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/title_search_miss.json +15 -0
  638. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/doi_hit.json +29 -0
  639. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/error_5xx.json +4 -0
  640. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/title_search_miss.json +11 -0
  641. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/doi_hit.json +14 -0
  642. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/error_5xx.json +3 -0
  643. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/title_search_miss.json +5 -0
  644. package/vendor/ars/scripts/human_read_attestation_resolver.py +467 -0
  645. package/vendor/ars/scripts/ideation_diversity_assignment_gate.py +430 -0
  646. package/vendor/ars/scripts/inquiry_branch_ledger.py +2540 -0
  647. package/vendor/ars/scripts/legacy/ars_apply_revision_patch_v1_0.py +715 -0
  648. package/vendor/ars/scripts/legacy/check_re_review_synthesis_v1_0.py +2215 -0
  649. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_10.py +223 -0
  650. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_7_3.py +277 -0
  651. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_9_0.py +304 -0
  652. package/vendor/ars/scripts/model_tiering_manifest.json +46 -0
  653. package/vendor/ars/scripts/openalex_client.py +232 -0
  654. package/vendor/ars/scripts/parse_audit_verdict.py +802 -0
  655. package/vendor/ars/scripts/pdf_content_classifier_worker.py +176 -0
  656. package/vendor/ars/scripts/pdf_read_preflight.py +1455 -0
  657. package/vendor/ars/scripts/policy_anchor_disclosure_referee.py +354 -0
  658. package/vendor/ars/scripts/recompute_receipts.py +1414 -0
  659. package/vendor/ars/scripts/render_claim_standing_view.py +374 -0
  660. package/vendor/ars/scripts/render_eval_comment.py +130 -0
  661. package/vendor/ars/scripts/render_harness_retirement_issue.py +167 -0
  662. package/vendor/ars/scripts/repro_lock_validation.py +90 -0
  663. package/vendor/ars/scripts/research_workflow_profile.py +1079 -0
  664. package/vendor/ars/scripts/resolve_human_subjects_authority.py +1158 -0
  665. package/vendor/ars/scripts/resolve_review_target_context.py +683 -0
  666. package/vendor/ars/scripts/resume_e4_record.py +509 -0
  667. package/vendor/ars/scripts/retraction_status.py +484 -0
  668. package/vendor/ars/scripts/review_criteria_binding.py +889 -0
  669. package/vendor/ars/scripts/review_panel_provenance.py +744 -0
  670. package/vendor/ars/scripts/revision_roadmap.py +1967 -0
  671. package/vendor/ars/scripts/run_ci_pytest_manifest.py +116 -0
  672. package/vendor/ars/scripts/run_codex_audit.sh +1191 -0
  673. package/vendor/ars/scripts/run_evals.py +513 -0
  674. package/vendor/ars/scripts/run_ideation_diversity_no_call.py +3505 -0
  675. package/vendor/ars/scripts/run_indirect_prompt_injection_no_call.py +3330 -0
  676. package/vendor/ars/scripts/run_indirect_prompt_injection_probe.py +399 -0
  677. package/vendor/ars/scripts/run_review_criteria_constructive_value.py +1895 -0
  678. package/vendor/ars/scripts/run_role_topology_utility_dry_run.py +606 -0
  679. package/vendor/ars/scripts/score_review_criteria_constructive_value.py +617 -0
  680. package/vendor/ars/scripts/semantic_scholar_client.py +291 -0
  681. package/vendor/ars/scripts/slr_lineage.py +59 -0
  682. package/vendor/ars/scripts/sync_adapter_docs.py +118 -0
  683. package/vendor/ars/scripts/temporal_integrity_audit.py +840 -0
  684. package/vendor/ars/scripts/test_431_exact_or_bust.py +253 -0
  685. package/vendor/ars/scripts/test__eval_threshold_gate.py +125 -0
  686. package/vendor/ars/scripts/test__markdown_lint_util.py +129 -0
  687. package/vendor/ars/scripts/test__next_verified_at_ms.py +256 -0
  688. package/vendor/ars/scripts/test_adjacent_framing_probe_lint.py +171 -0
  689. package/vendor/ars/scripts/test_adjudication_activity.py +1515 -0
  690. package/vendor/ars/scripts/test_ars_anchorize_draft.py +178 -0
  691. package/vendor/ars/scripts/test_ars_apply_revision_patch.py +1335 -0
  692. package/vendor/ars/scripts/test_ars_cache_invalidate.py +51 -0
  693. package/vendor/ars/scripts/test_ars_mark_read.py +910 -0
  694. package/vendor/ars/scripts/test_ars_update_check.py +816 -0
  695. package/vendor/ars/scripts/test_ars_write_scope_guard.py +790 -0
  696. package/vendor/ars/scripts/test_arxiv_client.py +374 -0
  697. package/vendor/ars/scripts/test_audit_schemas.py +560 -0
  698. package/vendor/ars/scripts/test_audit_snapshot_render_section_0.py +105 -0
  699. package/vendor/ars/scripts/test_block_parser.py +259 -0
  700. package/vendor/ars/scripts/test_bootstrap_timeline_yaml.py +148 -0
  701. package/vendor/ars/scripts/test_build_claim_standing_candidate_ledger.py +1203 -0
  702. package/vendor/ars/scripts/test_build_claim_standing_query_plan.py +791 -0
  703. package/vendor/ars/scripts/test_build_submission_packet_manifest.py +2644 -0
  704. package/vendor/ars/scripts/test_check_215_field_norm.py +238 -0
  705. package/vendor/ars/scripts/test_check_216_surface_form.py +341 -0
  706. package/vendor/ars/scripts/test_check_268_nested_commitment_ledger.py +194 -0
  707. package/vendor/ars/scripts/test_check_390_revision_patch_discipline.py +279 -0
  708. package/vendor/ars/scripts/test_check_392_citation_verification_intake.py +144 -0
  709. package/vendor/ars/scripts/test_check_394_submission_policy.py +200 -0
  710. package/vendor/ars/scripts/test_check_439_format_profile.py +252 -0
  711. package/vendor/ars/scripts/test_check_619_disclosure_closeout.py +158 -0
  712. package/vendor/ars/scripts/test_check_630_codex_subscription_transport.py +245 -0
  713. package/vendor/ars/scripts/test_check_669_review_pathway_rule_trace.py +304 -0
  714. package/vendor/ars/scripts/test_check_670_revision_roadmap_integration.py +260 -0
  715. package/vendor/ars/scripts/test_check_673_adjudication_activity.py +367 -0
  716. package/vendor/ars/scripts/test_check_684_review_criteria_binding.py +274 -0
  717. package/vendor/ars/scripts/test_check_agents_mirror_sync.py +137 -0
  718. package/vendor/ars/scripts/test_check_audit_artifact_consistency.py +2133 -0
  719. package/vendor/ars/scripts/test_check_benchmark_report.py +117 -0
  720. package/vendor/ars/scripts/test_check_bibliographic_integrity_signals.py +609 -0
  721. package/vendor/ars/scripts/test_check_calibration_tiers.py +376 -0
  722. package/vendor/ars/scripts/test_check_changelog_covers_merges.py +509 -0
  723. package/vendor/ars/scripts/test_check_ci_pytest_manifest.py +425 -0
  724. package/vendor/ars/scripts/test_check_claim_standing_candidate_ledger_integration.py +256 -0
  725. package/vendor/ars/scripts/test_check_claim_standing_freshness.py +277 -0
  726. package/vendor/ars/scripts/test_check_collaboration_depth_rubric.py +239 -0
  727. package/vendor/ars/scripts/test_check_command_frontmatter_name.py +178 -0
  728. package/vendor/ars/scripts/test_check_committee_correspondence.py +298 -0
  729. package/vendor/ars/scripts/test_check_compliance_report.py +381 -0
  730. package/vendor/ars/scripts/test_check_content_coverage_advisory_integration.py +308 -0
  731. package/vendor/ars/scripts/test_check_control_availability.py +361 -0
  732. package/vendor/ars/scripts/test_check_cross_document_consistency_advisory_integration.py +698 -0
  733. package/vendor/ars/scripts/test_check_cross_model_handoff_contract.py +301 -0
  734. package/vendor/ars/scripts/test_check_cross_model_verification_sync.py +203 -0
  735. package/vendor/ars/scripts/test_check_data_access_level.py +227 -0
  736. package/vendor/ars/scripts/test_check_data_flows.py +382 -0
  737. package/vendor/ars/scripts/test_check_decision_contract.py +387 -0
  738. package/vendor/ars/scripts/test_check_degradation_registry.py +270 -0
  739. package/vendor/ars/scripts/test_check_distribution_surface_claims.py +225 -0
  740. package/vendor/ars/scripts/test_check_domain_evidence_profile.py +439 -0
  741. package/vendor/ars/scripts/test_check_e4_promotion.py +163 -0
  742. package/vendor/ars/scripts/test_check_evals_gold_set.py +312 -0
  743. package/vendor/ars/scripts/test_check_evidence_row_integration.py +187 -0
  744. package/vendor/ars/scripts/test_check_field_norm_severity.py +173 -0
  745. package/vendor/ars/scripts/test_check_firm_rules_sync.py +342 -0
  746. package/vendor/ars/scripts/test_check_heldout_measurement_report.py +1508 -0
  747. package/vendor/ars/scripts/test_check_human_subjects_output_contract.py +129 -0
  748. package/vendor/ars/scripts/test_check_human_subjects_reference_migration.py +756 -0
  749. package/vendor/ars/scripts/test_check_instruction_data_boundary.py +204 -0
  750. package/vendor/ars/scripts/test_check_judge_prompt_version.py +90 -0
  751. package/vendor/ars/scripts/test_check_model_tiering.py +236 -0
  752. package/vendor/ars/scripts/test_check_panel_synthesis.py +1658 -0
  753. package/vendor/ars/scripts/test_check_passport_reset_contract.py +249 -0
  754. package/vendor/ars/scripts/test_check_pattern_eval_manifest.py +381 -0
  755. package/vendor/ars/scripts/test_check_persuasion_invariance_fixtures.py +591 -0
  756. package/vendor/ars/scripts/test_check_phase_conformance.py +4366 -0
  757. package/vendor/ars/scripts/test_check_pipeline_boundary_semantics.py +931 -0
  758. package/vendor/ars/scripts/test_check_pipeline_integrity.py +243 -0
  759. package/vendor/ars/scripts/test_check_policy_anchor_protocol.py +236 -0
  760. package/vendor/ars/scripts/test_check_policy_anchor_table.py +295 -0
  761. package/vendor/ars/scripts/test_check_prisma_trAIce_freshness.py +68 -0
  762. package/vendor/ars/scripts/test_check_promotion_bakeoff_preregistration.py +799 -0
  763. package/vendor/ars/scripts/test_check_ranking_lift.py +377 -0
  764. package/vendor/ars/scripts/test_check_re_review_synthesis.py +3398 -0
  765. package/vendor/ars/scripts/test_check_receipt_enum_sync.py +176 -0
  766. package/vendor/ars/scripts/test_check_repro_lock.py +107 -0
  767. package/vendor/ars/scripts/test_check_reviewer_data_fences.py +334 -0
  768. package/vendor/ars/scripts/test_check_reviewer_finding_contract.py +1107 -0
  769. package/vendor/ars/scripts/test_check_reviewer_role_label.py +491 -0
  770. package/vendor/ars/scripts/test_check_reviewer_scoring_honesty.py +222 -0
  771. package/vendor/ars/scripts/test_check_reviewer_sprint_prompt_sync.py +373 -0
  772. package/vendor/ars/scripts/test_check_revision_claim_drift_suite_v2.py +1925 -0
  773. package/vendor/ars/scripts/test_check_revision_token_conservation.py +398 -0
  774. package/vendor/ars/scripts/test_check_risk_register.py +336 -0
  775. package/vendor/ars/scripts/test_check_role_scoped_contract.py +1104 -0
  776. package/vendor/ars/scripts/test_check_rq_framing_patterns.py +110 -0
  777. package/vendor/ars/scripts/test_check_rubric_weight_consistency.py +32 -0
  778. package/vendor/ars/scripts/test_check_seeded_defect_fixtures.py +392 -0
  779. package/vendor/ars/scripts/test_check_setup_cross_model_parity.py +121 -0
  780. package/vendor/ars/scripts/test_check_spec_consistency.py +1081 -0
  781. package/vendor/ars/scripts/test_check_sprint_contract.py +458 -0
  782. package/vendor/ars/scripts/test_check_stage_capability_matrix.py +698 -0
  783. package/vendor/ars/scripts/test_check_submission_packet_manifest_integration.py +177 -0
  784. package/vendor/ars/scripts/test_check_surface_form_parity.py +417 -0
  785. package/vendor/ars/scripts/test_check_task_type.py +116 -0
  786. package/vendor/ars/scripts/test_check_tools_allowlist.py +835 -0
  787. package/vendor/ars/scripts/test_check_tortured_phrase_screening_integration.py +1306 -0
  788. package/vendor/ars/scripts/test_check_v3_10_134_write_scope.py +251 -0
  789. package/vendor/ars/scripts/test_check_v3_10_policy.py +547 -0
  790. package/vendor/ars/scripts/test_check_v3_6_7_pattern_protection.py +960 -0
  791. package/vendor/ars/scripts/test_check_v3_6_8_audit_scope_block.py +1000 -0
  792. package/vendor/ars/scripts/test_check_v3_6_8_cite_provenance_pipeline.py +454 -0
  793. package/vendor/ars/scripts/test_check_v3_6_8_frontmatter_trust_schema.py +581 -0
  794. package/vendor/ars/scripts/test_check_v3_6_8_mark_read_commands.py +120 -0
  795. package/vendor/ars/scripts/test_check_v3_6_8_pattern_protection.py +1138 -0
  796. package/vendor/ars/scripts/test_check_v3_7_3_three_layer_citation.py +566 -0
  797. package/vendor/ars/scripts/test_check_v3_8_annotation_literal_sync.py +262 -0
  798. package/vendor/ars/scripts/test_check_v3_9_0_triangulation.py +321 -0
  799. package/vendor/ars/scripts/test_check_v3_9_2_phase_boundary.py +190 -0
  800. package/vendor/ars/scripts/test_check_v3_9_4_temporal_verification.py +471 -0
  801. package/vendor/ars/scripts/test_check_version_consistency.py +1462 -0
  802. package/vendor/ars/scripts/test_check_workflow_classification.py +225 -0
  803. package/vendor/ars/scripts/test_chinese_literature_client.py +1889 -0
  804. package/vendor/ars/scripts/test_citation_existence_policy.py +480 -0
  805. package/vendor/ars/scripts/test_citation_verification_summary.py +342 -0
  806. package/vendor/ars/scripts/test_claim_audit_calibration.py +882 -0
  807. package/vendor/ars/scripts/test_claim_audit_finalizer.py +979 -0
  808. package/vendor/ars/scripts/test_claim_audit_pipeline.py +2398 -0
  809. package/vendor/ars/scripts/test_claim_audit_schema.py +1778 -0
  810. package/vendor/ars/scripts/test_claim_intent_manifest.py +666 -0
  811. package/vendor/ars/scripts/test_claim_registry_coverage.py +246 -0
  812. package/vendor/ars/scripts/test_claim_standing_discovery.py +579 -0
  813. package/vendor/ars/scripts/test_claim_standing_pipeline_wiring.py +290 -0
  814. package/vendor/ars/scripts/test_claim_standing_stance_assets.py +399 -0
  815. package/vendor/ars/scripts/test_claim_standing_stance_contracts.py +383 -0
  816. package/vendor/ars/scripts/test_claim_standing_stance_runner.py +349 -0
  817. package/vendor/ars/scripts/test_claim_standing_transmissions.py +605 -0
  818. package/vendor/ars/scripts/test_claim_strength_drift_disposition.py +517 -0
  819. package/vendor/ars/scripts/test_claim_verification_coverage_contract.py +104 -0
  820. package/vendor/ars/scripts/test_contamination_signals.py +1086 -0
  821. package/vendor/ars/scripts/test_content_coverage_advisory.py +1767 -0
  822. package/vendor/ars/scripts/test_cross_document_consistency_advisory.py +1270 -0
  823. package/vendor/ars/scripts/test_cross_model_codex_transport.py +1152 -0
  824. package/vendor/ars/scripts/test_cross_model_handoff.py +571 -0
  825. package/vendor/ars/scripts/test_cross_model_verification_guards.py +792 -0
  826. package/vendor/ars/scripts/test_crossref_client.py +393 -0
  827. package/vendor/ars/scripts/test_dispatch_e4_panel.py +4235 -0
  828. package/vendor/ars/scripts/test_e2e_claim_audit.py +540 -0
  829. package/vendor/ars/scripts/test_eval_harness_workflow.py +140 -0
  830. package/vendor/ars/scripts/test_evals_citation_extraction.py +150 -0
  831. package/vendor/ars/scripts/test_evals_lift_report_schema.py +108 -0
  832. package/vendor/ars/scripts/test_evidence_rows.py +2593 -0
  833. package/vendor/ars/scripts/test_experiment_provenance.py +915 -0
  834. package/vendor/ars/scripts/test_human_read_attestation_resolver.py +477 -0
  835. package/vendor/ars/scripts/test_ideation_diversity_assignment_gate.py +615 -0
  836. package/vendor/ars/scripts/test_indirect_prompt_injection_behavior_probe.py +250 -0
  837. package/vendor/ars/scripts/test_inquiry_branch_ledger.py +2296 -0
  838. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_10.py +248 -0
  839. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_7_3.py +545 -0
  840. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_9_0.py +497 -0
  841. package/vendor/ars/scripts/test_normalize_compat_verdict.py +149 -0
  842. package/vendor/ars/scripts/test_openalex_client.py +490 -0
  843. package/vendor/ars/scripts/test_passport_yaml.py +104 -0
  844. package/vendor/ars/scripts/test_pattern_eval_runtime.py +1295 -0
  845. package/vendor/ars/scripts/test_pdf_read_preflight.py +1943 -0
  846. package/vendor/ars/scripts/test_policy_anchor_disclosure.py +666 -0
  847. package/vendor/ars/scripts/test_reading_probe_lint.py +218 -0
  848. package/vendor/ars/scripts/test_recompute_receipts.py +778 -0
  849. package/vendor/ars/scripts/test_render_claim_standing_view.py +192 -0
  850. package/vendor/ars/scripts/test_render_eval_comment.py +162 -0
  851. package/vendor/ars/scripts/test_render_harness_retirement_issue.py +110 -0
  852. package/vendor/ars/scripts/test_repro_lock_validation_drift.py +100 -0
  853. package/vendor/ars/scripts/test_research_workflow_profile.py +734 -0
  854. package/vendor/ars/scripts/test_resolve_human_subjects_authority.py +1219 -0
  855. package/vendor/ars/scripts/test_resolve_review_target_context.py +703 -0
  856. package/vendor/ars/scripts/test_resume_e4_record.py +315 -0
  857. package/vendor/ars/scripts/test_retraction_status.py +456 -0
  858. package/vendor/ars/scripts/test_review_criteria_binding.py +629 -0
  859. package/vendor/ars/scripts/test_review_panel_provenance.py +565 -0
  860. package/vendor/ars/scripts/test_review_pathway_rule_trace.py +821 -0
  861. package/vendor/ars/scripts/test_revision_roadmap.py +1255 -0
  862. package/vendor/ars/scripts/test_run_ci_pytest_manifest.py +186 -0
  863. package/vendor/ars/scripts/test_run_codex_audit_e2e.py +369 -0
  864. package/vendor/ars/scripts/test_run_evals.py +430 -0
  865. package/vendor/ars/scripts/test_run_guard_launcher.py +500 -0
  866. package/vendor/ars/scripts/test_run_ideation_diversity_no_call.py +1833 -0
  867. package/vendor/ars/scripts/test_run_indirect_prompt_injection_no_call.py +1889 -0
  868. package/vendor/ars/scripts/test_run_review_criteria_constructive_value.py +586 -0
  869. package/vendor/ars/scripts/test_run_role_topology_utility_dry_run.py +428 -0
  870. package/vendor/ars/scripts/test_score_review_criteria_constructive_value.py +340 -0
  871. package/vendor/ars/scripts/test_semantic_scholar_client.py +554 -0
  872. package/vendor/ars/scripts/test_slr_lineage_emission.py +230 -0
  873. package/vendor/ars/scripts/test_socratic_rq_non_generation_contract.py +173 -0
  874. package/vendor/ars/scripts/test_temporal_integrity_audit.py +438 -0
  875. package/vendor/ars/scripts/test_text_similarity.py +95 -0
  876. package/vendor/ars/scripts/test_title_fuzzy_false_positive.py +111 -0
  877. package/vendor/ars/scripts/test_tortured_phrase_screening.py +2959 -0
  878. package/vendor/ars/scripts/test_transport_fixture_citation_gate.py +338 -0
  879. package/vendor/ars/scripts/test_uncited_assertion.py +558 -0
  880. package/vendor/ars/scripts/test_v3_6_7_phase_6_6.py +1279 -0
  881. package/vendor/ars/scripts/test_validate_compliance_fixtures.py +36 -0
  882. package/vendor/ars/scripts/test_validate_ideation_diversity_assets.py +230 -0
  883. package/vendor/ars/scripts/test_venue_disclosure_contract.py +755 -0
  884. package/vendor/ars/scripts/test_verification_cache.py +280 -0
  885. package/vendor/ars/scripts/test_verification_gate.py +461 -0
  886. package/vendor/ars/scripts/test_verify_passport_cli.py +123 -0
  887. package/vendor/ars/scripts/test_verify_submission_package.py +1407 -0
  888. package/vendor/ars/scripts/test_version_records_schema.py +211 -0
  889. package/vendor/ars/scripts/tortured_phrase_screening.py +3502 -0
  890. package/vendor/ars/scripts/uncited_assertion_detector.py +254 -0
  891. package/vendor/ars/scripts/v3_6_7_inversion_manifest.json +9 -0
  892. package/vendor/ars/scripts/v3_6_8_inversion_manifest.json +10 -0
  893. package/vendor/ars/scripts/validate_claim_standing_stance_assets.py +249 -0
  894. package/vendor/ars/scripts/validate_compliance_fixtures.py +56 -0
  895. package/vendor/ars/scripts/validate_ideation_diversity_assets.py +303 -0
  896. package/vendor/ars/scripts/venue_disclosure_contract_harness.py +837 -0
  897. package/vendor/ars/scripts/verification_cache.py +276 -0
  898. package/vendor/ars/scripts/verification_gate/__init__.py +345 -0
  899. package/vendor/ars/scripts/verify_passport.py +133 -0
  900. package/vendor/ars/scripts/verify_submission_package.py +1657 -0
  901. package/vendor/ars/shared/agents/compliance_agent.md +136 -0
  902. package/vendor/ars/shared/artifact_reproducibility_pattern.md +173 -0
  903. package/vendor/ars/shared/benchmark_report.schema.json +81 -0
  904. package/vendor/ars/shared/benchmark_report_pattern.md +180 -0
  905. package/vendor/ars/shared/bibliographic_integrity_signals.md +142 -0
  906. package/vendor/ars/shared/collaboration_depth_rubric.md +154 -0
  907. package/vendor/ars/shared/compliance_checkpoint_protocol.md +162 -0
  908. package/vendor/ars/shared/compliance_report.schema.json +187 -0
  909. package/vendor/ars/shared/contracts/README.md +938 -0
  910. package/vendor/ars/shared/contracts/activity/adjudication_activity_input.schema.json +555 -0
  911. package/vendor/ars/shared/contracts/activity/adjudication_activity_store.schema.json +560 -0
  912. package/vendor/ars/shared/contracts/audit/audit_jsonl.schema.json +128 -0
  913. package/vendor/ars/shared/contracts/audit/audit_sidecar.schema.json +169 -0
  914. package/vendor/ars/shared/contracts/audit/audit_verdict.schema.json +133 -0
  915. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory.schema.json +480 -0
  916. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory_draft.schema.json +564 -0
  917. package/vendor/ars/shared/contracts/audit/cross_document_source_manifest.schema.json +202 -0
  918. package/vendor/ars/shared/contracts/audit/tortured_phrase_advisory.schema.json +1362 -0
  919. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot.schema.json +208 -0
  920. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot_manifest.schema.json +335 -0
  921. package/vendor/ars/shared/contracts/capability/stage_capability_matrix.json +434 -0
  922. package/vendor/ars/shared/contracts/claim_standing/candidate_ledger.schema.json +705 -0
  923. package/vendor/ars/shared/contracts/claim_standing/query_plan.schema.json +389 -0
  924. package/vendor/ars/shared/contracts/claim_standing/query_plan_v1_1.schema.json +782 -0
  925. package/vendor/ars/shared/contracts/claim_standing/retrieval_input.schema.json +440 -0
  926. package/vendor/ars/shared/contracts/claim_standing/stance_record.schema.json +460 -0
  927. package/vendor/ars/shared/contracts/claim_standing/transmission_ledger.schema.json +282 -0
  928. package/vendor/ars/shared/contracts/cross_model/codex_citation_receipt.schema.json +157 -0
  929. package/vendor/ars/shared/contracts/cross_model/codex_citation_request.schema.json +23 -0
  930. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_commitment.schema.json +55 -0
  931. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_reveal.schema.json +50 -0
  932. package/vendor/ars/shared/contracts/degradation_registry.json +428 -0
  933. package/vendor/ars/shared/contracts/evaluator/full.json +126 -0
  934. package/vendor/ars/shared/contracts/evidence/claim_registry.schema.json +50 -0
  935. package/vendor/ars/shared/contracts/evidence/claim_registry_coverage_report.schema.json +79 -0
  936. package/vendor/ars/shared/contracts/evidence/evidence_row.schema.json +504 -0
  937. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_1.schema.json +364 -0
  938. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_2.schema.json +714 -0
  939. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_3.schema.json +524 -0
  940. package/vendor/ars/shared/contracts/human_subjects/authority_profile_registry.schema.json +497 -0
  941. package/vendor/ars/shared/contracts/human_subjects/committee_correspondence.schema.json +253 -0
  942. package/vendor/ars/shared/contracts/human_subjects/content_coverage_advisory.schema.json +620 -0
  943. package/vendor/ars/shared/contracts/human_subjects/irb_context_record.schema.json +329 -0
  944. package/vendor/ars/shared/contracts/human_subjects/resolved_authority_context.schema.json +347 -0
  945. package/vendor/ars/shared/contracts/human_subjects/review_pathway_rule_trace.schema.json +265 -0
  946. package/vendor/ars/shared/contracts/human_subjects/review_pathway_trace_request.schema.json +127 -0
  947. package/vendor/ars/shared/contracts/human_subjects/submission_packet_inventory.schema.json +240 -0
  948. package/vendor/ars/shared/contracts/human_subjects/submission_packet_manifest.schema.json +999 -0
  949. package/vendor/ars/shared/contracts/passport/audit_artifact_entry.schema.json +266 -0
  950. package/vendor/ars/shared/contracts/passport/bibliographic_integrity_signal.schema.json +1676 -0
  951. package/vendor/ars/shared/contracts/passport/citation_provenance.schema.json +107 -0
  952. package/vendor/ars/shared/contracts/passport/citation_verification_summary.schema.json +164 -0
  953. package/vendor/ars/shared/contracts/passport/claim_audit_result.schema.json +124 -0
  954. package/vendor/ars/shared/contracts/passport/claim_drift.schema.json +58 -0
  955. package/vendor/ars/shared/contracts/passport/claim_intent_manifest.schema.json +107 -0
  956. package/vendor/ars/shared/contracts/passport/constraint_violation.schema.json +65 -0
  957. package/vendor/ars/shared/contracts/passport/experiment_alignment_result.schema.json +69 -0
  958. package/vendor/ars/shared/contracts/passport/experiment_provenance_entry.schema.json +169 -0
  959. package/vendor/ars/shared/contracts/passport/human_read_log.schema.json +86 -0
  960. package/vendor/ars/shared/contracts/passport/inquiry_ledger_ref.schema.json +22 -0
  961. package/vendor/ars/shared/contracts/passport/literature_corpus_entry.schema.json +650 -0
  962. package/vendor/ars/shared/contracts/passport/preregistration_artifact.schema.json +132 -0
  963. package/vendor/ars/shared/contracts/passport/rejection_log.schema.json +89 -0
  964. package/vendor/ars/shared/contracts/passport/reset_ledger_entry.schema.json +158 -0
  965. package/vendor/ars/shared/contracts/passport/temporal_audit_results.schema.json +208 -0
  966. package/vendor/ars/shared/contracts/passport/terminal_policies.schema.json +50 -0
  967. package/vendor/ars/shared/contracts/passport/timeline.schema.json +102 -0
  968. package/vendor/ars/shared/contracts/passport/uncited_assertion.schema.json +56 -0
  969. package/vendor/ars/shared/contracts/passport/uncited_audit_failure.schema.json +72 -0
  970. package/vendor/ars/shared/contracts/passport/user_attested_read_resolution.schema.json +87 -0
  971. package/vendor/ars/shared/contracts/passport/version_records.schema.json +138 -0
  972. package/vendor/ars/shared/contracts/patch/block_manifest.schema.json +45 -0
  973. package/vendor/ars/shared/contracts/patch/legacy/v1_0/revision_patch.schema.json +110 -0
  974. package/vendor/ars/shared/contracts/patch/revision_patch.schema.json +250 -0
  975. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_diagnostic.schema.json +39 -0
  976. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_worker.schema.json +88 -0
  977. package/vendor/ars/shared/contracts/pdf/pdf_read_preflight.schema.json +227 -0
  978. package/vendor/ars/shared/contracts/re_review/input_manifest.schema.json +161 -0
  979. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/input_manifest.schema.json +134 -0
  980. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/precommitment.schema.json +193 -0
  981. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/traceability.schema.json +841 -0
  982. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/verdict_record.schema.json +244 -0
  983. package/vendor/ars/shared/contracts/re_review/precommitment.schema.json +193 -0
  984. package/vendor/ars/shared/contracts/re_review/traceability.schema.json +916 -0
  985. package/vendor/ars/shared/contracts/re_review/verdict_record.schema.json +245 -0
  986. package/vendor/ars/shared/contracts/research_workflow/inquiry_branch_ledger.schema.json +449 -0
  987. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile.schema.json +222 -0
  988. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile_selection_receipt.schema.json +111 -0
  989. package/vendor/ars/shared/contracts/review_target/constructive_review_findings.schema.json +172 -0
  990. package/vendor/ars/shared/contracts/review_target/criteria_registry.schema.json +97 -0
  991. package/vendor/ars/shared/contracts/review_target/review_criteria_binding_manifest.schema.json +235 -0
  992. package/vendor/ars/shared/contracts/review_target/review_criteria_source_receipt.schema.json +158 -0
  993. package/vendor/ars/shared/contracts/review_target/review_target_context.schema.json +106 -0
  994. package/vendor/ars/shared/contracts/review_target/review_target_declaration.schema.json +118 -0
  995. package/vendor/ars/shared/contracts/reviewer/full.json +114 -0
  996. package/vendor/ars/shared/contracts/reviewer/methodology_focus.json +75 -0
  997. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance.schema.json +263 -0
  998. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_carrier.schema.json +122 -0
  999. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_input.schema.json +120 -0
  1000. package/vendor/ars/shared/contracts/revision/author_adjudication.schema.json +251 -0
  1001. package/vendor/ars/shared/contracts/revision/author_adjudication_input.schema.json +25 -0
  1002. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition.schema.json +97 -0
  1003. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition_input.schema.json +80 -0
  1004. package/vendor/ars/shared/contracts/revision/claim_strength_drift_findings.schema.json +139 -0
  1005. package/vendor/ars/shared/contracts/revision/claim_surface_manifest.schema.json +99 -0
  1006. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization.schema.json +140 -0
  1007. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization_input.schema.json +28 -0
  1008. package/vendor/ars/shared/contracts/revision/integrity_correction_list.schema.json +48 -0
  1009. package/vendor/ars/shared/contracts/revision/integrity_pass_receipt.schema.json +16 -0
  1010. package/vendor/ars/shared/contracts/revision/revision_evidence_bundle.schema.json +134 -0
  1011. package/vendor/ars/shared/contracts/revision/revision_roadmap.schema.json +334 -0
  1012. package/vendor/ars/shared/contracts/submission/format_profile.example.yaml +33 -0
  1013. package/vendor/ars/shared/contracts/submission/format_profile.schema.json +102 -0
  1014. package/vendor/ars/shared/contracts/submission/submission_verification_report.schema.json +233 -0
  1015. package/vendor/ars/shared/contracts/submission/venue_profile.schema.json +114 -0
  1016. package/vendor/ars/shared/contracts/writer/full.json +87 -0
  1017. package/vendor/ars/shared/cross_model_verification.md +714 -0
  1018. package/vendor/ars/shared/evals_lift_report.schema.json +141 -0
  1019. package/vendor/ars/shared/ground_truth_isolation_pattern.md +275 -0
  1020. package/vendor/ars/shared/handoff_schemas.md +1209 -0
  1021. package/vendor/ars/shared/human_subjects_authority_registry.json +1278 -0
  1022. package/vendor/ars/shared/mode_spectrum.md +57 -0
  1023. package/vendor/ars/shared/model_tiering.md +83 -0
  1024. package/vendor/ars/shared/policy_data/nature_policy.md +56 -0
  1025. package/vendor/ars/shared/prisma_trAIce_protocol.md +157 -0
  1026. package/vendor/ars/shared/raise_framework.md +129 -0
  1027. package/vendor/ars/shared/references/authority_content_coverage_advisory_protocol.md +275 -0
  1028. package/vendor/ars/shared/references/claim_standing_candidate_ledger_protocol.md +66 -0
  1029. package/vendor/ars/shared/references/claim_strength_ladder.md +93 -0
  1030. package/vendor/ars/shared/references/cross_document_consistency_advisory_protocol.md +263 -0
  1031. package/vendor/ars/shared/references/evidence_row_protocol.md +260 -0
  1032. package/vendor/ars/shared/references/firm_rules.md +90 -0
  1033. package/vendor/ars/shared/references/human_subjects_authority_protocol.md +274 -0
  1034. package/vendor/ars/shared/references/intent_clarification_protocol.md +168 -0
  1035. package/vendor/ars/shared/references/irb_terminology_glossary.md +229 -0
  1036. package/vendor/ars/shared/references/protected_hedging_phrases.md +118 -0
  1037. package/vendor/ars/shared/references/psychometric_terminology_glossary.md +109 -0
  1038. package/vendor/ars/shared/references/review_criteria_consumer_protocol.md +238 -0
  1039. package/vendor/ars/shared/references/review_pathway_rule_trace_protocol.md +166 -0
  1040. package/vendor/ars/shared/references/submission_packet_manifest_protocol.md +292 -0
  1041. package/vendor/ars/shared/references/word_count_conventions.md +124 -0
  1042. package/vendor/ars/shared/research_workflow_profiles/field_general.json +1 -0
  1043. package/vendor/ars/shared/review_criteria_registry.json +207 -0
  1044. package/vendor/ars/shared/review_criteria_sources/msr-2027-technical-papers.2026-08-24.json +46 -0
  1045. package/vendor/ars/shared/review_criteria_sources/sigsoft-empirical-standards.2026-08-24.json +31 -0
  1046. package/vendor/ars/shared/sprint_contract.schema.json +482 -0
  1047. package/vendor/ars/shared/style_calibration_protocol.md +151 -0
  1048. package/vendor/ars/shared/templates/codex_audit_multifile_template.md +263 -0
  1049. package/vendor/ars/tools/release-discipline/.toolkit-version +1 -0
  1050. package/vendor/ars/tools/release-discipline/README.md +4 -0
  1051. package/vendor/ars/tools/release-discipline/scripts/_release_doc_alignment_schema.py +1011 -0
  1052. package/vendor/ars/tools/release-discipline/scripts/check_command_invariants.py +497 -0
  1053. package/vendor/ars/tools/release-discipline/scripts/check_release_doc_alignment.py +263 -0
  1054. package/vendor/ars/tools/release-discipline/scripts/sync-toolkit.sh +147 -0
  1055. package/vendor/windows/NOTICE.md +12 -0
  1056. package/vendor/windows/arm64/fd.exe +0 -0
  1057. package/vendor/windows/arm64/licenses/fd/LICENSE-APACHE +201 -0
  1058. package/vendor/windows/arm64/licenses/fd/LICENSE-MIT +21 -0
  1059. package/vendor/windows/arm64/licenses/ripgrep/COPYING +3 -0
  1060. package/vendor/windows/arm64/licenses/ripgrep/LICENSE-MIT +21 -0
  1061. package/vendor/windows/arm64/licenses/ripgrep/UNLICENSE +24 -0
  1062. package/vendor/windows/arm64/rg.exe +0 -0
  1063. package/vendor/windows/x64/fd.exe +0 -0
  1064. package/vendor/windows/x64/licenses/fd/LICENSE-APACHE +201 -0
  1065. package/vendor/windows/x64/licenses/fd/LICENSE-MIT +21 -0
  1066. package/vendor/windows/x64/licenses/ripgrep/COPYING +3 -0
  1067. package/vendor/windows/x64/licenses/ripgrep/LICENSE-MIT +21 -0
  1068. package/vendor/windows/x64/licenses/ripgrep/UNLICENSE +24 -0
  1069. package/vendor/windows/x64/rg.exe +0 -0
@@ -0,0 +1,1895 @@
1
+ #!/usr/bin/env python3
2
+ """Contained subscription-CLI runner for the #684 paired measurement.
3
+
4
+ CI exercises asset validation, prompt sealing, fake-Codex dispatch, blinding,
5
+ and expert-record assembly. No command selects an API transport. The only
6
+ live path is ``dispatch`` and it requires the exact frozen run-plan SHA-256 plus
7
+ the explicit ``--execute-24-subscription-calls`` flag.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import datetime as dt
13
+ import hashlib
14
+ import json
15
+ import os
16
+ from pathlib import Path
17
+ import re
18
+ import secrets
19
+ import shutil
20
+ import stat
21
+ import subprocess
22
+ import sys
23
+ import tempfile
24
+ from typing import Any, NoReturn
25
+
26
+ from jsonschema import Draft202012Validator, FormatChecker
27
+ from referencing import Registry, Resource
28
+
29
+ from check_heldout_measurement_report import location_errors, validate_report
30
+ from resolve_review_target_context import render_brief, resolve, validate_registry
31
+ from score_review_criteria_constructive_value import score as score_paired_record
32
+
33
+
34
+ REPO_ROOT = Path(__file__).resolve().parents[1]
35
+ SUITE = "review_criteria_constructive_value"
36
+ SUITE_ROOT = REPO_ROOT / "evals" / "heldout" / SUITE
37
+ LOCK_PATH = SUITE_ROOT / "suite_lock.json"
38
+ SCENARIOS_PATH = SUITE_ROOT / "scenarios.json"
39
+ SCENARIOS_SCHEMA_PATH = SUITE_ROOT / "scenarios.schema.json"
40
+ DECLARATION_SCHEMA_PATH = (
41
+ REPO_ROOT / "shared/contracts/review_target/review_target_declaration.schema.json"
42
+ )
43
+ REGISTRY_PATH = REPO_ROOT / "scripts/fixtures/review_target_context/synthetic-registry.json"
44
+ HELDOUT_SET_PATH = SUITE_ROOT / "heldout_set.json"
45
+ CALL_PLAN_PATH = SUITE_ROOT / "call_plan.json"
46
+ BASELINE_PROMPT_PATH = SUITE_ROOT / "baseline_prompt.md"
47
+ TREATMENT_PROMPT_PATH = SUITE_ROOT / "treatment_prompt.md"
48
+ OUTPUT_SCHEMA_PATH = SUITE_ROOT / "subject_output.schema.json"
49
+ EXPERT_PACKET_SCHEMA_PATH = SUITE_ROOT / "expert_packet.schema.json"
50
+ EXPERT_LABELS_SCHEMA_PATH = SUITE_ROOT / "expert_labels.schema.json"
51
+ DECISIONS_SCHEMA_PATH = SUITE_ROOT / "adjudication_decisions.schema.json"
52
+ PAIRED_SCHEMA_PATH = SUITE_ROOT / "paired_adjudication.schema.json"
53
+ EXECUTION_SCHEMA_PATH = REPO_ROOT / "evals/heldout/execution_manifest.schema.json"
54
+ MEASUREMENT_PLAN_PATH = SUITE_ROOT / "measurement_plan.md"
55
+ EXPERT_GUIDE_PATH = SUITE_ROOT / "expert_label_guide.md"
56
+
57
+ RUN_PLAN_VERSION = "review-criteria-run-plan/1.0"
58
+ RECEIPT_VERSION = "review-criteria-subject-receipt/1.0"
59
+ MIN_CODEX_VERSION = (0, 147, 0)
60
+ MAX_ASSET_BYTES = 4 * 1024 * 1024
61
+ MAX_EVENT_BYTES = 8 * 1024 * 1024
62
+ MAX_OUTPUT_BYTES = 2 * 1024 * 1024
63
+ MODEL_RE = re.compile(r"^gpt-[a-z0-9][a-z0-9._-]{0,123}$")
64
+ SHA_RE = re.compile(r"^[0-9a-f]{64}$")
65
+ COMMIT_RE = re.compile(r"^[0-9a-f]{40}$")
66
+ VERSION_RE = re.compile(r"\bcodex-cli\s+(\d+)\.(\d+)\.(\d+)\b")
67
+ FEATURE_NAME_RE = re.compile(r"^[a-z][a-z0-9_]*$")
68
+ PROVIDER_SCHEMA_STRIPPED_KEYWORDS = frozenset(
69
+ {"$schema", "$id", "title", "uniqueItems", "minLength", "maxLength"}
70
+ )
71
+ PROVIDER_SCHEMA_ALLOWED_KEYWORDS = frozenset(
72
+ {
73
+ "type",
74
+ "const",
75
+ "enum",
76
+ "properties",
77
+ "required",
78
+ "additionalProperties",
79
+ "items",
80
+ "minItems",
81
+ "maxItems",
82
+ "pattern",
83
+ }
84
+ )
85
+ BLINDING = [
86
+ "arm_identity",
87
+ "mechanism_state",
88
+ "other_experts",
89
+ "raw_aggregate",
90
+ "expected_direction",
91
+ ]
92
+ LOCKED_ASSET_REFS = {
93
+ "evals/heldout/review_criteria_constructive_value/adjudication_decisions.schema.json",
94
+ "evals/heldout/review_criteria_constructive_value/baseline_prompt.md",
95
+ "evals/heldout/review_criteria_constructive_value/call_plan.json",
96
+ "evals/heldout/review_criteria_constructive_value/expert_label_guide.md",
97
+ "evals/heldout/review_criteria_constructive_value/expert_labels.schema.json",
98
+ "evals/heldout/review_criteria_constructive_value/expert_packet.schema.json",
99
+ "evals/heldout/review_criteria_constructive_value/heldout_set.json",
100
+ "evals/heldout/review_criteria_constructive_value/measurement_plan.md",
101
+ "evals/heldout/review_criteria_constructive_value/paired_adjudication.schema.json",
102
+ "evals/heldout/review_criteria_constructive_value/scenarios.json",
103
+ "evals/heldout/review_criteria_constructive_value/scenarios.schema.json",
104
+ "evals/heldout/review_criteria_constructive_value/subject_output.schema.json",
105
+ "evals/heldout/review_criteria_constructive_value/treatment_prompt.md",
106
+ "scripts/fixtures/review_target_context/synthetic-registry.json",
107
+ "scripts/run_review_criteria_constructive_value.py",
108
+ "scripts/score_review_criteria_constructive_value.py",
109
+ }
110
+ DISABLED_FEATURES = (
111
+ "shell_tool",
112
+ "unified_exec",
113
+ "apps",
114
+ "plugins",
115
+ "plugin_sharing",
116
+ "skill_search",
117
+ "multi_agent",
118
+ "multi_agent_v2",
119
+ "computer_use",
120
+ "browser_use",
121
+ "browser_use_external",
122
+ "browser_use_full_cdp_access",
123
+ "in_app_browser",
124
+ "image_generation",
125
+ "artifact",
126
+ "code_mode",
127
+ "code_mode_host",
128
+ "hooks",
129
+ "goals",
130
+ "workspace_dependencies",
131
+ "shell_snapshot",
132
+ )
133
+ FORBIDDEN_EVENT_ITEM_TOKENS = (
134
+ "command",
135
+ "tool",
136
+ "file_change",
137
+ "mcp",
138
+ "web_search",
139
+ "image",
140
+ "computer",
141
+ "collab",
142
+ "subagent",
143
+ "plan",
144
+ )
145
+
146
+
147
+ class MeasurementError(RuntimeError):
148
+ """A closed asset, transport, output, or expert-record violation."""
149
+
150
+
151
+ def _fail(message: str) -> NoReturn:
152
+ raise MeasurementError(message)
153
+
154
+
155
+ def _reject_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
156
+ result: dict[str, Any] = {}
157
+ for key, value in pairs:
158
+ if key in result:
159
+ raise ValueError(f"duplicate JSON key: {key}")
160
+ result[key] = value
161
+ return result
162
+
163
+
164
+ def _strict_loads(raw: bytes) -> Any:
165
+ return json.loads(
166
+ raw.decode("utf-8"),
167
+ object_pairs_hook=_reject_pairs,
168
+ parse_constant=lambda value: (_ for _ in ()).throw(
169
+ ValueError(f"non-finite JSON number: {value}")
170
+ ),
171
+ )
172
+
173
+
174
+ def _canonical(value: Any) -> bytes:
175
+ try:
176
+ return json.dumps(
177
+ value,
178
+ ensure_ascii=False,
179
+ allow_nan=False,
180
+ sort_keys=True,
181
+ separators=(",", ":"),
182
+ ).encode("utf-8")
183
+ except (TypeError, ValueError, UnicodeEncodeError) as exc:
184
+ raise MeasurementError(f"value is not canonical JSON: {exc}") from exc
185
+
186
+
187
+ def _sha(raw: bytes) -> str:
188
+ return hashlib.sha256(raw).hexdigest()
189
+
190
+
191
+ def _safe_explicit_file(path: Path, *, limit: int = MAX_ASSET_BYTES) -> bytes:
192
+ absolute = path.absolute()
193
+ parts = absolute.parts
194
+ directory_flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
195
+ nofollow = getattr(os, "O_NOFOLLOW", 0)
196
+ directory_fd = os.open(absolute.anchor, directory_flags)
197
+ try:
198
+ for component in parts[1:-1]:
199
+ next_fd = os.open(
200
+ component,
201
+ directory_flags | nofollow,
202
+ dir_fd=directory_fd,
203
+ )
204
+ os.close(directory_fd)
205
+ directory_fd = next_fd
206
+ fd = os.open(parts[-1], os.O_RDONLY | nofollow, dir_fd=directory_fd)
207
+ except OSError as exc:
208
+ raise MeasurementError(
209
+ f"cannot open explicit path without symlinks {path}: {exc}"
210
+ ) from exc
211
+ finally:
212
+ os.close(directory_fd)
213
+ info = os.fstat(fd)
214
+ if not stat.S_ISREG(info.st_mode):
215
+ os.close(fd)
216
+ _fail(f"explicit input is not a regular file: {path}")
217
+ if info.st_size > limit:
218
+ os.close(fd)
219
+ _fail(f"explicit input exceeds {limit} bytes: {path}")
220
+ chunks: list[bytes] = []
221
+ total = 0
222
+ try:
223
+ while True:
224
+ chunk = os.read(fd, min(65_536, limit + 1 - total))
225
+ if not chunk:
226
+ break
227
+ chunks.append(chunk)
228
+ total += len(chunk)
229
+ if total > limit:
230
+ _fail(f"explicit input exceeds {limit} bytes: {path}")
231
+ final = os.fstat(fd)
232
+ raw = b"".join(chunks)
233
+ if len(raw) != final.st_size or (
234
+ info.st_dev,
235
+ info.st_ino,
236
+ info.st_size,
237
+ info.st_mtime_ns,
238
+ info.st_ctime_ns,
239
+ ) != (
240
+ final.st_dev,
241
+ final.st_ino,
242
+ final.st_size,
243
+ final.st_mtime_ns,
244
+ final.st_ctime_ns,
245
+ ):
246
+ _fail(f"explicit input changed while being read: {path}")
247
+ return raw
248
+ finally:
249
+ os.close(fd)
250
+
251
+
252
+ def _load_json(path: Path) -> tuple[dict[str, Any], bytes]:
253
+ raw = _safe_explicit_file(path)
254
+ try:
255
+ value = _strict_loads(raw)
256
+ except (UnicodeError, ValueError, json.JSONDecodeError) as exc:
257
+ raise MeasurementError(f"invalid strict JSON {path}: {exc}") from exc
258
+ if not isinstance(value, dict):
259
+ _fail(f"JSON root must be an object: {path}")
260
+ return value, raw
261
+
262
+
263
+ def _schema(path: Path) -> dict[str, Any]:
264
+ value, _ = _load_json(path)
265
+ Draft202012Validator.check_schema(value)
266
+ return value
267
+
268
+
269
+ def _validate(schema_path: Path, value: Any, label: str) -> None:
270
+ schema = _schema(schema_path)
271
+ errors = sorted(
272
+ Draft202012Validator(schema, format_checker=FormatChecker()).iter_errors(value),
273
+ key=lambda error: list(error.absolute_path),
274
+ )
275
+ if errors:
276
+ first = errors[0]
277
+ location = "$" + "".join(f"[{part!r}]" for part in first.absolute_path)
278
+ _fail(f"{label} schema failure at {location}: {first.message}")
279
+
280
+
281
+ def _project_provider_response_schema(node: Any) -> Any:
282
+ """Remove local-only assertions from the Codex/OpenAI response schema."""
283
+ if not isinstance(node, dict):
284
+ _fail("provider response schema source node must be an object")
285
+ projected: dict[str, Any] = {}
286
+ for key, value in node.items():
287
+ if key in PROVIDER_SCHEMA_STRIPPED_KEYWORDS:
288
+ continue
289
+ if key == "properties":
290
+ if not isinstance(value, dict):
291
+ _fail("provider response schema properties must be an object")
292
+ projected[key] = {
293
+ name: _project_provider_response_schema(child)
294
+ for name, child in value.items()
295
+ }
296
+ elif key == "items":
297
+ projected[key] = _project_provider_response_schema(value)
298
+ else:
299
+ projected[key] = value
300
+ return projected
301
+
302
+
303
+ def _validate_provider_response_schema(node: Any, path: str = "$") -> None:
304
+ """Pin the strict response-schema subset required by Codex/OpenAI."""
305
+ if not isinstance(node, dict):
306
+ _fail(f"provider response schema node must be an object at {path}")
307
+ unsupported = set(node) - PROVIDER_SCHEMA_ALLOWED_KEYWORDS
308
+ if unsupported:
309
+ _fail(
310
+ f"provider response schema has unsupported keywords at {path}: "
311
+ f"{sorted(unsupported)}"
312
+ )
313
+ if ("const" in node or "enum" in node) and "type" not in node:
314
+ _fail(f"provider response schema requires explicit type at {path}")
315
+ if node.get("type") == "object":
316
+ properties = node.get("properties")
317
+ required = node.get("required")
318
+ if not isinstance(properties, dict) or node.get("additionalProperties") is not False:
319
+ _fail(f"provider response object must be closed at {path}")
320
+ if not isinstance(required, list) or set(required) != set(properties):
321
+ _fail(f"provider response object must require every property at {path}")
322
+ for key, value in properties.items():
323
+ _validate_provider_response_schema(value, f"{path}.properties[{key!r}]")
324
+ if "items" in node:
325
+ _validate_provider_response_schema(node["items"], f"{path}.items")
326
+
327
+
328
+ def _repo_ref(ref: str) -> Path:
329
+ if not isinstance(ref, str) or not ref or ref.startswith("/") or "\\" in ref:
330
+ _fail(f"invalid repository reference: {ref!r}")
331
+ if any(part in {"", ".", ".."} for part in ref.split("/")):
332
+ _fail(f"invalid repository reference: {ref!r}")
333
+ return REPO_ROOT / ref
334
+
335
+
336
+ def _validate_lock() -> dict[str, str]:
337
+ lock, _ = _load_json(LOCK_PATH)
338
+ if set(lock) != {"schema_version", "suite", "assets"}:
339
+ _fail("suite_lock.json must be the closed three-field object")
340
+ if lock["schema_version"] != "review-criteria-suite-lock/1.0" or lock["suite"] != SUITE:
341
+ _fail("suite_lock.json identity mismatch")
342
+ assets = lock["assets"]
343
+ if not isinstance(assets, dict) or set(assets) != LOCKED_ASSET_REFS:
344
+ _fail("suite_lock.json must contain the exact closed asset set")
345
+ for ref, digest in assets.items():
346
+ if not isinstance(digest, str) or SHA_RE.fullmatch(digest) is None:
347
+ _fail(f"suite lock digest is invalid for {ref!r}")
348
+ raw = _safe_explicit_file(_repo_ref(ref))
349
+ if _sha(raw) != digest:
350
+ _fail(f"suite lock hash mismatch for {ref}")
351
+ return assets
352
+
353
+
354
+ def _scenario_contexts() -> tuple[list[dict[str, Any]], dict[str, dict[str, Any]], dict[str, Any]]:
355
+ scenarios, _ = _load_json(SCENARIOS_PATH)
356
+ scenario_schema = _schema(SCENARIOS_SCHEMA_PATH)
357
+ declaration_schema = _schema(DECLARATION_SCHEMA_PATH)
358
+ registry = Registry().with_resource(
359
+ declaration_schema["$id"], Resource.from_contents(declaration_schema)
360
+ )
361
+ errors = list(Draft202012Validator(scenario_schema, registry=registry).iter_errors(scenarios))
362
+ if errors:
363
+ _fail(f"scenarios schema failure: {errors[0].message}")
364
+ criteria_registry, _ = _load_json(REGISTRY_PATH)
365
+ validate_registry(criteria_registry)
366
+ contexts: dict[str, dict[str, Any]] = {}
367
+ items = scenarios["items"]
368
+ for item in items:
369
+ contexts[item["item_id"]] = resolve(item["declaration"], criteria_registry)
370
+ return items, contexts, criteria_registry
371
+
372
+
373
+ def validate_assets() -> dict[str, Any]:
374
+ assets = _validate_lock()
375
+ items, contexts, registry = _scenario_contexts()
376
+ skeleton, _ = _load_json(HELDOUT_SET_PATH)
377
+ expected = [
378
+ (item["item_id"], item["consumer_id"], item["role"])
379
+ for item in items
380
+ ]
381
+ declared = [
382
+ (item["item_id"], item["consumer"], item["role"])
383
+ for item in skeleton.get("items", [])
384
+ ]
385
+ if declared != expected:
386
+ _fail("heldout_set.json identity/order does not match scenarios.json")
387
+
388
+ plan, _ = _load_json(CALL_PLAN_PATH)
389
+ if set(plan) != {
390
+ "schema_version",
391
+ "suite",
392
+ "design",
393
+ "content_class",
394
+ "api_spend_ceiling_usd",
395
+ "transport",
396
+ "calls",
397
+ }:
398
+ _fail("call_plan.json has an open or incomplete root")
399
+ if (
400
+ plan["schema_version"] != "review-criteria-call-plan/1.0"
401
+ or plan["suite"] != SUITE
402
+ or plan["content_class"] != "repository_owned_synthetic"
403
+ or plan["api_spend_ceiling_usd"] != 0
404
+ or plan["transport"] != "codex_chatgpt_subscription"
405
+ ):
406
+ _fail("call_plan.json identity/transport/spend policy mismatch")
407
+ calls = plan["calls"]
408
+ if not isinstance(calls, list) or len(calls) != 24:
409
+ _fail("call plan must contain exactly 24 calls")
410
+ item_ids = [item[0] for item in expected]
411
+ seen: set[tuple[str, str, int]] = set()
412
+ for index, call in enumerate(calls, 1):
413
+ if not isinstance(call, dict) or set(call) != {
414
+ "sequence_index", "call_id", "item_id", "arm", "replicate"
415
+ }:
416
+ _fail(f"call_plan.calls[{index - 1}] is not closed")
417
+ if call["sequence_index"] != index:
418
+ _fail("call plan sequence indices must be contiguous from 1")
419
+ key = (call["item_id"], call["arm"], call["replicate"])
420
+ if (
421
+ call["item_id"] not in item_ids
422
+ or call["arm"] not in {"baseline", "treatment"}
423
+ or type(call["replicate"]) is not int
424
+ or call["replicate"] not in {1, 2}
425
+ or key in seen
426
+ ):
427
+ _fail(f"call plan contains invalid/duplicate cell: {key!r}")
428
+ expected_id = f"{call['item_id']}-{call['arm']}-r{call['replicate']}"
429
+ if call["call_id"] != expected_id:
430
+ _fail(f"call id does not bind its design cell: {call['call_id']!r}")
431
+ seen.add(key)
432
+ full = {(item, arm, rep) for item in item_ids for arm in ("baseline", "treatment") for rep in (1, 2)}
433
+ if seen != full:
434
+ _fail("call plan does not cover the exact 6 x 2 x 2 design")
435
+ for offset, item_id in enumerate(item_ids):
436
+ arms = [call["arm"] for call in calls[offset * 4:(offset + 1) * 4]
437
+ if call["item_id"] == item_id]
438
+ expected_arms = ["baseline", "treatment", "treatment", "baseline"]
439
+ if offset % 2:
440
+ expected_arms = ["treatment", "baseline", "baseline", "treatment"]
441
+ if arms != expected_arms:
442
+ _fail(f"call plan balance drift for {item_id}")
443
+
444
+ for schema_path in (
445
+ OUTPUT_SCHEMA_PATH,
446
+ EXPERT_PACKET_SCHEMA_PATH,
447
+ EXPERT_LABELS_SCHEMA_PATH,
448
+ DECISIONS_SCHEMA_PATH,
449
+ PAIRED_SCHEMA_PATH,
450
+ EXECUTION_SCHEMA_PATH,
451
+ ):
452
+ _schema(schema_path)
453
+ provider_schema = _project_provider_response_schema(_schema(OUTPUT_SCHEMA_PATH))
454
+ _validate_provider_response_schema(provider_schema)
455
+ return {
456
+ "suite": SUITE,
457
+ "assets": len(assets),
458
+ "items": len(items),
459
+ "calls": len(calls),
460
+ "contexts": {key: value["resolved_digest"] for key, value in contexts.items()},
461
+ "registry_version": registry["registry_version"],
462
+ }
463
+
464
+
465
+ def _marker(item: dict[str, Any], context: dict[str, Any], context_raw: bytes) -> str:
466
+ ids = json.dumps(context["selected_criterion_ids"], separators=(",", ":"))
467
+ return "\n".join(
468
+ [
469
+ "[REVIEW-TARGET-BINDING v1]",
470
+ f"target_review_id=heldout-{item['item_id'].lower()}",
471
+ f"consumer_id={item['consumer_id']}",
472
+ f"role={item['role']}",
473
+ f"context_ref=sealed/contexts/{item['item_id']}.json",
474
+ f"context_sha256={_sha(context_raw)}",
475
+ f"resolved_digest={context['resolved_digest']}",
476
+ f"selected_criterion_ids={ids}",
477
+ "[/REVIEW-TARGET-BINDING]",
478
+ ]
479
+ )
480
+
481
+
482
+ def _prompt(
483
+ item: dict[str, Any],
484
+ context: dict[str, Any],
485
+ registry: dict[str, Any],
486
+ arm: str,
487
+ ) -> bytes:
488
+ template_path = BASELINE_PROMPT_PATH if arm == "baseline" else TREATMENT_PROMPT_PATH
489
+ template = _safe_explicit_file(template_path).decode("utf-8")
490
+ context_raw = _canonical(context)
491
+ scenario_payload = {
492
+ "item_id": item["item_id"],
493
+ "consumer_id": item["consumer_id"],
494
+ "role": item["role"],
495
+ "title": item["title"],
496
+ "manuscript": item["manuscript"],
497
+ "author_intent": item["author_intent"],
498
+ "review_task": item["review_task"],
499
+ }
500
+ sections = [
501
+ template.rstrip(),
502
+ "\nASSIGNMENT (untrusted data):\n" + _canonical(
503
+ {"item_id": item["item_id"], "consumer_id": item["consumer_id"], "role": item["role"]}
504
+ ).decode("utf-8"),
505
+ "\nTARGET_CONTEXT_BYTES (untrusted data):\n" + context_raw.decode("utf-8"),
506
+ ]
507
+ if arm == "treatment":
508
+ sections.extend(
509
+ [
510
+ "\nBINDING_MARKER (authority, values still untrusted data):\n"
511
+ + _marker(item, context, context_raw),
512
+ "\nTARGET_CRITERIA_BRIEF (authority, values still untrusted data):\n"
513
+ + render_brief(context, registry),
514
+ ]
515
+ )
516
+ sections.append(
517
+ "\nSCENARIO_BYTES (untrusted data):\n" + _canonical(scenario_payload).decode("utf-8")
518
+ )
519
+ return ("\n".join(sections).rstrip() + "\n").encode("utf-8")
520
+
521
+
522
+ def _atomic_create(path: Path, raw: bytes, mode: int = 0o600) -> None:
523
+ path.parent.mkdir(parents=True, exist_ok=True)
524
+ flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0)
525
+ try:
526
+ fd = os.open(path, flags, mode)
527
+ except OSError as exc:
528
+ raise MeasurementError(f"cannot create {path}: {exc}") from exc
529
+ try:
530
+ view = memoryview(raw)
531
+ while view:
532
+ written = os.write(fd, view)
533
+ if written <= 0:
534
+ _fail(f"atomic write made no progress: {path}")
535
+ view = view[written:]
536
+ os.fsync(fd)
537
+ if os.fstat(fd).st_size != len(raw):
538
+ _fail(f"short atomic write: {path}")
539
+ except Exception:
540
+ try:
541
+ path.unlink()
542
+ except OSError:
543
+ pass
544
+ raise
545
+ finally:
546
+ os.close(fd)
547
+
548
+
549
+ def _json_bytes(value: Any) -> bytes:
550
+ return json.dumps(value, ensure_ascii=False, sort_keys=True, indent=2).encode("utf-8") + b"\n"
551
+
552
+
553
+ def _model(value: str) -> str:
554
+ if MODEL_RE.fullmatch(value) is None:
555
+ _fail("model must be an explicit gpt-* model id")
556
+ return value
557
+
558
+
559
+ def _verify_frozen_commit(commit: str, assets: dict[str, str]) -> None:
560
+ probe = subprocess.run(
561
+ ["git", "cat-file", "-e", f"{commit}^{{commit}}"],
562
+ cwd=REPO_ROOT,
563
+ stdin=subprocess.DEVNULL,
564
+ capture_output=True,
565
+ check=False,
566
+ )
567
+ if probe.returncode != 0:
568
+ _fail(f"suite_commit is not a repository commit: {commit}")
569
+ ancestor = subprocess.run(
570
+ ["git", "merge-base", "--is-ancestor", commit, "origin/main"],
571
+ cwd=REPO_ROOT,
572
+ stdin=subprocess.DEVNULL,
573
+ capture_output=True,
574
+ check=False,
575
+ )
576
+ if ancestor.returncode != 0:
577
+ _fail("suite_commit must already be on local origin/main history")
578
+ for ref, expected in assets.items():
579
+ shown = subprocess.run(
580
+ ["git", "show", f"{commit}:{ref}"],
581
+ cwd=REPO_ROOT,
582
+ stdin=subprocess.DEVNULL,
583
+ stdout=subprocess.PIPE,
584
+ stderr=subprocess.PIPE,
585
+ check=False,
586
+ )
587
+ if shown.returncode != 0 or _sha(shown.stdout) != expected:
588
+ _fail(f"suite_commit does not contain the locked asset bytes: {ref}")
589
+
590
+
591
+ def init_run(args: argparse.Namespace) -> dict[str, Any]:
592
+ validate_assets()
593
+ assets = _validate_lock()
594
+ model = _model(args.model)
595
+ if COMMIT_RE.fullmatch(args.suite_commit) is None:
596
+ _fail("suite_commit must be exactly 40 lowercase hexadecimal characters")
597
+ _verify_frozen_commit(args.suite_commit, assets)
598
+ if args.reasoning_effort not in {"low", "medium", "high", "xhigh"}:
599
+ _fail("reasoning_effort must be low, medium, high, or xhigh")
600
+ if args.input_token_cap < 1 or args.output_token_cap < 1:
601
+ _fail("token caps must be positive integers")
602
+ if not re.fullmatch(r"\d+\.\d+\.\d+", args.codex_version):
603
+ _fail("codex_version must be an exact dotted version")
604
+ run_dir = args.run_dir.resolve()
605
+ if run_dir.exists():
606
+ _fail(f"run directory already exists: {run_dir}")
607
+ run_dir.mkdir(parents=True, mode=0o700)
608
+
609
+ items, contexts, registry = _scenario_contexts()
610
+ by_id = {item["item_id"]: item for item in items}
611
+ call_plan, call_plan_raw = _load_json(CALL_PLAN_PATH)
612
+ calls: list[dict[str, Any]] = []
613
+ for call in call_plan["calls"]:
614
+ prompt = _prompt(by_id[call["item_id"]], contexts[call["item_id"]], registry, call["arm"])
615
+ if len(prompt) > args.input_token_cap * 4:
616
+ _fail(
617
+ f"prompt {call['call_id']} exceeds the conservative local input cap "
618
+ f"({len(prompt)} bytes > {args.input_token_cap * 4})"
619
+ )
620
+ prompt_ref = f"prompts/{call['call_id']}.txt"
621
+ _atomic_create(run_dir / prompt_ref, prompt)
622
+ calls.append(
623
+ {
624
+ **call,
625
+ "prompt_ref": prompt_ref,
626
+ "prompt_sha256": _sha(prompt),
627
+ "output_ref": f"outputs/{call['call_id']}.json",
628
+ "events_ref": f"events/{call['call_id']}.jsonl",
629
+ "receipt_ref": f"receipts/{call['call_id']}.json",
630
+ }
631
+ )
632
+ lock_raw = _safe_explicit_file(LOCK_PATH)
633
+ run_plan = {
634
+ "schema_version": RUN_PLAN_VERSION,
635
+ "suite": SUITE,
636
+ "suite_commit": args.suite_commit,
637
+ "content_class": "repository_owned_synthetic",
638
+ "transport": "codex_chatgpt_subscription",
639
+ "auth_mode": "chatgpt_subscription",
640
+ "api_spend_ceiling_usd": 0,
641
+ "codex_version": args.codex_version,
642
+ "model_id": model,
643
+ "reasoning_effort": args.reasoning_effort,
644
+ "sampling": "provider_managed_not_exposed",
645
+ "input_token_cap": args.input_token_cap,
646
+ "output_token_cap": args.output_token_cap,
647
+ "tools": [],
648
+ "isolation": {
649
+ "ephemeral_auth_home": True,
650
+ "empty_working_root": True,
651
+ "ignore_user_config": True,
652
+ "local_tools_disabled": True,
653
+ "web_disabled": True,
654
+ "forbidden_event_scan": True,
655
+ },
656
+ "suite_lock_sha256": _sha(lock_raw),
657
+ "call_plan_sha256": _sha(call_plan_raw),
658
+ "calls": calls,
659
+ }
660
+ _validate_run_plan(run_plan)
661
+ _atomic_create(run_dir / "run-plan.json", _json_bytes(run_plan))
662
+ return {
663
+ "run_plan": str(run_dir / "run-plan.json"),
664
+ "run_plan_sha256": _sha(_safe_explicit_file(run_dir / "run-plan.json")),
665
+ "calls": 24,
666
+ "model_id": model,
667
+ "api_spend_ceiling_usd": 0,
668
+ }
669
+
670
+
671
+ def _codex_home(environ: dict[str, str]) -> Path:
672
+ if environ.get("CODEX_HOME"):
673
+ return Path(environ["CODEX_HOME"]).expanduser().resolve()
674
+ if not environ.get("HOME"):
675
+ _fail("HOME is unavailable")
676
+ return (Path(environ["HOME"]).expanduser() / ".codex").resolve()
677
+
678
+
679
+ def _feature_names(raw: str) -> set[str]:
680
+ names = {
681
+ parts[0]
682
+ for line in raw.splitlines()
683
+ if (
684
+ (parts := line.split())
685
+ and len(parts) >= 3
686
+ and FEATURE_NAME_RE.fullmatch(parts[0]) is not None
687
+ and parts[-1] in {"true", "false"}
688
+ )
689
+ }
690
+ if not names:
691
+ raise ValueError("empty or malformed Codex feature registry")
692
+ return names
693
+
694
+
695
+ def detect(model: str, environ: dict[str, str] | None = None) -> dict[str, Any]:
696
+ _model(model)
697
+ env = dict(os.environ if environ is None else environ)
698
+ codex = shutil.which("codex", path=env.get("PATH"))
699
+ result: dict[str, Any] = {
700
+ "transport": "codex_chatgpt_subscription",
701
+ "model_id": model,
702
+ "available": False,
703
+ "auth_mode": None,
704
+ "reason_code": None,
705
+ }
706
+ if not codex:
707
+ result["reason_code"] = "CODEX_CLI_MISSING"
708
+ return result
709
+ auth_path = _codex_home(env) / "auth.json"
710
+ try:
711
+ auth_raw = _safe_explicit_file(auth_path, limit=1024 * 1024)
712
+ if not isinstance(_strict_loads(auth_raw), dict):
713
+ raise ValueError("auth root is not an object")
714
+ except (MeasurementError, UnicodeError, ValueError, json.JSONDecodeError):
715
+ result["reason_code"] = "SUBSCRIPTION_AUTH_INVALID"
716
+ return result
717
+ status_env = {
718
+ "PATH": env.get("PATH", os.defpath),
719
+ "CODEX_HOME": str(_codex_home(env)),
720
+ "HOME": env.get("HOME", str(_codex_home(env).parent)),
721
+ "LANG": "C",
722
+ "LC_ALL": "C",
723
+ "NO_COLOR": "1",
724
+ }
725
+ try:
726
+ version_run = subprocess.run(
727
+ [codex, "--version"], env=status_env, stdin=subprocess.DEVNULL,
728
+ capture_output=True, text=True, timeout=10, check=False,
729
+ )
730
+ status_run = subprocess.run(
731
+ [codex, "login", "status"], env=status_env, stdin=subprocess.DEVNULL,
732
+ capture_output=True, text=True, timeout=10, check=False,
733
+ )
734
+ except (OSError, subprocess.TimeoutExpired):
735
+ result["reason_code"] = "CODEX_STATUS_UNAVAILABLE"
736
+ return result
737
+ match = VERSION_RE.search(version_run.stdout)
738
+ if version_run.returncode or match is None:
739
+ result["reason_code"] = "CODEX_VERSION_UNAVAILABLE"
740
+ return result
741
+ version = tuple(int(value) for value in match.groups())
742
+ if version < MIN_CODEX_VERSION:
743
+ result["reason_code"] = "CODEX_VERSION_TOO_OLD"
744
+ return result
745
+ status_lines = {
746
+ line.strip()
747
+ for line in (status_run.stdout + "\n" + status_run.stderr).splitlines()
748
+ if line.strip()
749
+ }
750
+ if status_run.returncode or "Logged in using ChatGPT" not in status_lines:
751
+ result["reason_code"] = "AUTH_NOT_CHATGPT_SUBSCRIPTION"
752
+ return result
753
+ try:
754
+ features_run = subprocess.run(
755
+ [codex, "features", "list"], env=status_env, stdin=subprocess.DEVNULL,
756
+ capture_output=True, text=True, timeout=10, check=False,
757
+ )
758
+ except (OSError, subprocess.TimeoutExpired):
759
+ result["reason_code"] = "CODEX_FEATURES_UNAVAILABLE"
760
+ return result
761
+ if features_run.returncode:
762
+ result["reason_code"] = "CODEX_FEATURES_UNAVAILABLE"
763
+ return result
764
+ try:
765
+ feature_names = _feature_names(features_run.stdout)
766
+ except ValueError:
767
+ result["reason_code"] = "CODEX_FEATURES_UNAVAILABLE"
768
+ return result
769
+ unsupported = sorted(set(DISABLED_FEATURES) - feature_names)
770
+ if unsupported:
771
+ result["reason_code"] = "CODEX_FEATURE_FLAGS_INCOMPATIBLE"
772
+ result["unsupported_feature_flags"] = unsupported
773
+ return result
774
+ result.update(
775
+ available=True,
776
+ auth_mode="chatgpt_subscription",
777
+ codex_version=".".join(str(value) for value in version),
778
+ )
779
+ return result
780
+
781
+
782
+ def _child_command(codex: str, plan: dict[str, Any], output: Path, schema: Path, work: Path) -> list[str]:
783
+ command = [
784
+ codex,
785
+ "exec",
786
+ "--strict-config",
787
+ "--ephemeral",
788
+ "--ignore-user-config",
789
+ "--ignore-rules",
790
+ "--skip-git-repo-check",
791
+ "--sandbox",
792
+ "read-only",
793
+ "--model",
794
+ plan["model_id"],
795
+ "--cd",
796
+ str(work),
797
+ "--output-schema",
798
+ str(schema),
799
+ "--output-last-message",
800
+ str(output),
801
+ "--json",
802
+ "-c",
803
+ f'model_reasoning_effort="{plan["reasoning_effort"]}"',
804
+ "-c",
805
+ 'web_search="disabled"',
806
+ "-c",
807
+ "mcp_servers={}",
808
+ "-c",
809
+ "analytics.enabled=false",
810
+ ]
811
+ for feature in DISABLED_FEATURES:
812
+ command.extend(("--disable", feature))
813
+ command.append("-")
814
+ return command
815
+
816
+
817
+ def _scan_events(raw: bytes) -> None:
818
+ if len(raw) > MAX_EVENT_BYTES:
819
+ _fail("Codex event stream exceeds the sealed limit")
820
+ event_count = 0
821
+ for index, line in enumerate(raw.splitlines()):
822
+ if not line:
823
+ continue
824
+ event_count += 1
825
+ try:
826
+ event = _strict_loads(line)
827
+ except (UnicodeError, ValueError, json.JSONDecodeError) as exc:
828
+ raise MeasurementError(f"malformed Codex event line {index + 1}: {exc}") from exc
829
+ if not isinstance(event, dict):
830
+ _fail(f"Codex event line {index + 1} is not an object")
831
+ event_type = event.get("type")
832
+ if event_type in {"error", "turn.failed"}:
833
+ _fail(f"Codex emitted failure event {event_type!r}")
834
+ item = event.get("item")
835
+ if isinstance(item, dict):
836
+ item_type = item.get("type")
837
+ folded = str(item_type).casefold().replace("-", "_")
838
+ if any(token in folded for token in FORBIDDEN_EVENT_ITEM_TOKENS):
839
+ _fail(f"Codex emitted forbidden tool event item {item_type!r}")
840
+ if event_count == 0:
841
+ _fail("Codex event stream is empty")
842
+
843
+
844
+ def _validate_subject_output(
845
+ value: dict[str, Any], item: dict[str, Any], context: dict[str, Any]
846
+ ) -> None:
847
+ _validate(OUTPUT_SCHEMA_PATH, value, "subject output")
848
+ for field, expected in (
849
+ ("item_id", item["item_id"]),
850
+ ("consumer_id", item["consumer_id"]),
851
+ ("role", item["role"]),
852
+ ):
853
+ if value[field] != expected:
854
+ _fail(f"subject output {field} does not match the sealed assignment")
855
+ selected = context["selected_criterion_ids"]
856
+ applicability_ids = [row["criterion_id"] for row in value["applicability"]]
857
+ if applicability_ids != selected:
858
+ _fail("subject output applicability must cover selected criterion ids in order")
859
+ finding_ids: set[str] = set()
860
+ for finding in value["findings"]:
861
+ if finding["finding_id"] in finding_ids:
862
+ _fail("subject output contains duplicate finding_id")
863
+ finding_ids.add(finding["finding_id"])
864
+ if not set(finding["criterion_ids"]).issubset(set(selected)):
865
+ _fail("subject output finding names an unselected criterion")
866
+ remedy = finding["remedy"]
867
+ if remedy["status"] == "none":
868
+ expected = {
869
+ "minimum_action": None,
870
+ "effort_scope": "none",
871
+ "changes_research_intent": "not_applicable",
872
+ "requires_new_data": False,
873
+ }
874
+ if any(remedy[key] != expected_value for key, expected_value in expected.items()):
875
+ _fail("no-remedy subject output has contradictory action fields")
876
+ if remedy["no_honest_reason"] is None:
877
+ _fail("no-remedy subject output requires no_honest_reason")
878
+ else:
879
+ if remedy["minimum_action"] is None or remedy["effort_scope"] == "none":
880
+ _fail("available remedy requires an action and non-none effort scope")
881
+ if remedy["no_honest_reason"] is not None:
882
+ _fail("available remedy cannot carry no_honest_reason")
883
+ if remedy["effort_scope"] == "new_data" and remedy["requires_new_data"] is not True:
884
+ _fail("new_data remedy must declare requires_new_data=true")
885
+
886
+
887
+ def _rfc3339_now() -> str:
888
+ return dt.datetime.now(dt.timezone.utc).isoformat().replace("+00:00", "Z")
889
+
890
+
891
+ def _copy_auth(source: Path, target: Path) -> None:
892
+ raw = _safe_explicit_file(source, limit=1024 * 1024)
893
+ if not isinstance(_strict_loads(raw), dict):
894
+ _fail("Codex subscription auth root must be an object")
895
+ _atomic_create(target, raw)
896
+
897
+
898
+ def _retain_blocked_io(
899
+ run_dir: Path,
900
+ call_id: str,
901
+ stdout: bytes | None,
902
+ stderr: bytes | None,
903
+ output_path: Path | None,
904
+ ) -> None:
905
+ blocked_root = run_dir / "blocked"
906
+ for suffix, raw, limit in (
907
+ ("stdout.jsonl", stdout, MAX_EVENT_BYTES),
908
+ ("stderr.txt", stderr, 1024 * 1024),
909
+ ):
910
+ if not raw:
911
+ continue
912
+ if len(raw) <= limit:
913
+ _atomic_create(blocked_root / f"{call_id}.{suffix}", raw)
914
+ else:
915
+ _atomic_create(
916
+ blocked_root / f"{call_id}.{suffix}.oversize.json",
917
+ _json_bytes(
918
+ {
919
+ "retained": False,
920
+ "size_bytes": len(raw),
921
+ "sha256": _sha(raw),
922
+ "reason": "exceeds sealed retention cap",
923
+ }
924
+ ),
925
+ )
926
+ if output_path is None or not output_path.exists():
927
+ return
928
+ try:
929
+ output_raw = _safe_explicit_file(output_path, limit=MAX_OUTPUT_BYTES)
930
+ except MeasurementError as exc:
931
+ _atomic_create(
932
+ blocked_root / f"{call_id}.output-unavailable.json",
933
+ _json_bytes({"retained": False, "reason": str(exc)}),
934
+ )
935
+ else:
936
+ _atomic_create(blocked_root / f"{call_id}.output.raw", output_raw)
937
+
938
+
939
+ def _run_one(
940
+ plan: dict[str, Any], call: dict[str, Any], run_dir: Path, environ: dict[str, str]
941
+ ) -> dict[str, Any]:
942
+ codex = shutil.which("codex", path=environ.get("PATH"))
943
+ if not codex:
944
+ _fail("Codex CLI disappeared after detection")
945
+ prompt_path = run_dir / call["prompt_ref"]
946
+ prompt = _safe_explicit_file(prompt_path)
947
+ if _sha(prompt) != call["prompt_sha256"]:
948
+ _fail(f"prompt hash drift for {call['call_id']}")
949
+ if len(prompt) > plan["input_token_cap"] * 4:
950
+ _fail(f"prompt exceeds local cap for {call['call_id']}")
951
+ started = _rfc3339_now()
952
+ with tempfile.TemporaryDirectory(prefix="ars-rcv-subject-") as temp_name:
953
+ # macOS returns /var/... while /var is a platform symlink to /private/var.
954
+ # Canonicalize this runner-created root once; caller paths remain no-follow.
955
+ temp = Path(temp_name).resolve()
956
+ os.chmod(temp, 0o700)
957
+ child_home = temp / "codex-home"
958
+ work = temp / "work"
959
+ child_home.mkdir(mode=0o700)
960
+ work.mkdir(mode=0o700)
961
+ schema = temp / "subject-output.schema.json"
962
+ provider_schema = _project_provider_response_schema(_schema(OUTPUT_SCHEMA_PATH))
963
+ _validate_provider_response_schema(provider_schema)
964
+ _atomic_create(schema, _json_bytes(provider_schema))
965
+ _copy_auth(_codex_home(environ) / "auth.json", child_home / "auth.json")
966
+ output = temp / "last-message.json"
967
+ child_env = {
968
+ "PATH": environ.get("PATH", os.defpath),
969
+ "CODEX_HOME": str(child_home),
970
+ "HOME": str(temp),
971
+ "TMPDIR": str(temp),
972
+ "LANG": "C",
973
+ "LC_ALL": "C",
974
+ "NO_COLOR": "1",
975
+ }
976
+ command = _child_command(codex, plan, output, schema, work)
977
+ try:
978
+ completed = subprocess.run(
979
+ command,
980
+ input=prompt,
981
+ stdout=subprocess.PIPE,
982
+ stderr=subprocess.PIPE,
983
+ env=child_env,
984
+ cwd=work,
985
+ timeout=1800,
986
+ check=False,
987
+ )
988
+ except subprocess.TimeoutExpired as exc:
989
+ _retain_blocked_io(run_dir, call["call_id"], exc.stdout, exc.stderr, output)
990
+ raise MeasurementError(
991
+ f"subscription CLI timed out for {call['call_id']}"
992
+ ) from exc
993
+ except OSError as exc:
994
+ raise MeasurementError(
995
+ f"subscription CLI failed to start for {call['call_id']}: {exc}"
996
+ ) from exc
997
+ try:
998
+ if completed.returncode != 0:
999
+ _fail(
1000
+ f"subscription CLI exited {completed.returncode} for {call['call_id']}"
1001
+ )
1002
+ _scan_events(completed.stdout)
1003
+ output_raw = _safe_explicit_file(
1004
+ output,
1005
+ limit=min(MAX_OUTPUT_BYTES, plan["output_token_cap"] * 8),
1006
+ )
1007
+ try:
1008
+ output_value = _strict_loads(output_raw)
1009
+ except (UnicodeError, ValueError, json.JSONDecodeError) as exc:
1010
+ raise MeasurementError(
1011
+ f"invalid subject JSON for {call['call_id']}: {exc}"
1012
+ ) from exc
1013
+ if not isinstance(output_value, dict):
1014
+ _fail(f"subject output root is not an object for {call['call_id']}")
1015
+ items, contexts, _registry = _scenario_contexts()
1016
+ by_id = {item["item_id"]: item for item in items}
1017
+ _validate_subject_output(
1018
+ output_value,
1019
+ by_id[call["item_id"]],
1020
+ contexts[call["item_id"]],
1021
+ )
1022
+ except MeasurementError:
1023
+ _retain_blocked_io(
1024
+ run_dir,
1025
+ call["call_id"],
1026
+ completed.stdout,
1027
+ completed.stderr,
1028
+ output,
1029
+ )
1030
+ raise
1031
+ completed_at = _rfc3339_now()
1032
+ _atomic_create(run_dir / call["events_ref"], completed.stdout)
1033
+ normalized_output = _json_bytes(output_value)
1034
+ _atomic_create(run_dir / call["output_ref"], normalized_output)
1035
+ receipt = {
1036
+ "schema_version": RECEIPT_VERSION,
1037
+ "call_id": call["call_id"],
1038
+ "sequence_index": call["sequence_index"],
1039
+ "item_id": call["item_id"],
1040
+ "arm": call["arm"],
1041
+ "replicate": call["replicate"],
1042
+ "transport": "codex_chatgpt_subscription",
1043
+ "auth_mode": "chatgpt_subscription",
1044
+ "model_id": plan["model_id"],
1045
+ "codex_version": plan["codex_version"],
1046
+ "reasoning_effort": plan["reasoning_effort"],
1047
+ "started_at": started,
1048
+ "completed_at": completed_at,
1049
+ "prompt_sha256": call["prompt_sha256"],
1050
+ "output_sha256": _sha(normalized_output),
1051
+ "events_sha256": _sha(completed.stdout),
1052
+ "api_spend_usd": 0,
1053
+ "tools_observed": [],
1054
+ }
1055
+ _atomic_create(run_dir / call["receipt_ref"], _json_bytes(receipt))
1056
+ return receipt
1057
+
1058
+
1059
+ def _load_receipt(plan: dict[str, Any], call: dict[str, Any], run_dir: Path) -> dict[str, Any]:
1060
+ receipt, _ = _load_json(run_dir / call["receipt_ref"])
1061
+ required = {
1062
+ "schema_version", "call_id", "sequence_index", "item_id", "arm", "replicate",
1063
+ "transport", "auth_mode", "model_id", "codex_version", "reasoning_effort",
1064
+ "started_at", "completed_at", "prompt_sha256", "output_sha256",
1065
+ "events_sha256", "api_spend_usd", "tools_observed",
1066
+ }
1067
+ if set(receipt) != required or receipt["schema_version"] != RECEIPT_VERSION:
1068
+ _fail(f"receipt is open or malformed: {call['call_id']}")
1069
+ for field in ("call_id", "sequence_index", "item_id", "arm", "replicate", "prompt_sha256"):
1070
+ if receipt[field] != call[field]:
1071
+ _fail(f"receipt {field} mismatch: {call['call_id']}")
1072
+ if (
1073
+ receipt["transport"] != "codex_chatgpt_subscription"
1074
+ or receipt["auth_mode"] != "chatgpt_subscription"
1075
+ or receipt["model_id"] != plan["model_id"]
1076
+ or receipt["codex_version"] != plan["codex_version"]
1077
+ or receipt["reasoning_effort"] != plan["reasoning_effort"]
1078
+ or receipt["api_spend_usd"] != 0
1079
+ or receipt["tools_observed"] != []
1080
+ ):
1081
+ _fail(f"receipt transport/config mismatch: {call['call_id']}")
1082
+ output_raw = _safe_explicit_file(run_dir / call["output_ref"])
1083
+ events_raw = _safe_explicit_file(run_dir / call["events_ref"])
1084
+ if _sha(output_raw) != receipt["output_sha256"] or _sha(events_raw) != receipt["events_sha256"]:
1085
+ _fail(f"receipt artifact hash mismatch: {call['call_id']}")
1086
+ _scan_events(events_raw)
1087
+ return receipt
1088
+
1089
+
1090
+ def _validate_run_plan(plan: dict[str, Any]) -> None:
1091
+ required = {
1092
+ "schema_version", "suite", "suite_commit", "content_class", "transport",
1093
+ "auth_mode", "api_spend_ceiling_usd", "codex_version", "model_id",
1094
+ "reasoning_effort", "sampling", "input_token_cap", "output_token_cap",
1095
+ "tools", "isolation", "suite_lock_sha256", "call_plan_sha256", "calls",
1096
+ }
1097
+ if set(plan) != required:
1098
+ _fail("run plan is open or incomplete")
1099
+ if (
1100
+ plan["schema_version"] != RUN_PLAN_VERSION
1101
+ or plan["suite"] != SUITE
1102
+ or COMMIT_RE.fullmatch(plan["suite_commit"]) is None
1103
+ or plan["content_class"] != "repository_owned_synthetic"
1104
+ or plan["transport"] != "codex_chatgpt_subscription"
1105
+ or plan["auth_mode"] != "chatgpt_subscription"
1106
+ or plan["api_spend_ceiling_usd"] != 0
1107
+ or MODEL_RE.fullmatch(plan["model_id"]) is None
1108
+ or plan["reasoning_effort"] not in {"low", "medium", "high", "xhigh"}
1109
+ or plan["sampling"] != "provider_managed_not_exposed"
1110
+ or type(plan["input_token_cap"]) is not int
1111
+ or type(plan["output_token_cap"]) is not int
1112
+ or plan["input_token_cap"] < 1
1113
+ or plan["output_token_cap"] < 1
1114
+ or plan["tools"] != []
1115
+ or SHA_RE.fullmatch(plan["suite_lock_sha256"]) is None
1116
+ or SHA_RE.fullmatch(plan["call_plan_sha256"]) is None
1117
+ ):
1118
+ _fail("run plan identity/configuration is invalid")
1119
+ isolation = plan["isolation"]
1120
+ if not isinstance(isolation, dict) or set(isolation) != {
1121
+ "ephemeral_auth_home", "empty_working_root", "ignore_user_config",
1122
+ "local_tools_disabled", "web_disabled", "forbidden_event_scan",
1123
+ } or any(value is not True for value in isolation.values()):
1124
+ _fail("run plan isolation attestations must be the exact all-true set")
1125
+ calls = plan["calls"]
1126
+ if not isinstance(calls, list) or len(calls) != 24:
1127
+ _fail("run plan must contain exactly 24 calls")
1128
+ expected_call_keys = {
1129
+ "sequence_index", "call_id", "item_id", "arm", "replicate", "prompt_ref",
1130
+ "prompt_sha256", "output_ref", "events_ref", "receipt_ref",
1131
+ }
1132
+ frozen_plan, _ = _load_json(CALL_PLAN_PATH)
1133
+ for index, (call, frozen_call) in enumerate(zip(calls, frozen_plan["calls"]), 1):
1134
+ if not isinstance(call, dict) or set(call) != expected_call_keys:
1135
+ _fail(f"run plan call {index} is open or incomplete")
1136
+ if call["sequence_index"] != index or SHA_RE.fullmatch(call["prompt_sha256"]) is None:
1137
+ _fail(f"run plan call {index} sequence/hash is invalid")
1138
+ for field in ("sequence_index", "call_id", "item_id", "arm", "replicate"):
1139
+ if call[field] != frozen_call[field]:
1140
+ _fail(f"run plan call {index} drifts from call_plan.json at {field}")
1141
+ expected_refs = {
1142
+ "prompt_ref": f"prompts/{call['call_id']}.txt",
1143
+ "output_ref": f"outputs/{call['call_id']}.json",
1144
+ "events_ref": f"events/{call['call_id']}.jsonl",
1145
+ "receipt_ref": f"receipts/{call['call_id']}.json",
1146
+ }
1147
+ if any(call[field] != value for field, value in expected_refs.items()):
1148
+ _fail(f"run plan call {index} has a noncanonical artifact reference")
1149
+
1150
+
1151
+ def _validate_plan_authority(plan: dict[str, Any]) -> None:
1152
+ """Bind a persisted run plan back to the exact locked main-history suite."""
1153
+ _validate_run_plan(plan)
1154
+ assets = _validate_lock()
1155
+ if _sha(_safe_explicit_file(LOCK_PATH)) != plan["suite_lock_sha256"]:
1156
+ _fail("run plan suite_lock_sha256 no longer matches the frozen assets")
1157
+ if _sha(_safe_explicit_file(CALL_PLAN_PATH)) != plan["call_plan_sha256"]:
1158
+ _fail("run plan call_plan_sha256 no longer matches the exact 24-call plan")
1159
+ _verify_frozen_commit(plan["suite_commit"], assets)
1160
+
1161
+
1162
+ def dispatch(args: argparse.Namespace, environ: dict[str, str] | None = None) -> dict[str, Any]:
1163
+ if not args.execute_24_subscription_calls:
1164
+ _fail("dispatch requires --execute-24-subscription-calls")
1165
+ validate_assets()
1166
+ env = dict(os.environ if environ is None else environ)
1167
+ run_dir = args.run_dir.resolve()
1168
+ plan_path = run_dir / "run-plan.json"
1169
+ plan, plan_raw = _load_json(plan_path)
1170
+ if args.plan_sha256 != _sha(plan_raw) or SHA_RE.fullmatch(args.plan_sha256) is None:
1171
+ _fail("--plan-sha256 does not match the frozen run-plan bytes")
1172
+ _validate_plan_authority(plan)
1173
+ detection = detect(plan["model_id"], env)
1174
+ if not detection["available"]:
1175
+ _fail(f"subscription transport unavailable: {detection['reason_code']}")
1176
+ if detection["codex_version"] != plan["codex_version"]:
1177
+ _fail("detected Codex version differs from the frozen run plan")
1178
+ receipts: list[dict[str, Any]] = []
1179
+ for call in plan["calls"]:
1180
+ receipt_path = run_dir / call["receipt_ref"]
1181
+ blocked_path = run_dir / "blocked" / f"{call['call_id']}.json"
1182
+ if blocked_path.exists():
1183
+ _fail(
1184
+ f"call {call['call_id']} is already recorded blocked; this plan "
1185
+ "does not authorize a retry"
1186
+ )
1187
+ if receipt_path.exists():
1188
+ receipts.append(_load_receipt(plan, call, run_dir))
1189
+ continue
1190
+ orphaned = [
1191
+ ref for ref in (call["output_ref"], call["events_ref"])
1192
+ if (run_dir / ref).exists()
1193
+ ]
1194
+ if orphaned:
1195
+ _fail(
1196
+ f"call {call['call_id']} has artifacts without a closed receipt: "
1197
+ + ", ".join(orphaned)
1198
+ )
1199
+ try:
1200
+ receipts.append(_run_one(plan, call, run_dir, env))
1201
+ except MeasurementError as exc:
1202
+ if not blocked_path.exists():
1203
+ _atomic_create(
1204
+ blocked_path,
1205
+ _json_bytes(
1206
+ {
1207
+ "schema_version": "review-criteria-blocked-call/1.0",
1208
+ "call_id": call["call_id"],
1209
+ "sequence_index": call["sequence_index"],
1210
+ "reason": str(exc),
1211
+ "partial_published": True,
1212
+ "api_spend_usd": 0,
1213
+ }
1214
+ ),
1215
+ )
1216
+ raise
1217
+ manifest = {
1218
+ "schema_version": "heldout-execution-manifest/1.0",
1219
+ "suite": SUITE,
1220
+ "created_at": receipts[0]["started_at"],
1221
+ "write_once": True,
1222
+ "execution_window": {
1223
+ "window_id": f"{SUITE}-subscription-window",
1224
+ "started_at": receipts[0]["started_at"],
1225
+ "completed_at": receipts[-1]["completed_at"],
1226
+ },
1227
+ "calls": [
1228
+ {
1229
+ "call_id": receipt["call_id"],
1230
+ "sequence_index": receipt["sequence_index"],
1231
+ "started_at": receipt["started_at"],
1232
+ "completed_at": receipt["completed_at"],
1233
+ "prompt_sha256": receipt["prompt_sha256"],
1234
+ "output_sha256": receipt["output_sha256"],
1235
+ "concurrency_group": None,
1236
+ "attempt": 1,
1237
+ }
1238
+ for receipt in receipts
1239
+ ],
1240
+ }
1241
+ _validate(EXECUTION_SCHEMA_PATH, manifest, "execution manifest")
1242
+ manifest_path = run_dir / "execution-manifest.json"
1243
+ if manifest_path.exists():
1244
+ existing, existing_raw = _load_json(manifest_path)
1245
+ if existing != manifest:
1246
+ _fail("write-once execution manifest conflicts with completed receipts")
1247
+ manifest_raw = existing_raw
1248
+ else:
1249
+ manifest_raw = _json_bytes(manifest)
1250
+ _atomic_create(manifest_path, manifest_raw)
1251
+ return {
1252
+ "completed_calls": len(receipts),
1253
+ "execution_manifest": str(manifest_path),
1254
+ "execution_manifest_sha256": _sha(manifest_raw),
1255
+ "api_spend_usd": 0,
1256
+ }
1257
+
1258
+
1259
+ def _complete_outputs(run_dir: Path) -> tuple[dict[str, Any], list[dict[str, Any]], dict[str, dict[str, Any]]]:
1260
+ plan, _ = _load_json(run_dir / "run-plan.json")
1261
+ _validate_plan_authority(plan)
1262
+ items, contexts, _registry = _scenario_contexts()
1263
+ by_id = {item["item_id"]: item for item in items}
1264
+ outputs = []
1265
+ for call in plan["calls"]:
1266
+ _load_receipt(plan, call, run_dir)
1267
+ output, _ = _load_json(run_dir / call["output_ref"])
1268
+ _validate_subject_output(output, by_id[call["item_id"]], contexts[call["item_id"]])
1269
+ outputs.append({"call": call, "output": output})
1270
+ return plan, outputs, contexts
1271
+
1272
+
1273
+ def prepare_expert_packet(args: argparse.Namespace) -> dict[str, Any]:
1274
+ validate_assets()
1275
+ run_dir = args.run_dir.resolve()
1276
+ plan, outputs, contexts = _complete_outputs(run_dir)
1277
+ items, _context_map, _registry = _scenario_contexts()
1278
+ by_id = {item["item_id"]: item for item in items}
1279
+ blinded: list[dict[str, Any]] = []
1280
+ mapping: list[dict[str, Any]] = []
1281
+ used: set[str] = set()
1282
+ for row in outputs:
1283
+ while True:
1284
+ blind_id = f"blind-{secrets.token_hex(8)}"
1285
+ if blind_id not in used:
1286
+ used.add(blind_id)
1287
+ break
1288
+ call = row["call"]
1289
+ item = by_id[call["item_id"]]
1290
+ blinded.append(
1291
+ {
1292
+ "blind_output_id": blind_id,
1293
+ "scenario": {
1294
+ "title": item["title"],
1295
+ "manuscript": item["manuscript"],
1296
+ "author_intent": item["author_intent"],
1297
+ "review_task": item["review_task"],
1298
+ },
1299
+ "target_context": contexts[call["item_id"]],
1300
+ "subject_output": row["output"],
1301
+ }
1302
+ )
1303
+ mapping.append(
1304
+ {
1305
+ "blind_output_id": blind_id,
1306
+ "call_id": call["call_id"],
1307
+ "item_id": call["item_id"],
1308
+ "arm": call["arm"],
1309
+ "replicate": call["replicate"],
1310
+ }
1311
+ )
1312
+ blinded.sort(key=lambda row: row["blind_output_id"])
1313
+ mapping.sort(key=lambda row: row["blind_output_id"])
1314
+ packet = {
1315
+ "schema_version": "review-criteria-expert-packet/1.0",
1316
+ "suite": SUITE,
1317
+ "content_class": "repository_owned_synthetic",
1318
+ "blinding": BLINDING,
1319
+ "outputs": blinded,
1320
+ }
1321
+ _validate(EXPERT_PACKET_SCHEMA_PATH, packet, "expert packet")
1322
+ packet_raw = _json_bytes(packet)
1323
+ packet_path = args.output.resolve()
1324
+ map_path = args.arm_map.resolve()
1325
+ _atomic_create(packet_path, packet_raw)
1326
+ _atomic_create(
1327
+ map_path,
1328
+ _json_bytes(
1329
+ {
1330
+ "schema_version": "review-criteria-arm-map/1.0",
1331
+ "suite": SUITE,
1332
+ "packet_sha256": _sha(packet_raw),
1333
+ "run_plan_sha256": _sha(_safe_explicit_file(run_dir / "run-plan.json")),
1334
+ "model_id": plan["model_id"],
1335
+ "mapping": mapping,
1336
+ }
1337
+ ),
1338
+ )
1339
+ return {
1340
+ "expert_packet": str(packet_path),
1341
+ "expert_packet_sha256": _sha(packet_raw),
1342
+ "arm_map": str(map_path),
1343
+ "outputs": 24,
1344
+ }
1345
+
1346
+
1347
+ def _indexed(rows: list[dict[str, Any]], key: str, label: str) -> dict[str, dict[str, Any]]:
1348
+ result: dict[str, dict[str, Any]] = {}
1349
+ for row in rows:
1350
+ value = row[key]
1351
+ if value in result:
1352
+ _fail(f"duplicate {key} in {label}: {value}")
1353
+ result[value] = row
1354
+ return result
1355
+
1356
+
1357
+ def _validate_arm_map(
1358
+ arm_map: dict[str, Any], packet_sha: str, plan: dict[str, Any], plan_raw: bytes
1359
+ ) -> dict[str, dict[str, Any]]:
1360
+ if set(arm_map) != {
1361
+ "schema_version", "suite", "packet_sha256", "run_plan_sha256",
1362
+ "model_id", "mapping",
1363
+ }:
1364
+ _fail("arm map is open or incomplete")
1365
+ if (
1366
+ arm_map["schema_version"] != "review-criteria-arm-map/1.0"
1367
+ or arm_map["suite"] != SUITE
1368
+ or arm_map["packet_sha256"] != packet_sha
1369
+ or arm_map["run_plan_sha256"] != _sha(plan_raw)
1370
+ or arm_map["model_id"] != plan["model_id"]
1371
+ or not isinstance(arm_map["mapping"], list)
1372
+ or len(arm_map["mapping"]) != 24
1373
+ ):
1374
+ _fail("arm map identity/hash/model mismatch")
1375
+ mapping_index = _indexed(arm_map["mapping"], "blind_output_id", "arm map")
1376
+ call_index = _indexed(plan["calls"], "call_id", "run plan")
1377
+ if {row.get("call_id") for row in arm_map["mapping"]} != set(call_index):
1378
+ _fail("arm map must cover every run-plan call exactly once")
1379
+ for blind_id, mapping in mapping_index.items():
1380
+ if set(mapping) != {"blind_output_id", "call_id", "item_id", "arm", "replicate"}:
1381
+ _fail(f"arm map row is open or incomplete: {blind_id}")
1382
+ call = call_index.get(mapping["call_id"])
1383
+ if call is None or any(
1384
+ mapping[field] != call[field] for field in ("item_id", "arm", "replicate")
1385
+ ):
1386
+ _fail(f"arm map row does not match the frozen call: {blind_id}")
1387
+ return mapping_index
1388
+
1389
+
1390
+ def _validate_packet_binding(
1391
+ packet: dict[str, Any],
1392
+ mapping_index: dict[str, dict[str, Any]],
1393
+ outputs: list[dict[str, Any]],
1394
+ contexts: dict[str, dict[str, Any]],
1395
+ ) -> dict[str, dict[str, Any]]:
1396
+ packet_index = _indexed(packet["outputs"], "blind_output_id", "expert packet")
1397
+ if set(packet_index) != set(mapping_index):
1398
+ _fail("expert packet and arm map must cover the same blind ids")
1399
+ call_outputs = {row["call"]["call_id"]: row["output"] for row in outputs}
1400
+ items, _contexts, _registry = _scenario_contexts()
1401
+ item_index = {item["item_id"]: item for item in items}
1402
+ for blind_id, mapping in mapping_index.items():
1403
+ item = item_index[mapping["item_id"]]
1404
+ expected_scenario = {
1405
+ "title": item["title"],
1406
+ "manuscript": item["manuscript"],
1407
+ "author_intent": item["author_intent"],
1408
+ "review_task": item["review_task"],
1409
+ }
1410
+ packet_row = packet_index[blind_id]
1411
+ if packet_row["scenario"] != expected_scenario:
1412
+ _fail(f"expert packet scenario drift for {blind_id}")
1413
+ if packet_row["target_context"] != contexts[mapping["item_id"]]:
1414
+ _fail(f"expert packet target-context drift for {blind_id}")
1415
+ if packet_row["subject_output"] != call_outputs[mapping["call_id"]]:
1416
+ _fail(f"expert packet subject-output drift for {blind_id}")
1417
+ return packet_index
1418
+
1419
+
1420
+ def _validate_label_coverage(packet: dict[str, Any], labels: dict[str, Any]) -> None:
1421
+ _validate(EXPERT_LABELS_SCHEMA_PATH, labels, "expert labels")
1422
+ output_index = _indexed(packet["outputs"], "blind_output_id", "expert packet")
1423
+ label_index = _indexed(labels["labels"], "blind_output_id", "expert labels")
1424
+ if set(output_index) != set(label_index):
1425
+ _fail("expert labels must cover the exact blinded output ids")
1426
+ for blind_id, output_row in output_index.items():
1427
+ subject = output_row["subject_output"]
1428
+ label = label_index[blind_id]
1429
+ predicted_criteria = [row["criterion_id"] for row in subject["applicability"]]
1430
+ labelled_criteria = [row["criterion_id"] for row in label["applicability"]]
1431
+ if labelled_criteria != predicted_criteria:
1432
+ _fail(f"expert applicability coverage/order mismatch for {blind_id}")
1433
+ predicted_findings = [row["finding_id"] for row in subject["findings"]]
1434
+ labelled_findings = [row["finding_id"] for row in label["findings"]]
1435
+ if labelled_findings != predicted_findings:
1436
+ _fail(f"expert finding coverage/order mismatch for {blind_id}")
1437
+
1438
+
1439
+ def validate_labels(args: argparse.Namespace) -> dict[str, Any]:
1440
+ packet, packet_raw = _load_json(args.packet.resolve())
1441
+ _validate(EXPERT_PACKET_SCHEMA_PATH, packet, "expert packet")
1442
+ labels, _ = _load_json(args.labels.resolve())
1443
+ if labels.get("packet_sha256") != _sha(packet_raw):
1444
+ _fail("expert labels packet_sha256 mismatch")
1445
+ _validate_label_coverage(packet, labels)
1446
+ return {
1447
+ "expert_id": labels["expert"]["expert_id"],
1448
+ "labels": len(labels["labels"]),
1449
+ "packet_sha256": labels["packet_sha256"],
1450
+ }
1451
+
1452
+
1453
+ def finalize(args: argparse.Namespace) -> dict[str, Any]:
1454
+ validate_assets()
1455
+ if len(args.expert_labels) != 2:
1456
+ _fail("finalize requires exactly two independent expert-label files")
1457
+ run_dir = args.run_dir.resolve()
1458
+ plan, outputs, contexts = _complete_outputs(run_dir)
1459
+ plan_raw = _safe_explicit_file(run_dir / "run-plan.json")
1460
+ packet, packet_raw = _load_json(args.packet.resolve())
1461
+ _validate(EXPERT_PACKET_SCHEMA_PATH, packet, "expert packet")
1462
+ packet_sha = _sha(packet_raw)
1463
+ arm_map, _ = _load_json(args.arm_map.resolve())
1464
+ map_index = _validate_arm_map(arm_map, packet_sha, plan, plan_raw)
1465
+ packet_index = _validate_packet_binding(packet, map_index, outputs, contexts)
1466
+
1467
+ labels: list[dict[str, Any]] = []
1468
+ for path in args.expert_labels:
1469
+ value, _ = _load_json(path.resolve())
1470
+ if value.get("packet_sha256") != packet_sha:
1471
+ _fail("expert labels packet_sha256 mismatch")
1472
+ _validate_label_coverage(packet, value)
1473
+ labels.append(value)
1474
+ expert_ids = [value["expert"]["expert_id"] for value in labels]
1475
+ if len({value.casefold() for value in expert_ids}) != 2:
1476
+ _fail("expert ids must be distinct")
1477
+ decisions, _ = _load_json(args.decisions.resolve())
1478
+ _validate(DECISIONS_SCHEMA_PATH, decisions, "adjudication decisions")
1479
+ if decisions["packet_sha256"] != packet_sha:
1480
+ _fail("adjudication decisions packet_sha256 mismatch")
1481
+ decision_index = _indexed(decisions["decisions"], "blind_output_id", "decisions")
1482
+ if set(decision_index) != set(packet_index):
1483
+ _fail("adjudication decisions must cover the exact expert packet")
1484
+ label_indices = [_indexed(value["labels"], "blind_output_id", "expert labels") for value in labels]
1485
+ call_outputs = {row["call"]["call_id"]: row["output"] for row in outputs}
1486
+ by_item: dict[str, dict[str, Any]] = {}
1487
+ for blind_id, mapping in map_index.items():
1488
+ item_id = mapping["item_id"]
1489
+ by_item.setdefault(
1490
+ item_id,
1491
+ {
1492
+ "item_id": item_id,
1493
+ "target_context": {
1494
+ "context_ref": f"sealed/contexts/{item_id}.json",
1495
+ "context_sha256": _sha(_canonical(contexts[item_id])),
1496
+ "resolved_digest": contexts[item_id]["resolved_digest"],
1497
+ "selected_criterion_ids": contexts[item_id]["selected_criterion_ids"],
1498
+ },
1499
+ "arms": {"baseline": [], "treatment": []},
1500
+ },
1501
+ )
1502
+ subject = call_outputs[mapping["call_id"]]
1503
+ raw_labels = [index[blind_id] for index in label_indices]
1504
+ decision = decision_index[blind_id]
1505
+ if [row["criterion_id"] for row in decision["applicability"]] != [
1506
+ row["criterion_id"] for row in subject["applicability"]
1507
+ ]:
1508
+ _fail(f"decision applicability coverage/order mismatch for {blind_id}")
1509
+ if [row["finding_id"] for row in decision["findings"]] != [
1510
+ row["finding_id"] for row in subject["findings"]
1511
+ ]:
1512
+ _fail(f"decision finding coverage/order mismatch for {blind_id}")
1513
+ applicability = []
1514
+ for index, predicted in enumerate(subject["applicability"]):
1515
+ values = [row["applicability"][index]["label"] for row in raw_labels]
1516
+ final = decision["applicability"][index]["expert_label"]
1517
+ if len(set(values)) == 1 and final != values[0]:
1518
+ _fail(f"adjudication overturns unanimous applicability for {blind_id}")
1519
+ applicability.append(
1520
+ {
1521
+ "criterion_id": predicted["criterion_id"],
1522
+ "predicted": predicted["predicted"],
1523
+ "expert_labels": [
1524
+ {"expert_id": expert_ids[label_index], "label": values[label_index]}
1525
+ for label_index in range(2)
1526
+ ],
1527
+ "expert_label": final,
1528
+ }
1529
+ )
1530
+ findings = []
1531
+ for index, predicted in enumerate(subject["findings"]):
1532
+ raw_finding = [row["findings"][index] for row in raw_labels]
1533
+ final = decision["findings"][index]
1534
+ for raw_key, final_key in (
1535
+ ("support_label", "support_label"),
1536
+ ("severity", "expert_severity"),
1537
+ ("venue_alignment", "expert_venue_alignment"),
1538
+ ("usefulness", "usefulness"),
1539
+ ):
1540
+ values = [row[raw_key] for row in raw_finding]
1541
+ if len(set(values)) == 1 and final[final_key] != values[0]:
1542
+ _fail(f"adjudication overturns unanimous {raw_key} for {blind_id}")
1543
+ findings.append(
1544
+ {
1545
+ "finding_id": predicted["finding_id"],
1546
+ "expert_labels": [
1547
+ {
1548
+ "expert_id": expert_ids[label_index],
1549
+ "support_label": raw_finding[label_index]["support_label"],
1550
+ "severity": raw_finding[label_index]["severity"],
1551
+ "venue_alignment": raw_finding[label_index]["venue_alignment"],
1552
+ "usefulness": raw_finding[label_index]["usefulness"],
1553
+ }
1554
+ for label_index in range(2)
1555
+ ],
1556
+ "support_label": final["support_label"],
1557
+ "predicted_severity": predicted["predicted_severity"],
1558
+ "expert_severity": final["expert_severity"],
1559
+ "predicted_venue_alignment": predicted["predicted_venue_alignment"],
1560
+ "expert_venue_alignment": final["expert_venue_alignment"],
1561
+ "usefulness": final["usefulness"],
1562
+ }
1563
+ )
1564
+ by_item[item_id]["arms"][mapping["arm"]].append(
1565
+ {
1566
+ "replicate_id": mapping["call_id"],
1567
+ "profile": subject["profile"],
1568
+ "applicability": applicability,
1569
+ "findings": findings,
1570
+ }
1571
+ )
1572
+ item_rows = []
1573
+ budget = {
1574
+ "model_id": plan["model_id"],
1575
+ "model_family": "openai",
1576
+ "tools": [],
1577
+ "sampling": plan["sampling"],
1578
+ "input_token_cap": plan["input_token_cap"],
1579
+ "output_token_cap": plan["output_token_cap"],
1580
+ }
1581
+ for item_id in sorted(by_item):
1582
+ row = by_item[item_id]
1583
+ arms = []
1584
+ for arm, mechanism in (("baseline", "pre_684"), ("treatment", "criteria_binding_v1")):
1585
+ reps = sorted(row["arms"][arm], key=lambda value: value["replicate_id"])
1586
+ arms.append(
1587
+ {
1588
+ "arm_id": arm,
1589
+ "mechanism": mechanism,
1590
+ "target_context": row["target_context"],
1591
+ "budget": budget,
1592
+ "replicates": reps,
1593
+ }
1594
+ )
1595
+ item_rows.append(
1596
+ {"item_id": item_id, "target_context": row["target_context"], "arms": arms}
1597
+ )
1598
+ record = {
1599
+ "schema_version": "review-criteria-paired-adjudication/1.0",
1600
+ "suite": SUITE,
1601
+ "subject": {"suite_commit": plan["suite_commit"], **budget, "replicates_per_item": 2},
1602
+ "experts": [value["expert"] for value in labels],
1603
+ "adjudication": {
1604
+ "adjudicator_id": decisions["adjudicator_id"],
1605
+ "adjudicator_type": decisions["adjudicator_type"],
1606
+ "method": decisions["method"],
1607
+ "arm_blind": True,
1608
+ "disagreements_retained": True,
1609
+ },
1610
+ "items": item_rows,
1611
+ }
1612
+ _validate(PAIRED_SCHEMA_PATH, record, "paired adjudication")
1613
+ output_raw = _json_bytes(record)
1614
+ _atomic_create(args.output.resolve(), output_raw)
1615
+ return {
1616
+ "paired_adjudication": str(args.output.resolve()),
1617
+ "paired_adjudication_sha256": _sha(output_raw),
1618
+ "experts": expert_ids,
1619
+ "items": 6,
1620
+ "replicates": 24,
1621
+ }
1622
+
1623
+
1624
+ def _repo_relative(path: Path, *, under_suite: bool = False) -> str:
1625
+ resolved = path.resolve()
1626
+ if not resolved.is_relative_to(REPO_ROOT):
1627
+ _fail(f"publishable artifact must be inside the repository: {path}")
1628
+ if under_suite and not resolved.is_relative_to(SUITE_ROOT.resolve()):
1629
+ _fail(f"publishable artifact must be inside the held-out suite: {path}")
1630
+ return resolved.relative_to(REPO_ROOT).as_posix()
1631
+
1632
+
1633
+ def _measurement_report_value(
1634
+ *,
1635
+ plan: dict[str, Any],
1636
+ measurement_date: str,
1637
+ paired_ref: str,
1638
+ paired_sha256: str,
1639
+ execution_ref: str,
1640
+ execution_sha256: str,
1641
+ raw_paths: list[str],
1642
+ score: dict[str, Any],
1643
+ ) -> dict[str, Any]:
1644
+ plan_ref = MEASUREMENT_PLAN_PATH.relative_to(REPO_ROOT).as_posix()
1645
+ rubric_ref = EXPERT_GUIDE_PATH.relative_to(REPO_ROOT).as_posix()
1646
+ rubric_sha = _sha(_safe_explicit_file(EXPERT_GUIDE_PATH))
1647
+ plan_sha = _sha(_safe_explicit_file(MEASUREMENT_PLAN_PATH))
1648
+ return {
1649
+ "measurement_contract": "heldout-measurement/1.1",
1650
+ "suite": SUITE,
1651
+ "suite_class": "paired_controls",
1652
+ "measurement_date": measurement_date,
1653
+ "decision_relevant": True,
1654
+ "subject": {
1655
+ "model_id": plan["model_id"],
1656
+ "config": {
1657
+ "suite_commit": plan["suite_commit"],
1658
+ "prompts_ref": (
1659
+ "evals/heldout/review_criteria_constructive_value/"
1660
+ "baseline_prompt.md + treatment_prompt.md + suite_lock.json"
1661
+ ),
1662
+ "settings": (
1663
+ f"Codex CLI {plan['codex_version']}; reasoning={plan['reasoning_effort']}; "
1664
+ "ephemeral auth home; empty read-only root; local/web tools disabled"
1665
+ ),
1666
+ "sampling": plan["sampling"],
1667
+ },
1668
+ },
1669
+ "judge_plan": {
1670
+ "exception": "human_expert_panel",
1671
+ "expert_panel_ref": paired_ref,
1672
+ "expert_panel_sha256": paired_sha256,
1673
+ },
1674
+ "judges": [],
1675
+ "aggregate": {
1676
+ "headline": {
1677
+ "metric_name": "separate_metric_vector_no_composite",
1678
+ "value": "see results.suite_specific; composite_score=null",
1679
+ "construction_rule": (
1680
+ "All pre-registered metrics and treatment-minus-baseline deltas "
1681
+ "remain separate; no composite or substituted efficacy headline."
1682
+ ),
1683
+ "estimand_status": "point_estimate",
1684
+ },
1685
+ "agreement": {
1686
+ "rate": None,
1687
+ "divergent_items": [],
1688
+ "note": (
1689
+ "Model-judge agreement is not applicable. Raw human-expert labels "
1690
+ "and blind resolutions are retained in expert_panel_ref."
1691
+ ),
1692
+ },
1693
+ },
1694
+ "replicates": {
1695
+ "per_item": 2,
1696
+ "rule_ref": f"{plan_ref}#paired-execution",
1697
+ "spread": {"treatment_minus_baseline": score["deltas"]},
1698
+ "exception": None,
1699
+ },
1700
+ "adjudication": {
1701
+ "applies": True,
1702
+ "rubric_ref": rubric_ref,
1703
+ "rubric_sha256": rubric_sha,
1704
+ "rubric_precommitted": True,
1705
+ "blinded_to": ["condition", "mechanism_state", "raw_aggregate"],
1706
+ "overrides": [],
1707
+ "raw_published": True,
1708
+ "resolution_direction": "bidirectional",
1709
+ "resolution_rule_ref": (
1710
+ f"{rubric_ref} and adjudication_decisions.schema.json"
1711
+ ),
1712
+ },
1713
+ "preregistration": {
1714
+ "plan_ref": plan_ref,
1715
+ "plan_sha256": plan_sha,
1716
+ "rubric_ref": rubric_ref,
1717
+ "rubric_sha256": rubric_sha,
1718
+ "frozen_commit": plan["suite_commit"],
1719
+ "frozen_before_dispatch": True,
1720
+ "rubric_and_plan_frozen_together": True,
1721
+ "judge_template_version": "review-criteria-human-expert-label/1.0",
1722
+ "amendments_append_only": True,
1723
+ "amendments": [],
1724
+ },
1725
+ "execution_manifest": {
1726
+ "ref": execution_ref,
1727
+ "sha256": execution_sha256,
1728
+ "write_once": True,
1729
+ "claims": ["ordering"],
1730
+ },
1731
+ "attempts": {
1732
+ "atomicity": (
1733
+ "one fresh isolated subscription call per pre-registered design cell; "
1734
+ "a blocked cell stops dispatch and this plan authorizes no retry"
1735
+ ),
1736
+ "partial_published": False,
1737
+ "blocked_runs": [],
1738
+ },
1739
+ "raw_outputs": {"retained": True, "paths": raw_paths},
1740
+ "results": {
1741
+ "design": "balanced paired-controls measurement",
1742
+ "arm_roles": {
1743
+ "treatment_or_cohort_arms": ["baseline", "treatment"],
1744
+ "variant_packet_arms": [],
1745
+ },
1746
+ "suite_specific": score,
1747
+ },
1748
+ "verdict": (
1749
+ "Observed synthetic-suite metrics are reported separately for the pinned "
1750
+ "subscription model; no general reviewer-superiority claim is made."
1751
+ ),
1752
+ "caveats": [
1753
+ "Repository-owned synthetic scenarios only; results do not establish real-world venue acceptance.",
1754
+ "One pinned subject model and two human experts; no cross-model efficacy claim.",
1755
+ "Subscription quota was consumed; incremental metered API spend was USD 0.",
1756
+ ],
1757
+ }
1758
+
1759
+
1760
+ def build_report(args: argparse.Namespace) -> dict[str, Any]:
1761
+ validate_assets()
1762
+ try:
1763
+ dt.date.fromisoformat(args.measurement_date)
1764
+ except ValueError as exc:
1765
+ raise MeasurementError("measurement_date must be a real ISO date") from exc
1766
+ run_dir = args.run_dir.resolve()
1767
+ plan, _outputs, _contexts = _complete_outputs(run_dir)
1768
+ _validate_run_plan(plan)
1769
+ paired_path = args.paired_adjudication.resolve()
1770
+ paired, paired_raw = _load_json(paired_path)
1771
+ _validate(PAIRED_SCHEMA_PATH, paired, "paired adjudication")
1772
+ if (
1773
+ paired["subject"]["suite_commit"] != plan["suite_commit"]
1774
+ or paired["subject"]["model_id"] != plan["model_id"]
1775
+ or paired["subject"]["input_token_cap"] != plan["input_token_cap"]
1776
+ or paired["subject"]["output_token_cap"] != plan["output_token_cap"]
1777
+ ):
1778
+ _fail("paired adjudication subject does not match the frozen run plan")
1779
+ score = score_paired_record(paired, paired_raw)
1780
+ execution_path = run_dir / "execution-manifest.json"
1781
+ execution, execution_raw = _load_json(execution_path)
1782
+ _validate(EXECUTION_SCHEMA_PATH, execution, "execution manifest")
1783
+ if len(execution["calls"]) != 24:
1784
+ _fail("execution manifest must retain all 24 completed calls")
1785
+ run_ref = _repo_relative(run_dir, under_suite=True)
1786
+ paired_ref = _repo_relative(paired_path, under_suite=True)
1787
+ execution_ref = _repo_relative(execution_path, under_suite=True)
1788
+ raw_paths = [run_ref]
1789
+ if not paired_path.is_relative_to(run_dir):
1790
+ raw_paths.append(paired_ref)
1791
+ report = _measurement_report_value(
1792
+ plan=plan,
1793
+ measurement_date=args.measurement_date,
1794
+ paired_ref=paired_ref,
1795
+ paired_sha256=_sha(paired_raw),
1796
+ execution_ref=execution_ref,
1797
+ execution_sha256=_sha(execution_raw),
1798
+ raw_paths=raw_paths,
1799
+ score=score,
1800
+ )
1801
+ output = args.output.resolve()
1802
+ if not output.is_relative_to(SUITE_ROOT.resolve()):
1803
+ _fail("measurement report output must be inside the held-out suite")
1804
+ errors, _warnings = validate_report(report, resolve_refs=True)
1805
+ errors.extend(location_errors(output, report))
1806
+ if errors:
1807
+ _fail("measurement report validation failed: " + "; ".join(errors))
1808
+ report_raw = _json_bytes(report)
1809
+ _atomic_create(output, report_raw)
1810
+ return {
1811
+ "measurement_report": str(output),
1812
+ "measurement_report_sha256": _sha(report_raw),
1813
+ "expert_panel_sha256": _sha(paired_raw),
1814
+ "execution_manifest_sha256": _sha(execution_raw),
1815
+ "api_spend_usd": 0,
1816
+ }
1817
+
1818
+
1819
+ def _parser() -> argparse.ArgumentParser:
1820
+ parser = argparse.ArgumentParser(description=__doc__)
1821
+ sub = parser.add_subparsers(dest="command", required=True)
1822
+ sub.add_parser("validate-assets")
1823
+
1824
+ detect_parser = sub.add_parser("detect")
1825
+ detect_parser.add_argument("--model", required=True)
1826
+
1827
+ init_parser = sub.add_parser("init-run")
1828
+ init_parser.add_argument("--run-dir", required=True, type=Path)
1829
+ init_parser.add_argument("--suite-commit", required=True)
1830
+ init_parser.add_argument("--model", required=True)
1831
+ init_parser.add_argument("--codex-version", required=True)
1832
+ init_parser.add_argument("--reasoning-effort", default="high")
1833
+ init_parser.add_argument("--input-token-cap", type=int, default=12000)
1834
+ init_parser.add_argument("--output-token-cap", type=int, default=3000)
1835
+
1836
+ dispatch_parser = sub.add_parser("dispatch")
1837
+ dispatch_parser.add_argument("--run-dir", required=True, type=Path)
1838
+ dispatch_parser.add_argument("--plan-sha256", required=True)
1839
+ dispatch_parser.add_argument("--execute-24-subscription-calls", action="store_true")
1840
+
1841
+ packet_parser = sub.add_parser("prepare-expert-packet")
1842
+ packet_parser.add_argument("--run-dir", required=True, type=Path)
1843
+ packet_parser.add_argument("--output", required=True, type=Path)
1844
+ packet_parser.add_argument("--arm-map", required=True, type=Path)
1845
+
1846
+ labels_parser = sub.add_parser("validate-labels")
1847
+ labels_parser.add_argument("--packet", required=True, type=Path)
1848
+ labels_parser.add_argument("--labels", required=True, type=Path)
1849
+
1850
+ final_parser = sub.add_parser("finalize")
1851
+ final_parser.add_argument("--run-dir", required=True, type=Path)
1852
+ final_parser.add_argument("--packet", required=True, type=Path)
1853
+ final_parser.add_argument("--arm-map", required=True, type=Path)
1854
+ final_parser.add_argument("--expert-labels", action="append", required=True, type=Path)
1855
+ final_parser.add_argument("--decisions", required=True, type=Path)
1856
+ final_parser.add_argument("--output", required=True, type=Path)
1857
+
1858
+ report_parser = sub.add_parser("build-report")
1859
+ report_parser.add_argument("--run-dir", required=True, type=Path)
1860
+ report_parser.add_argument("--paired-adjudication", required=True, type=Path)
1861
+ report_parser.add_argument("--measurement-date", required=True)
1862
+ report_parser.add_argument("--output", required=True, type=Path)
1863
+ return parser
1864
+
1865
+
1866
+ def main(argv: list[str] | None = None) -> int:
1867
+ args = _parser().parse_args(argv)
1868
+ try:
1869
+ if args.command == "validate-assets":
1870
+ result = validate_assets()
1871
+ elif args.command == "detect":
1872
+ result = detect(args.model)
1873
+ elif args.command == "init-run":
1874
+ result = init_run(args)
1875
+ elif args.command == "dispatch":
1876
+ result = dispatch(args)
1877
+ elif args.command == "prepare-expert-packet":
1878
+ result = prepare_expert_packet(args)
1879
+ elif args.command == "validate-labels":
1880
+ result = validate_labels(args)
1881
+ elif args.command == "finalize":
1882
+ result = finalize(args)
1883
+ elif args.command == "build-report":
1884
+ result = build_report(args)
1885
+ else: # pragma: no cover
1886
+ raise AssertionError(args.command)
1887
+ except (MeasurementError, ValueError) as exc:
1888
+ print(f"ERROR: {exc}", file=sys.stderr)
1889
+ return 2
1890
+ print(json.dumps(result, ensure_ascii=False, sort_keys=True, indent=2))
1891
+ return 0
1892
+
1893
+
1894
+ if __name__ == "__main__":
1895
+ raise SystemExit(main())