psyclaw 0.27.22 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1048) hide show
  1. package/README.md +11 -5
  2. package/dist/apps/panel/index.html +2 -2
  3. package/dist/src/adapters/pi/extension.js +225 -92
  4. package/dist/src/adapters/pi/extension.js.map +1 -1
  5. package/dist/src/agents/import.js +44 -32
  6. package/dist/src/agents/import.js.map +1 -1
  7. package/dist/src/analysis/hooks.d.ts +1 -0
  8. package/dist/src/analysis/hooks.js +20 -1
  9. package/dist/src/analysis/hooks.js.map +1 -1
  10. package/dist/src/ars/bridge.d.ts +20 -0
  11. package/dist/src/ars/bridge.js +132 -0
  12. package/dist/src/ars/bridge.js.map +1 -0
  13. package/dist/src/ars/contracts.d.ts +55 -0
  14. package/dist/src/ars/contracts.js +2 -0
  15. package/dist/src/ars/contracts.js.map +1 -0
  16. package/dist/src/ars/panel-plan.d.ts +4 -0
  17. package/dist/src/ars/panel-plan.js +11 -0
  18. package/dist/src/ars/panel-plan.js.map +1 -0
  19. package/dist/src/ars/pi-panel-executor.d.ts +30 -0
  20. package/dist/src/ars/pi-panel-executor.js +140 -0
  21. package/dist/src/ars/pi-panel-executor.js.map +1 -0
  22. package/dist/src/ars/profile.d.ts +36 -0
  23. package/dist/src/ars/profile.js +119 -0
  24. package/dist/src/ars/profile.js.map +1 -0
  25. package/dist/src/ars/re-review.d.ts +22 -0
  26. package/dist/src/ars/re-review.js +172 -0
  27. package/dist/src/ars/re-review.js.map +1 -0
  28. package/dist/src/branding.d.ts +2 -4
  29. package/dist/src/branding.js +3 -5
  30. package/dist/src/branding.js.map +1 -1
  31. package/dist/src/bundled-tools.d.ts +3 -0
  32. package/dist/src/bundled-tools.js +21 -0
  33. package/dist/src/bundled-tools.js.map +1 -0
  34. package/dist/src/chat.js +6 -5
  35. package/dist/src/chat.js.map +1 -1
  36. package/dist/src/creation/contracts.d.ts +38 -0
  37. package/dist/src/creation/contracts.js +2 -0
  38. package/dist/src/creation/contracts.js.map +1 -0
  39. package/dist/src/creation/service.d.ts +7 -0
  40. package/dist/src/creation/service.js +196 -0
  41. package/dist/src/creation/service.js.map +1 -0
  42. package/dist/src/index.d.ts +10 -0
  43. package/dist/src/index.js +10 -0
  44. package/dist/src/index.js.map +1 -1
  45. package/dist/src/install/installer.js +32 -10
  46. package/dist/src/install/installer.js.map +1 -1
  47. package/dist/src/orchestration/personas.d.ts +15 -0
  48. package/dist/src/orchestration/personas.js +51 -0
  49. package/dist/src/orchestration/personas.js.map +1 -0
  50. package/dist/src/orchestration/pi-executor.d.ts +1 -0
  51. package/dist/src/orchestration/pi-executor.js +1 -1
  52. package/dist/src/orchestration/pi-executor.js.map +1 -1
  53. package/dist/src/panel/extension.js +29 -8
  54. package/dist/src/panel/extension.js.map +1 -1
  55. package/dist/src/panel/server.js +14 -5
  56. package/dist/src/panel/server.js.map +1 -1
  57. package/dist/src/project/paths.d.ts +3 -0
  58. package/dist/src/project/paths.js +7 -0
  59. package/dist/src/project/paths.js.map +1 -1
  60. package/dist/src/rules/user-rules.d.ts +8 -0
  61. package/dist/src/rules/user-rules.js +36 -0
  62. package/dist/src/rules/user-rules.js.map +1 -0
  63. package/dist/src/skills/contracts.d.ts +4 -4
  64. package/dist/src/skills/recommended.js +1 -1
  65. package/dist/src/skills/registry.js +49 -28
  66. package/dist/src/skills/registry.js.map +1 -1
  67. package/dist/src/style/cli-ui.js +0 -1
  68. package/dist/src/style/cli-ui.js.map +1 -1
  69. package/package.json +14 -3
  70. package/scripts/rebrand-pi.mjs +6 -0
  71. package/skills/recommended/catalog.json +2 -11
  72. package/vendor/ars/.claude/CLAUDE.md +371 -0
  73. package/vendor/ars/.command-invariants.toml +24 -0
  74. package/vendor/ars/CITATION.cff +35 -0
  75. package/vendor/ars/LICENSE +417 -0
  76. package/vendor/ars/MODE_REGISTRY.md +76 -0
  77. package/vendor/ars/NOTICE.md +26 -0
  78. package/vendor/ars/POSITIONING.md +99 -0
  79. package/vendor/ars/PSYCLAW_SOURCE.json +10 -0
  80. package/vendor/ars/README.md +751 -0
  81. package/vendor/ars/SECURITY.md +52 -0
  82. package/vendor/ars/THIRD_PARTY.md +70 -0
  83. package/vendor/ars/academic-paper/SKILL.md +542 -0
  84. package/vendor/ars/academic-paper/agents/abstract_bilingual_agent.md +171 -0
  85. package/vendor/ars/academic-paper/agents/argument_builder_agent.md +276 -0
  86. package/vendor/ars/academic-paper/agents/citation_compliance_agent.md +422 -0
  87. package/vendor/ars/academic-paper/agents/draft_writer_agent.md +656 -0
  88. package/vendor/ars/academic-paper/agents/formatter_agent.md +999 -0
  89. package/vendor/ars/academic-paper/agents/intake_agent.md +393 -0
  90. package/vendor/ars/academic-paper/agents/literature_strategist_agent.md +626 -0
  91. package/vendor/ars/academic-paper/agents/peer_reviewer_agent.md +516 -0
  92. package/vendor/ars/academic-paper/agents/revision_coach_agent.md +334 -0
  93. package/vendor/ars/academic-paper/agents/socratic_mentor_agent.md +527 -0
  94. package/vendor/ars/academic-paper/agents/structure_architect_agent.md +401 -0
  95. package/vendor/ars/academic-paper/agents/visualization_agent.md +441 -0
  96. package/vendor/ars/academic-paper/examples/chinese_paper_example.md +278 -0
  97. package/vendor/ars/academic-paper/examples/clinical_citation_verification_checklist.md +95 -0
  98. package/vendor/ars/academic-paper/examples/clinical_epistemic_status_example.md +100 -0
  99. package/vendor/ars/academic-paper/examples/commitment_ledger_example.md +147 -0
  100. package/vendor/ars/academic-paper/examples/imrad_hei_example.md +234 -0
  101. package/vendor/ars/academic-paper/examples/literature_review_example.md +260 -0
  102. package/vendor/ars/academic-paper/examples/plan_mode_guided_writing.md +600 -0
  103. package/vendor/ars/academic-paper/examples/revision_mode_example.md +344 -0
  104. package/vendor/ars/academic-paper/examples/revision_recovery_example.md +506 -0
  105. package/vendor/ars/academic-paper/examples/version_family_reconciliation_example.md +89 -0
  106. package/vendor/ars/academic-paper/references/abstract_writing_guide.md +169 -0
  107. package/vendor/ars/academic-paper/references/academic_writing_style.md +188 -0
  108. package/vendor/ars/academic-paper/references/anti_leakage_protocol.md +83 -0
  109. package/vendor/ars/academic-paper/references/apa7_chinese_citation_guide.md +364 -0
  110. package/vendor/ars/academic-paper/references/apa7_extended_guide.md +198 -0
  111. package/vendor/ars/academic-paper/references/changelog.md +11 -0
  112. package/vendor/ars/academic-paper/references/citation_format_switcher.md +228 -0
  113. package/vendor/ars/academic-paper/references/committee_correspondence_protocol.md +158 -0
  114. package/vendor/ars/academic-paper/references/credit_authorship_guide.md +308 -0
  115. package/vendor/ars/academic-paper/references/disclosure_mode_protocol.md +478 -0
  116. package/vendor/ars/academic-paper/references/domain_evidence_profiles.md +38 -0
  117. package/vendor/ars/academic-paper/references/failure_paths.md +349 -0
  118. package/vendor/ars/academic-paper/references/funding_statement_guide.md +319 -0
  119. package/vendor/ars/academic-paper/references/hei_domain_glossary.md +169 -0
  120. package/vendor/ars/academic-paper/references/intro_title_rhetoric_guide.md +114 -0
  121. package/vendor/ars/academic-paper/references/journal_submission_guide.md +249 -0
  122. package/vendor/ars/academic-paper/references/latex_template_reference.md +378 -0
  123. package/vendor/ars/academic-paper/references/mode_selection_guide.md +378 -0
  124. package/vendor/ars/academic-paper/references/paper_structure_patterns.md +330 -0
  125. package/vendor/ars/academic-paper/references/plan_mode_protocol.md +112 -0
  126. package/vendor/ars/academic-paper/references/policy_anchor_disclosure_protocol.md +200 -0
  127. package/vendor/ars/academic-paper/references/policy_anchor_table.md +157 -0
  128. package/vendor/ars/academic-paper/references/revision_patch_protocol.md +173 -0
  129. package/vendor/ars/academic-paper/references/statistical_visualization_standards.md +750 -0
  130. package/vendor/ars/academic-paper/references/venue_disclosure_policies.md +259 -0
  131. package/vendor/ars/academic-paper/references/vlm_figure_verification.md +126 -0
  132. package/vendor/ars/academic-paper/references/workflow_phase_details.md +135 -0
  133. package/vendor/ars/academic-paper/references/writing_judgment_framework.md +59 -0
  134. package/vendor/ars/academic-paper/references/writing_quality_check.md +173 -0
  135. package/vendor/ars/academic-paper/templates/bilingual_abstract_template.md +78 -0
  136. package/vendor/ars/academic-paper/templates/case_study_template.md +129 -0
  137. package/vendor/ars/academic-paper/templates/conference_paper_template.md +108 -0
  138. package/vendor/ars/academic-paper/templates/credit_statement_template.md +132 -0
  139. package/vendor/ars/academic-paper/templates/funding_statement_template.md +290 -0
  140. package/vendor/ars/academic-paper/templates/imrad_template.md +183 -0
  141. package/vendor/ars/academic-paper/templates/latex_article_template.tex +199 -0
  142. package/vendor/ars/academic-paper/templates/literature_review_template.md +135 -0
  143. package/vendor/ars/academic-paper/templates/policy_brief_template.md +139 -0
  144. package/vendor/ars/academic-paper/templates/revision_tracking_template.md +199 -0
  145. package/vendor/ars/academic-paper/templates/theoretical_paper_template.md +119 -0
  146. package/vendor/ars/academic-paper-reviewer/SKILL.md +491 -0
  147. package/vendor/ars/academic-paper-reviewer/agents/devils_advocate_reviewer_agent.md +443 -0
  148. package/vendor/ars/academic-paper-reviewer/agents/domain_reviewer_agent.md +412 -0
  149. package/vendor/ars/academic-paper-reviewer/agents/editorial_synthesizer_agent.md +478 -0
  150. package/vendor/ars/academic-paper-reviewer/agents/eic_agent.md +339 -0
  151. package/vendor/ars/academic-paper-reviewer/agents/field_analyst_agent.md +221 -0
  152. package/vendor/ars/academic-paper-reviewer/agents/methodology_reviewer_agent.md +449 -0
  153. package/vendor/ars/academic-paper-reviewer/agents/perspective_reviewer_agent.md +427 -0
  154. package/vendor/ars/academic-paper-reviewer/examples/hei_paper_review_example.md +391 -0
  155. package/vendor/ars/academic-paper-reviewer/examples/interdisciplinary_review_example.md +299 -0
  156. package/vendor/ars/academic-paper-reviewer/examples/subclaim_decomposition_example.md +80 -0
  157. package/vendor/ars/academic-paper-reviewer/references/calibration_mode_protocol.md +256 -0
  158. package/vendor/ars/academic-paper-reviewer/references/changelog.md +10 -0
  159. package/vendor/ars/academic-paper-reviewer/references/editorial_decision_standards.md +236 -0
  160. package/vendor/ars/academic-paper-reviewer/references/guided_mode_protocol.md +34 -0
  161. package/vendor/ars/academic-paper-reviewer/references/integration_guide.md +15 -0
  162. package/vendor/ars/academic-paper-reviewer/references/quality_rubrics.md +84 -0
  163. package/vendor/ars/academic-paper-reviewer/references/re_review_mode_protocol.md +340 -0
  164. package/vendor/ars/academic-paper-reviewer/references/review_criteria_framework.md +98 -0
  165. package/vendor/ars/academic-paper-reviewer/references/review_panel_provenance_protocol.md +197 -0
  166. package/vendor/ars/academic-paper-reviewer/references/review_quality_thinking.md +58 -0
  167. package/vendor/ars/academic-paper-reviewer/references/reviewer_sprint_prompt_source.md +324 -0
  168. package/vendor/ars/academic-paper-reviewer/references/sprint_contract_protocol.md +296 -0
  169. package/vendor/ars/academic-paper-reviewer/references/statistical_reporting_standards.md +505 -0
  170. package/vendor/ars/academic-paper-reviewer/references/top_journals_by_field.md +206 -0
  171. package/vendor/ars/academic-paper-reviewer/templates/editorial_decision_template.md +235 -0
  172. package/vendor/ars/academic-paper-reviewer/templates/peer_review_report_template.md +305 -0
  173. package/vendor/ars/academic-paper-reviewer/templates/revision_response_template.md +248 -0
  174. package/vendor/ars/academic-pipeline/SKILL.md +736 -0
  175. package/vendor/ars/academic-pipeline/agents/claim_ref_alignment_audit_agent.md +382 -0
  176. package/vendor/ars/academic-pipeline/agents/collaboration_depth_agent.md +164 -0
  177. package/vendor/ars/academic-pipeline/agents/integrity_verification_agent.md +870 -0
  178. package/vendor/ars/academic-pipeline/agents/pipeline_orchestrator_agent.md +1379 -0
  179. package/vendor/ars/academic-pipeline/agents/state_tracker_agent.md +622 -0
  180. package/vendor/ars/academic-pipeline/examples/full_pipeline_example.md +482 -0
  181. package/vendor/ars/academic-pipeline/examples/integrity_failure_recovery.md +389 -0
  182. package/vendor/ars/academic-pipeline/examples/mid_entry_example.md +414 -0
  183. package/vendor/ars/academic-pipeline/references/adapters/.gitkeep +0 -0
  184. package/vendor/ars/academic-pipeline/references/adapters/overview.md +153 -0
  185. package/vendor/ars/academic-pipeline/references/ai_research_failure_modes.md +185 -0
  186. package/vendor/ars/academic-pipeline/references/changelog.md +14 -0
  187. package/vendor/ars/academic-pipeline/references/claim_audit_calibration_protocol.md +175 -0
  188. package/vendor/ars/academic-pipeline/references/claim_verification_protocol.md +282 -0
  189. package/vendor/ars/academic-pipeline/references/external_review_protocol.md +131 -0
  190. package/vendor/ars/academic-pipeline/references/integrity_review_protocol.md +110 -0
  191. package/vendor/ars/academic-pipeline/references/literature_corpus_consumers.md +193 -0
  192. package/vendor/ars/academic-pipeline/references/mode_advisor.md +135 -0
  193. package/vendor/ars/academic-pipeline/references/passport_as_reset_boundary.md +132 -0
  194. package/vendor/ars/academic-pipeline/references/pipeline_state_machine.md +405 -0
  195. package/vendor/ars/academic-pipeline/references/plagiarism_detection_protocol.md +239 -0
  196. package/vendor/ars/academic-pipeline/references/process_summary_protocol.md +209 -0
  197. package/vendor/ars/academic-pipeline/references/progress_dashboard_template.md +38 -0
  198. package/vendor/ars/academic-pipeline/references/reinforcement_content.md +15 -0
  199. package/vendor/ars/academic-pipeline/references/reproducibility_audit.md +55 -0
  200. package/vendor/ars/academic-pipeline/references/score_trajectory_protocol.md +78 -0
  201. package/vendor/ars/academic-pipeline/references/team_collaboration_protocol.md +261 -0
  202. package/vendor/ars/academic-pipeline/references/two_stage_review_protocol.md +27 -0
  203. package/vendor/ars/academic-pipeline/templates/pipeline_status_template.md +146 -0
  204. package/vendor/ars/agents/report_compiler_agent.md +341 -0
  205. package/vendor/ars/agents/research_architect_agent.md +298 -0
  206. package/vendor/ars/agents/synthesis_agent.md +356 -0
  207. package/vendor/ars/commands/ars-3w.md +10 -0
  208. package/vendor/ars/commands/ars-abstract.md +10 -0
  209. package/vendor/ars/commands/ars-cache-invalidate.md +20 -0
  210. package/vendor/ars/commands/ars-citation-check.md +10 -0
  211. package/vendor/ars/commands/ars-disclosure.md +10 -0
  212. package/vendor/ars/commands/ars-format-convert.md +10 -0
  213. package/vendor/ars/commands/ars-full.md +9 -0
  214. package/vendor/ars/commands/ars-lit-review.md +12 -0
  215. package/vendor/ars/commands/ars-mark-read.md +18 -0
  216. package/vendor/ars/commands/ars-outline.md +10 -0
  217. package/vendor/ars/commands/ars-plan.md +10 -0
  218. package/vendor/ars/commands/ars-rebuttal-audit.md +12 -0
  219. package/vendor/ars/commands/ars-reviewer.md +9 -0
  220. package/vendor/ars/commands/ars-revision-coach.md +9 -0
  221. package/vendor/ars/commands/ars-revision.md +10 -0
  222. package/vendor/ars/commands/ars-unmark-read.md +16 -0
  223. package/vendor/ars/deep-research/SKILL.md +600 -0
  224. package/vendor/ars/deep-research/agents/bibliography_agent.md +473 -0
  225. package/vendor/ars/deep-research/agents/devils_advocate_agent.md +192 -0
  226. package/vendor/ars/deep-research/agents/editor_in_chief_agent.md +167 -0
  227. package/vendor/ars/deep-research/agents/ethics_review_agent.md +267 -0
  228. package/vendor/ars/deep-research/agents/meta_analysis_agent.md +325 -0
  229. package/vendor/ars/deep-research/agents/monitoring_agent.md +209 -0
  230. package/vendor/ars/deep-research/agents/report_compiler_agent.md +341 -0
  231. package/vendor/ars/deep-research/agents/research_architect_agent.md +298 -0
  232. package/vendor/ars/deep-research/agents/research_question_agent.md +216 -0
  233. package/vendor/ars/deep-research/agents/risk_of_bias_agent.md +231 -0
  234. package/vendor/ars/deep-research/agents/socratic_mentor_agent.md +764 -0
  235. package/vendor/ars/deep-research/agents/source_verification_agent.md +219 -0
  236. package/vendor/ars/deep-research/agents/synthesis_agent.md +356 -0
  237. package/vendor/ars/deep-research/agents/timeline_extraction_agent.md +99 -0
  238. package/vendor/ars/deep-research/examples/exploratory_research.md +157 -0
  239. package/vendor/ars/deep-research/examples/fact_check_mode.md +173 -0
  240. package/vendor/ars/deep-research/examples/handoff_to_paper.md +318 -0
  241. package/vendor/ars/deep-research/examples/idea_diversity_coverage_gap_advisory.md +64 -0
  242. package/vendor/ars/deep-research/examples/policy_analysis.md +161 -0
  243. package/vendor/ars/deep-research/examples/review_mode.md +253 -0
  244. package/vendor/ars/deep-research/examples/socratic_guided_research.md +331 -0
  245. package/vendor/ars/deep-research/examples/systematic_review.md +133 -0
  246. package/vendor/ars/deep-research/references/apa7_style_guide.md +162 -0
  247. package/vendor/ars/deep-research/references/argumentation_reasoning_framework.md +68 -0
  248. package/vendor/ars/deep-research/references/arxiv_api_protocol.md +76 -0
  249. package/vendor/ars/deep-research/references/changelog.md +22 -0
  250. package/vendor/ars/deep-research/references/chinese_literature_api_protocol.md +317 -0
  251. package/vendor/ars/deep-research/references/cross_agent_quality_definitions.md +14 -0
  252. package/vendor/ars/deep-research/references/crossref_api_protocol.md +84 -0
  253. package/vendor/ars/deep-research/references/equator_reporting_guidelines.md +482 -0
  254. package/vendor/ars/deep-research/references/ethics_checklist.md +282 -0
  255. package/vendor/ars/deep-research/references/failure_paths.md +355 -0
  256. package/vendor/ars/deep-research/references/interdisciplinary_bridges.md +292 -0
  257. package/vendor/ars/deep-research/references/irb_decision_tree.md +315 -0
  258. package/vendor/ars/deep-research/references/literature_monitoring_strategies.md +263 -0
  259. package/vendor/ars/deep-research/references/logical_fallacies.md +192 -0
  260. package/vendor/ars/deep-research/references/methodology_patterns.md +462 -0
  261. package/vendor/ars/deep-research/references/mode_selection_guide.md +331 -0
  262. package/vendor/ars/deep-research/references/openalex_api_protocol.md +82 -0
  263. package/vendor/ars/deep-research/references/preregistration_guide.md +324 -0
  264. package/vendor/ars/deep-research/references/semantic_scholar_api_protocol.md +107 -0
  265. package/vendor/ars/deep-research/references/socratic_mode_protocol.md +99 -0
  266. package/vendor/ars/deep-research/references/socratic_questioning_framework.md +232 -0
  267. package/vendor/ars/deep-research/references/source_quality_hierarchy.md +188 -0
  268. package/vendor/ars/deep-research/references/systematic_review_protocol.md +95 -0
  269. package/vendor/ars/deep-research/references/systematic_review_toolkit.md +353 -0
  270. package/vendor/ars/deep-research/templates/evidence_assessment_template.md +127 -0
  271. package/vendor/ars/deep-research/templates/literature_matrix_template.md +85 -0
  272. package/vendor/ars/deep-research/templates/preregistration_template.md +318 -0
  273. package/vendor/ars/deep-research/templates/prisma_protocol_template.md +248 -0
  274. package/vendor/ars/deep-research/templates/prisma_report_template.md +415 -0
  275. package/vendor/ars/deep-research/templates/research_brief_template.md +93 -0
  276. package/vendor/ars/package.json +24 -0
  277. package/vendor/ars/pi/README.md +161 -0
  278. package/vendor/ars/pi/package.json +26 -0
  279. package/vendor/ars/pi/wrapper.js +193 -0
  280. package/vendor/ars/pi/wrapper.test.mjs +201 -0
  281. package/vendor/ars/pyproject.toml +2 -0
  282. package/vendor/ars/requirements-pdf-content-classifier.txt +5 -0
  283. package/vendor/ars/scripts/_block_parser.py +396 -0
  284. package/vendor/ars/scripts/_ci_pytest_manifest.toml +661 -0
  285. package/vendor/ars/scripts/_claim_audit_constants.py +268 -0
  286. package/vendor/ars/scripts/_e4_evidence.py +110 -0
  287. package/vendor/ars/scripts/_eval_threshold_gate.py +73 -0
  288. package/vendor/ars/scripts/_markdown_lint_util.py +224 -0
  289. package/vendor/ars/scripts/_next_verified_at_ms.py +176 -0
  290. package/vendor/ars/scripts/_passport_yaml.py +53 -0
  291. package/vendor/ars/scripts/_skill_lint.py +254 -0
  292. package/vendor/ars/scripts/_text_similarity.py +141 -0
  293. package/vendor/ars/scripts/adapters/README.md +89 -0
  294. package/vendor/ars/scripts/adapters/_common.py +209 -0
  295. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_passport.yaml +25 -0
  296. package/vendor/ars/scripts/adapters/examples/folder_scan/expected_rejection_log.yaml +18 -0
  297. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Chen2024_AIAssessment.pdf +0 -0
  298. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/Wang_2023_formative_feedback.pdf +0 -0
  299. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture/paper1.pdf +0 -0
  300. package/vendor/ars/scripts/adapters/examples/folder_scan/input_fixture//344/270/255/346/226/207/346/252/224/345/220/215_2024.pdf +0 -0
  301. package/vendor/ars/scripts/adapters/examples/obsidian/expected_passport.yaml +40 -0
  302. package/vendor/ars/scripts/adapters/examples/obsidian/expected_rejection_log.yaml +13 -0
  303. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.gitkeep +0 -0
  304. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/.obsidian/app.json +1 -0
  305. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/_templates/tmpl.md +7 -0
  306. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/chen2024ai.md +13 -0
  307. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/invalid.md +1 -0
  308. package/vendor/ars/scripts/adapters/examples/obsidian/input_fixture/vault/wang2023formative.md +10 -0
  309. package/vendor/ars/scripts/adapters/examples/zotero/expected_passport.yaml +34 -0
  310. package/vendor/ars/scripts/adapters/examples/zotero/expected_rejection_log.yaml +34 -0
  311. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/.gitkeep +0 -0
  312. package/vendor/ars/scripts/adapters/examples/zotero/input_fixture/export.json +43 -0
  313. package/vendor/ars/scripts/adapters/folder_scan.py +214 -0
  314. package/vendor/ars/scripts/adapters/obsidian.py +336 -0
  315. package/vendor/ars/scripts/adapters/tests/.gitkeep +0 -0
  316. package/vendor/ars/scripts/adapters/tests/conftest.py +77 -0
  317. package/vendor/ars/scripts/adapters/tests/test_check_corpus_consumer_protocol.py +632 -0
  318. package/vendor/ars/scripts/adapters/tests/test_check_literature_corpus_schema.py +631 -0
  319. package/vendor/ars/scripts/adapters/tests/test_common.py +365 -0
  320. package/vendor/ars/scripts/adapters/tests/test_conftest.py +96 -0
  321. package/vendor/ars/scripts/adapters/tests/test_folder_scan.py +260 -0
  322. package/vendor/ars/scripts/adapters/tests/test_literature_corpus_entry_schema.py +745 -0
  323. package/vendor/ars/scripts/adapters/tests/test_obsidian.py +357 -0
  324. package/vendor/ars/scripts/adapters/tests/test_rejection_log_schema.py +271 -0
  325. package/vendor/ars/scripts/adapters/tests/test_sync_adapter_docs.py +88 -0
  326. package/vendor/ars/scripts/adapters/tests/test_zotero.py +454 -0
  327. package/vendor/ars/scripts/adapters/zotero.py +318 -0
  328. package/vendor/ars/scripts/adjudication_activity.py +1592 -0
  329. package/vendor/ars/scripts/announce-ars-loaded.sh +144 -0
  330. package/vendor/ars/scripts/ars_anchorize_draft.py +170 -0
  331. package/vendor/ars/scripts/ars_apply_revision_patch.py +912 -0
  332. package/vendor/ars/scripts/ars_cache_invalidate.py +40 -0
  333. package/vendor/ars/scripts/ars_mark_read.py +521 -0
  334. package/vendor/ars/scripts/ars_phase_scope_manifest.json +33 -0
  335. package/vendor/ars/scripts/ars_update_check.sh +215 -0
  336. package/vendor/ars/scripts/ars_write_scope_guard.py +506 -0
  337. package/vendor/ars/scripts/arxiv_client.py +222 -0
  338. package/vendor/ars/scripts/audit_snapshot.py +572 -0
  339. package/vendor/ars/scripts/bibliographic_integrity_signals.py +800 -0
  340. package/vendor/ars/scripts/bootstrap_timeline_yaml.py +146 -0
  341. package/vendor/ars/scripts/build_claim_standing_candidate_ledger.py +1238 -0
  342. package/vendor/ars/scripts/build_claim_standing_query_plan.py +643 -0
  343. package/vendor/ars/scripts/build_content_coverage_advisory.py +1205 -0
  344. package/vendor/ars/scripts/build_cross_document_consistency_advisory.py +2332 -0
  345. package/vendor/ars/scripts/build_review_pathway_rule_trace.py +830 -0
  346. package/vendor/ars/scripts/build_submission_packet_manifest.py +2310 -0
  347. package/vendor/ars/scripts/check_215_field_norm.py +173 -0
  348. package/vendor/ars/scripts/check_216_surface_form.py +250 -0
  349. package/vendor/ars/scripts/check_268_nested_commitment_ledger.py +180 -0
  350. package/vendor/ars/scripts/check_390_revision_patch_discipline.py +296 -0
  351. package/vendor/ars/scripts/check_392_citation_verification_intake.py +126 -0
  352. package/vendor/ars/scripts/check_394_submission_policy.py +178 -0
  353. package/vendor/ars/scripts/check_439_format_profile.py +307 -0
  354. package/vendor/ars/scripts/check_619_disclosure_closeout.py +237 -0
  355. package/vendor/ars/scripts/check_630_codex_subscription_transport.py +456 -0
  356. package/vendor/ars/scripts/check_669_review_pathway_rule_trace.py +662 -0
  357. package/vendor/ars/scripts/check_670_revision_roadmap_integration.py +518 -0
  358. package/vendor/ars/scripts/check_673_adjudication_activity.py +684 -0
  359. package/vendor/ars/scripts/check_684_review_criteria_binding.py +557 -0
  360. package/vendor/ars/scripts/check_agents_mirror_sync.py +115 -0
  361. package/vendor/ars/scripts/check_audit_artifact_consistency.py +2313 -0
  362. package/vendor/ars/scripts/check_benchmark_report.py +79 -0
  363. package/vendor/ars/scripts/check_bibliographic_integrity_signals.py +831 -0
  364. package/vendor/ars/scripts/check_calibration_tiers.py +235 -0
  365. package/vendor/ars/scripts/check_changelog_covers_merges.py +289 -0
  366. package/vendor/ars/scripts/check_ci_pytest_manifest.py +204 -0
  367. package/vendor/ars/scripts/check_claim_audit_consistency.py +1664 -0
  368. package/vendor/ars/scripts/check_claim_standing_candidate_ledger_integration.py +500 -0
  369. package/vendor/ars/scripts/check_claim_standing_freshness.py +253 -0
  370. package/vendor/ars/scripts/check_claim_standing_transmissions.py +449 -0
  371. package/vendor/ars/scripts/check_collaboration_depth_rubric.py +180 -0
  372. package/vendor/ars/scripts/check_command_frontmatter_name.py +116 -0
  373. package/vendor/ars/scripts/check_committee_correspondence.py +333 -0
  374. package/vendor/ars/scripts/check_compliance_report.py +108 -0
  375. package/vendor/ars/scripts/check_content_coverage_advisory_integration.py +796 -0
  376. package/vendor/ars/scripts/check_control_availability.py +172 -0
  377. package/vendor/ars/scripts/check_corpus_consumer_protocol.py +404 -0
  378. package/vendor/ars/scripts/check_cross_document_consistency_advisory_integration.py +1191 -0
  379. package/vendor/ars/scripts/check_cross_model_handoff_contract.py +234 -0
  380. package/vendor/ars/scripts/check_cross_model_verification_sync.py +261 -0
  381. package/vendor/ars/scripts/check_data_access_level.py +131 -0
  382. package/vendor/ars/scripts/check_data_flows.py +252 -0
  383. package/vendor/ars/scripts/check_decision_contract.py +464 -0
  384. package/vendor/ars/scripts/check_degradation_registry.py +326 -0
  385. package/vendor/ars/scripts/check_distribution_surface_claims.py +226 -0
  386. package/vendor/ars/scripts/check_domain_evidence_profile.py +538 -0
  387. package/vendor/ars/scripts/check_e4_promotion.py +195 -0
  388. package/vendor/ars/scripts/check_evals_gold_set.py +279 -0
  389. package/vendor/ars/scripts/check_evidence_row_integration.py +396 -0
  390. package/vendor/ars/scripts/check_experiment_provenance.py +117 -0
  391. package/vendor/ars/scripts/check_field_norm_severity.py +144 -0
  392. package/vendor/ars/scripts/check_firm_rules_sync.py +375 -0
  393. package/vendor/ars/scripts/check_heldout_measurement_report.py +1179 -0
  394. package/vendor/ars/scripts/check_human_subjects_output_contract.py +139 -0
  395. package/vendor/ars/scripts/check_human_subjects_reference_migration.py +844 -0
  396. package/vendor/ars/scripts/check_indirect_prompt_injection_no_call.py +328 -0
  397. package/vendor/ars/scripts/check_instruction_data_boundary.py +236 -0
  398. package/vendor/ars/scripts/check_judge_prompt_version.py +125 -0
  399. package/vendor/ars/scripts/check_literature_corpus_schema.py +402 -0
  400. package/vendor/ars/scripts/check_model_tiering.py +223 -0
  401. package/vendor/ars/scripts/check_panel_synthesis.py +1331 -0
  402. package/vendor/ars/scripts/check_passport_reset_contract.py +214 -0
  403. package/vendor/ars/scripts/check_pattern_eval_manifest.py +422 -0
  404. package/vendor/ars/scripts/check_persuasion_invariance_fixtures.py +637 -0
  405. package/vendor/ars/scripts/check_phase_conformance.py +2180 -0
  406. package/vendor/ars/scripts/check_pipeline_boundary_semantics.py +600 -0
  407. package/vendor/ars/scripts/check_pipeline_integrity.py +340 -0
  408. package/vendor/ars/scripts/check_policy_anchor_protocol.py +159 -0
  409. package/vendor/ars/scripts/check_policy_anchor_table.py +286 -0
  410. package/vendor/ars/scripts/check_preprint_venues_consistency.py +123 -0
  411. package/vendor/ars/scripts/check_prisma_trAIce_freshness.py +84 -0
  412. package/vendor/ars/scripts/check_promotion_bakeoff_preregistration.py +1303 -0
  413. package/vendor/ars/scripts/check_ranking_lift.py +323 -0
  414. package/vendor/ars/scripts/check_re_review_synthesis.py +2719 -0
  415. package/vendor/ars/scripts/check_receipt_enum_sync.py +203 -0
  416. package/vendor/ars/scripts/check_repro_lock.py +85 -0
  417. package/vendor/ars/scripts/check_review_pathway_output.py +276 -0
  418. package/vendor/ars/scripts/check_reviewer_data_fences.py +224 -0
  419. package/vendor/ars/scripts/check_reviewer_finding_contract.py +783 -0
  420. package/vendor/ars/scripts/check_reviewer_role_label.py +447 -0
  421. package/vendor/ars/scripts/check_reviewer_scoring_honesty.py +292 -0
  422. package/vendor/ars/scripts/check_reviewer_sprint_prompt_sync.py +409 -0
  423. package/vendor/ars/scripts/check_revision_claim_drift_suite_v2.py +1622 -0
  424. package/vendor/ars/scripts/check_revision_token_conservation.py +263 -0
  425. package/vendor/ars/scripts/check_risk_register.py +280 -0
  426. package/vendor/ars/scripts/check_role_scoped_contract.py +702 -0
  427. package/vendor/ars/scripts/check_rq_framing_patterns.py +184 -0
  428. package/vendor/ars/scripts/check_rubric_weight_consistency.py +32 -0
  429. package/vendor/ars/scripts/check_seeded_defect_fixtures.py +425 -0
  430. package/vendor/ars/scripts/check_setup_cross_model_parity.py +139 -0
  431. package/vendor/ars/scripts/check_spec_consistency.py +1249 -0
  432. package/vendor/ars/scripts/check_sprint_contract.py +371 -0
  433. package/vendor/ars/scripts/check_stage_capability_matrix.py +784 -0
  434. package/vendor/ars/scripts/check_submission_packet_manifest_integration.py +358 -0
  435. package/vendor/ars/scripts/check_surface_form_parity.py +445 -0
  436. package/vendor/ars/scripts/check_task_type.py +22 -0
  437. package/vendor/ars/scripts/check_tools_allowlist.py +538 -0
  438. package/vendor/ars/scripts/check_tortured_phrase_screening_integration.py +1974 -0
  439. package/vendor/ars/scripts/check_v3_10_134_write_scope.py +286 -0
  440. package/vendor/ars/scripts/check_v3_10_policy.py +656 -0
  441. package/vendor/ars/scripts/check_v3_6_6_ab_manifest.py +364 -0
  442. package/vendor/ars/scripts/check_v3_6_7_pattern_protection.py +1366 -0
  443. package/vendor/ars/scripts/check_v3_6_8_audit_scope_block.py +464 -0
  444. package/vendor/ars/scripts/check_v3_6_8_cite_provenance_pipeline.py +231 -0
  445. package/vendor/ars/scripts/check_v3_6_8_frontmatter_trust_schema.py +248 -0
  446. package/vendor/ars/scripts/check_v3_6_8_mark_read_commands.py +79 -0
  447. package/vendor/ars/scripts/check_v3_6_8_pattern_protection.py +941 -0
  448. package/vendor/ars/scripts/check_v3_7_3_three_layer_citation.py +318 -0
  449. package/vendor/ars/scripts/check_v3_8_annotation_literal_sync.py +228 -0
  450. package/vendor/ars/scripts/check_v3_9_0_triangulation.py +366 -0
  451. package/vendor/ars/scripts/check_v3_9_2_phase_boundary.py +270 -0
  452. package/vendor/ars/scripts/check_v3_9_4_temporal_verification.py +139 -0
  453. package/vendor/ars/scripts/check_venue_disclosure_policies.py +63 -0
  454. package/vendor/ars/scripts/check_version_consistency.py +826 -0
  455. package/vendor/ars/scripts/check_workflow_classification.py +223 -0
  456. package/vendor/ars/scripts/chinese_literature_client.py +1938 -0
  457. package/vendor/ars/scripts/citation_verification_summary.py +85 -0
  458. package/vendor/ars/scripts/claim_audit_calibration.py +517 -0
  459. package/vendor/ars/scripts/claim_audit_finalizer.py +456 -0
  460. package/vendor/ars/scripts/claim_audit_pipeline.py +1594 -0
  461. package/vendor/ars/scripts/claim_registry_coverage.py +493 -0
  462. package/vendor/ars/scripts/claim_standing_discovery.py +784 -0
  463. package/vendor/ars/scripts/claim_standing_stance_runner.py +758 -0
  464. package/vendor/ars/scripts/claim_standing_stance_scorer.py +239 -0
  465. package/vendor/ars/scripts/claim_strength_drift_disposition.py +666 -0
  466. package/vendor/ars/scripts/contamination_signals.py +689 -0
  467. package/vendor/ars/scripts/corpus_consumer_manifest.json +19 -0
  468. package/vendor/ars/scripts/cross_model_codex_transport.py +1374 -0
  469. package/vendor/ars/scripts/cross_model_codex_verify.sh +6 -0
  470. package/vendor/ars/scripts/cross_model_handoff.py +359 -0
  471. package/vendor/ars/scripts/cross_model_smoke_test.sh +183 -0
  472. package/vendor/ars/scripts/cross_model_smoke_test_codex.sh +35 -0
  473. package/vendor/ars/scripts/cross_model_verification/gemini_is_grounded.jq +45 -0
  474. package/vendor/ars/scripts/cross_model_verification/gemini_sources.jq +45 -0
  475. package/vendor/ars/scripts/cross_model_verification/normalize_compat_verdict.py +57 -0
  476. package/vendor/ars/scripts/cross_model_verification/openai_has_completed_web_search.jq +15 -0
  477. package/vendor/ars/scripts/cross_model_verification/openai_sources.jq +17 -0
  478. package/vendor/ars/scripts/cross_model_verification/openai_text.jq +11 -0
  479. package/vendor/ars/scripts/crossref_client.py +225 -0
  480. package/vendor/ars/scripts/dispatch_e4_panel.py +2731 -0
  481. package/vendor/ars/scripts/evidence_rows.py +2043 -0
  482. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3.json +32 -0
  483. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_input.json +27 -0
  484. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime.json +32 -0
  485. package/vendor/ars/scripts/fixtures/adjudication_activity/author_stage3_prime_input.json +27 -0
  486. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override.json +50 -0
  487. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_override_action.json +14 -0
  488. package/vendor/ars/scripts/fixtures/adjudication_activity/compliance_pass.json +44 -0
  489. package/vendor/ars/scripts/fixtures/adjudication_activity/explicit_user_request_log.json +26 -0
  490. package/vendor/ars/scripts/fixtures/adjudication_activity/mandatory_checkpoint_log.json +116 -0
  491. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/README.md +56 -0
  492. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +24 -0
  493. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  494. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  495. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a1_pass_with_p1/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  496. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/negative/a7_orphan_completion/2026-04-30T15-22-04Z-d8f3.jsonl +3 -0
  497. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +26 -0
  498. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  499. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  500. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/persisted_minor/2026-04-30T15-22-04Z-d8f3.verdict.yaml +19 -0
  501. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.audit_artifact_entry.json +24 -0
  502. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.jsonl +4 -0
  503. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.meta.json +43 -0
  504. package/vendor/ars/scripts/fixtures/audit_artifact_consistency/positive/proposal_pass/2026-04-30T15-22-04Z-d8f3.verdict.yaml +12 -0
  505. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction.json +46 -0
  506. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/retraction_check_attestation.json +44 -0
  507. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase.json +44 -0
  508. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_abstract_missing.json +107 -0
  509. package/vendor/ars/scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_detected.json +124 -0
  510. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/expected_outcomes.json +77 -0
  511. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/manifest.yaml +37 -0
  512. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/001-valid-doi-test.json +20 -0
  513. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/002-valid-arxiv-test.json +19 -0
  514. package/vendor/ars/scripts/fixtures/check_evals_gold_set/clean/tuples/003-fabricated-test.json +20 -0
  515. package/vendor/ars/scripts/fixtures/claim_audit_calibration/gold_set.json +344 -0
  516. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/query_plan.json +108 -0
  517. package/vendor/ars/scripts/fixtures/claim_standing_candidate_ledger/retrieval_input.json +179 -0
  518. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/concern_tracker.json +129 -0
  519. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/response_skeleton.md +19 -0
  520. package/vendor/ars/scripts/fixtures/committee_correspondence/16fd83f6aec7/source_letter.txt +9 -0
  521. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_draft.json +48 -0
  522. package/vendor/ars/scripts/fixtures/content_coverage_advisory/base_inventory.json +38 -0
  523. package/vendor/ars/scripts/fixtures/content_coverage_advisory/packet/consent.txt +1 -0
  524. package/vendor/ars/scripts/fixtures/content_coverage_advisory/session_sources.json +3 -0
  525. package/vendor/ars/scripts/fixtures/cross_document_consistency/README.md +6 -0
  526. package/vendor/ars/scripts/fixtures/cross_document_consistency/accepted_draft.md +35 -0
  527. package/vendor/ars/scripts/fixtures/cross_document_consistency/cases.json +75 -0
  528. package/vendor/ars/scripts/fixtures/cross_document_consistency/preregistration.md +5 -0
  529. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/forbidden_event.jsonl +4 -0
  530. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/grounded_verified.jsonl +3 -0
  531. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/malformed.jsonl +3 -0
  532. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/missing_search.jsonl +2 -0
  533. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/multiple_finals.jsonl +4 -0
  534. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/not_found.jsonl +3 -0
  535. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/unbound_source.jsonl +3 -0
  536. package/vendor/ars/scripts/fixtures/cross_model_codex_transport/wrong_search_shape.jsonl +3 -0
  537. package/vendor/ars/scripts/fixtures/evidence_rows/phase_e_inputs.json +114 -0
  538. package/vendor/ars/scripts/fixtures/evidence_rows/session_sources.json +5 -0
  539. package/vendor/ars/scripts/fixtures/human_subjects_authority/cross-border-us-tw-gdpr.json +71 -0
  540. package/vendor/ars/scripts/fixtures/human_subjects_authority/gdpr-member-state-unresolved.json +62 -0
  541. package/vendor/ars/scripts/fixtures/human_subjects_authority/missing-data-axis.json +45 -0
  542. package/vendor/ars/scripts/fixtures/human_subjects_authority/no-profile.json +33 -0
  543. package/vendor/ars/scripts/fixtures/human_subjects_authority/tw-gdpr-two-axis.json +74 -0
  544. package/vendor/ars/scripts/fixtures/human_subjects_authority/us-gdpr-two-axis.json +74 -0
  545. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/lint-near-misses.json +72 -0
  546. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/no-profile-request.json +18 -0
  547. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/tw-candidates-request.json +63 -0
  548. package/vendor/ars/scripts/fixtures/review_pathway_rule_trace/us-candidates-request.json +77 -0
  549. package/vendor/ars/scripts/fixtures/review_target_context/exact-declaration.json +24 -0
  550. package/vendor/ars/scripts/fixtures/review_target_context/field-general-declaration.json +24 -0
  551. package/vendor/ars/scripts/fixtures/review_target_context/msr-2027-technical-full-declaration.json +24 -0
  552. package/vendor/ars/scripts/fixtures/review_target_context/synthetic-registry.json +92 -0
  553. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/README.md +21 -0
  554. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_attested_only.json +55 -0
  555. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_machine_supported.json +49 -0
  556. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_not_isolated.json +56 -0
  557. package/vendor/ars/scripts/fixtures/revision_claim_drift_v2/subject_context_unknown.json +49 -0
  558. package/vendor/ars/scripts/fixtures/submission_package/clean/paper.md +16 -0
  559. package/vendor/ars/scripts/fixtures/submission_package/clean/references.bib +13 -0
  560. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/paper.md +11 -0
  561. package/vendor/ars/scripts/fixtures/submission_package/fallback_authoryear/references.bib +13 -0
  562. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/paper.tex +9 -0
  563. package/vendor/ars/scripts/fixtures/submission_package/fallback_latex/references.bib +13 -0
  564. package/vendor/ars/scripts/fixtures/submission_package/marker_no_join/paper.md +7 -0
  565. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/paper.md +8 -0
  566. package/vendor/ars/scripts/fixtures/submission_package/orphan_intext/references.bib +6 -0
  567. package/vendor/ars/scripts/fixtures/submission_package/passports/corpus_only.yaml +9 -0
  568. package/vendor/ars/scripts/fixtures/submission_package/passports/summary_join.yaml +16 -0
  569. package/vendor/ars/scripts/fixtures/submission_package/profiles/full.yaml +15 -0
  570. package/vendor/ars/scripts/fixtures/submission_package/profiles/tight.yaml +15 -0
  571. package/vendor/ars/scripts/fixtures/submission_package/summary_join/paper.md +7 -0
  572. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/paper.md +9 -0
  573. package/vendor/ars/scripts/fixtures/submission_package/uncited_reference/references.bib +13 -0
  574. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/paper.md +26 -0
  575. package/vendor/ars/scripts/fixtures/submission_package/venue_clean/references.bib +13 -0
  576. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/paper.md +20 -0
  577. package/vendor/ars/scripts/fixtures/submission_package/venue_violations/references.bib +13 -0
  578. package/vendor/ars/scripts/fixtures/submission_packet_manifest/base_inventory.json +101 -0
  579. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/consent-materials.txt +3 -0
  580. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/training-certificate.txt +2 -0
  581. package/vendor/ars/scripts/fixtures/submission_packet_manifest/packet/tw-consent-materials.txt +3 -0
  582. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/corpus_input.yaml +30 -0
  583. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.md +36 -0
  584. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/own_draft.tex +21 -0
  585. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/seed_expectations.json +218 -0
  586. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot.json +164 -0
  587. package/vendor/ars/scripts/fixtures/tortured_phrase_screening/snapshot_manifest.json +29 -0
  588. package/vendor/ars/scripts/fixtures/transport_bodies/README.md +55 -0
  589. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/empty_feed.xml +10 -0
  590. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/error_5xx.html +7 -0
  591. package/vendor/ars/scripts/fixtures/transport_bodies/arxiv/id_hit.xml +26 -0
  592. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/README.md +69 -0
  593. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/cnki_landing_page.html +13 -0
  594. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/error_5xx.html +2 -0
  595. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_ambiguous.json +16 -0
  596. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_hit.json +16 -0
  597. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coordinate_zero.json +14 -0
  598. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_hit.json +15 -0
  599. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esearch_coverage_zero.json +13 -0
  600. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_hit.json +43 -0
  601. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_issn_mismatch.json +31 -0
  602. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_no_doi.json +31 -0
  603. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_unknown_ra.json +34 -0
  604. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/esummary_year_mismatch.json +31 -0
  605. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_absent.json +4 -0
  606. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_exists.json +16 -0
  607. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/handle_internal_error.json +4 -0
  608. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_hit.json +25 -0
  609. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/istic_csl_other_title.json +18 -0
  610. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_cnki.json +6 -0
  611. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_crossref.json +6 -0
  612. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_istic.json +6 -0
  613. package/vendor/ars/scripts/fixtures/transport_bodies/chinese_literature/ra_unknown_prefix.json +6 -0
  614. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/doi_hit.json +24 -0
  615. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/error_5xx.html +7 -0
  616. package/vendor/ars/scripts/fixtures/transport_bodies/crossref/title_search_miss.json +15 -0
  617. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/doi_hit.json +29 -0
  618. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/error_5xx.json +4 -0
  619. package/vendor/ars/scripts/fixtures/transport_bodies/openalex/title_search_miss.json +11 -0
  620. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/doi_hit.json +14 -0
  621. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/error_5xx.json +3 -0
  622. package/vendor/ars/scripts/fixtures/transport_bodies/semantic_scholar/title_search_miss.json +5 -0
  623. package/vendor/ars/scripts/human_read_attestation_resolver.py +467 -0
  624. package/vendor/ars/scripts/ideation_diversity_assignment_gate.py +430 -0
  625. package/vendor/ars/scripts/inquiry_branch_ledger.py +2540 -0
  626. package/vendor/ars/scripts/legacy/ars_apply_revision_patch_v1_0.py +715 -0
  627. package/vendor/ars/scripts/legacy/check_re_review_synthesis_v1_0.py +2215 -0
  628. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_10.py +223 -0
  629. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_7_3.py +277 -0
  630. package/vendor/ars/scripts/migrate_literature_corpus_to_v3_9_0.py +304 -0
  631. package/vendor/ars/scripts/model_tiering_manifest.json +46 -0
  632. package/vendor/ars/scripts/openalex_client.py +232 -0
  633. package/vendor/ars/scripts/parse_audit_verdict.py +802 -0
  634. package/vendor/ars/scripts/pdf_content_classifier_worker.py +176 -0
  635. package/vendor/ars/scripts/pdf_read_preflight.py +1455 -0
  636. package/vendor/ars/scripts/policy_anchor_disclosure_referee.py +354 -0
  637. package/vendor/ars/scripts/recompute_receipts.py +1414 -0
  638. package/vendor/ars/scripts/render_claim_standing_view.py +374 -0
  639. package/vendor/ars/scripts/render_eval_comment.py +130 -0
  640. package/vendor/ars/scripts/render_harness_retirement_issue.py +167 -0
  641. package/vendor/ars/scripts/repro_lock_validation.py +90 -0
  642. package/vendor/ars/scripts/research_workflow_profile.py +1079 -0
  643. package/vendor/ars/scripts/resolve_human_subjects_authority.py +1158 -0
  644. package/vendor/ars/scripts/resolve_review_target_context.py +683 -0
  645. package/vendor/ars/scripts/resume_e4_record.py +509 -0
  646. package/vendor/ars/scripts/retraction_status.py +484 -0
  647. package/vendor/ars/scripts/review_criteria_binding.py +889 -0
  648. package/vendor/ars/scripts/review_panel_provenance.py +744 -0
  649. package/vendor/ars/scripts/revision_roadmap.py +1967 -0
  650. package/vendor/ars/scripts/run_ci_pytest_manifest.py +116 -0
  651. package/vendor/ars/scripts/run_codex_audit.sh +1191 -0
  652. package/vendor/ars/scripts/run_evals.py +513 -0
  653. package/vendor/ars/scripts/run_ideation_diversity_no_call.py +3505 -0
  654. package/vendor/ars/scripts/run_indirect_prompt_injection_no_call.py +3330 -0
  655. package/vendor/ars/scripts/run_indirect_prompt_injection_probe.py +399 -0
  656. package/vendor/ars/scripts/run_review_criteria_constructive_value.py +1895 -0
  657. package/vendor/ars/scripts/run_role_topology_utility_dry_run.py +606 -0
  658. package/vendor/ars/scripts/score_review_criteria_constructive_value.py +617 -0
  659. package/vendor/ars/scripts/semantic_scholar_client.py +291 -0
  660. package/vendor/ars/scripts/slr_lineage.py +59 -0
  661. package/vendor/ars/scripts/sync_adapter_docs.py +118 -0
  662. package/vendor/ars/scripts/temporal_integrity_audit.py +840 -0
  663. package/vendor/ars/scripts/test_431_exact_or_bust.py +253 -0
  664. package/vendor/ars/scripts/test__eval_threshold_gate.py +125 -0
  665. package/vendor/ars/scripts/test__markdown_lint_util.py +129 -0
  666. package/vendor/ars/scripts/test__next_verified_at_ms.py +256 -0
  667. package/vendor/ars/scripts/test_adjacent_framing_probe_lint.py +171 -0
  668. package/vendor/ars/scripts/test_adjudication_activity.py +1515 -0
  669. package/vendor/ars/scripts/test_ars_anchorize_draft.py +178 -0
  670. package/vendor/ars/scripts/test_ars_apply_revision_patch.py +1335 -0
  671. package/vendor/ars/scripts/test_ars_cache_invalidate.py +51 -0
  672. package/vendor/ars/scripts/test_ars_mark_read.py +910 -0
  673. package/vendor/ars/scripts/test_ars_update_check.py +816 -0
  674. package/vendor/ars/scripts/test_ars_write_scope_guard.py +790 -0
  675. package/vendor/ars/scripts/test_arxiv_client.py +374 -0
  676. package/vendor/ars/scripts/test_audit_schemas.py +560 -0
  677. package/vendor/ars/scripts/test_audit_snapshot_render_section_0.py +105 -0
  678. package/vendor/ars/scripts/test_block_parser.py +259 -0
  679. package/vendor/ars/scripts/test_bootstrap_timeline_yaml.py +148 -0
  680. package/vendor/ars/scripts/test_build_claim_standing_candidate_ledger.py +1203 -0
  681. package/vendor/ars/scripts/test_build_claim_standing_query_plan.py +791 -0
  682. package/vendor/ars/scripts/test_build_submission_packet_manifest.py +2644 -0
  683. package/vendor/ars/scripts/test_check_215_field_norm.py +238 -0
  684. package/vendor/ars/scripts/test_check_216_surface_form.py +341 -0
  685. package/vendor/ars/scripts/test_check_268_nested_commitment_ledger.py +194 -0
  686. package/vendor/ars/scripts/test_check_390_revision_patch_discipline.py +279 -0
  687. package/vendor/ars/scripts/test_check_392_citation_verification_intake.py +144 -0
  688. package/vendor/ars/scripts/test_check_394_submission_policy.py +200 -0
  689. package/vendor/ars/scripts/test_check_439_format_profile.py +252 -0
  690. package/vendor/ars/scripts/test_check_619_disclosure_closeout.py +158 -0
  691. package/vendor/ars/scripts/test_check_630_codex_subscription_transport.py +245 -0
  692. package/vendor/ars/scripts/test_check_669_review_pathway_rule_trace.py +304 -0
  693. package/vendor/ars/scripts/test_check_670_revision_roadmap_integration.py +260 -0
  694. package/vendor/ars/scripts/test_check_673_adjudication_activity.py +367 -0
  695. package/vendor/ars/scripts/test_check_684_review_criteria_binding.py +274 -0
  696. package/vendor/ars/scripts/test_check_agents_mirror_sync.py +137 -0
  697. package/vendor/ars/scripts/test_check_audit_artifact_consistency.py +2133 -0
  698. package/vendor/ars/scripts/test_check_benchmark_report.py +117 -0
  699. package/vendor/ars/scripts/test_check_bibliographic_integrity_signals.py +609 -0
  700. package/vendor/ars/scripts/test_check_calibration_tiers.py +376 -0
  701. package/vendor/ars/scripts/test_check_changelog_covers_merges.py +509 -0
  702. package/vendor/ars/scripts/test_check_ci_pytest_manifest.py +425 -0
  703. package/vendor/ars/scripts/test_check_claim_standing_candidate_ledger_integration.py +256 -0
  704. package/vendor/ars/scripts/test_check_claim_standing_freshness.py +277 -0
  705. package/vendor/ars/scripts/test_check_collaboration_depth_rubric.py +239 -0
  706. package/vendor/ars/scripts/test_check_command_frontmatter_name.py +178 -0
  707. package/vendor/ars/scripts/test_check_committee_correspondence.py +298 -0
  708. package/vendor/ars/scripts/test_check_compliance_report.py +381 -0
  709. package/vendor/ars/scripts/test_check_content_coverage_advisory_integration.py +308 -0
  710. package/vendor/ars/scripts/test_check_control_availability.py +361 -0
  711. package/vendor/ars/scripts/test_check_cross_document_consistency_advisory_integration.py +698 -0
  712. package/vendor/ars/scripts/test_check_cross_model_handoff_contract.py +301 -0
  713. package/vendor/ars/scripts/test_check_cross_model_verification_sync.py +203 -0
  714. package/vendor/ars/scripts/test_check_data_access_level.py +227 -0
  715. package/vendor/ars/scripts/test_check_data_flows.py +382 -0
  716. package/vendor/ars/scripts/test_check_decision_contract.py +387 -0
  717. package/vendor/ars/scripts/test_check_degradation_registry.py +270 -0
  718. package/vendor/ars/scripts/test_check_distribution_surface_claims.py +225 -0
  719. package/vendor/ars/scripts/test_check_domain_evidence_profile.py +439 -0
  720. package/vendor/ars/scripts/test_check_e4_promotion.py +163 -0
  721. package/vendor/ars/scripts/test_check_evals_gold_set.py +312 -0
  722. package/vendor/ars/scripts/test_check_evidence_row_integration.py +187 -0
  723. package/vendor/ars/scripts/test_check_field_norm_severity.py +173 -0
  724. package/vendor/ars/scripts/test_check_firm_rules_sync.py +342 -0
  725. package/vendor/ars/scripts/test_check_heldout_measurement_report.py +1508 -0
  726. package/vendor/ars/scripts/test_check_human_subjects_output_contract.py +129 -0
  727. package/vendor/ars/scripts/test_check_human_subjects_reference_migration.py +756 -0
  728. package/vendor/ars/scripts/test_check_instruction_data_boundary.py +204 -0
  729. package/vendor/ars/scripts/test_check_judge_prompt_version.py +90 -0
  730. package/vendor/ars/scripts/test_check_model_tiering.py +236 -0
  731. package/vendor/ars/scripts/test_check_panel_synthesis.py +1658 -0
  732. package/vendor/ars/scripts/test_check_passport_reset_contract.py +249 -0
  733. package/vendor/ars/scripts/test_check_pattern_eval_manifest.py +381 -0
  734. package/vendor/ars/scripts/test_check_persuasion_invariance_fixtures.py +591 -0
  735. package/vendor/ars/scripts/test_check_phase_conformance.py +4366 -0
  736. package/vendor/ars/scripts/test_check_pipeline_boundary_semantics.py +931 -0
  737. package/vendor/ars/scripts/test_check_pipeline_integrity.py +243 -0
  738. package/vendor/ars/scripts/test_check_policy_anchor_protocol.py +236 -0
  739. package/vendor/ars/scripts/test_check_policy_anchor_table.py +295 -0
  740. package/vendor/ars/scripts/test_check_prisma_trAIce_freshness.py +68 -0
  741. package/vendor/ars/scripts/test_check_promotion_bakeoff_preregistration.py +799 -0
  742. package/vendor/ars/scripts/test_check_ranking_lift.py +377 -0
  743. package/vendor/ars/scripts/test_check_re_review_synthesis.py +3398 -0
  744. package/vendor/ars/scripts/test_check_receipt_enum_sync.py +176 -0
  745. package/vendor/ars/scripts/test_check_repro_lock.py +107 -0
  746. package/vendor/ars/scripts/test_check_reviewer_data_fences.py +334 -0
  747. package/vendor/ars/scripts/test_check_reviewer_finding_contract.py +1107 -0
  748. package/vendor/ars/scripts/test_check_reviewer_role_label.py +491 -0
  749. package/vendor/ars/scripts/test_check_reviewer_scoring_honesty.py +222 -0
  750. package/vendor/ars/scripts/test_check_reviewer_sprint_prompt_sync.py +373 -0
  751. package/vendor/ars/scripts/test_check_revision_claim_drift_suite_v2.py +1925 -0
  752. package/vendor/ars/scripts/test_check_revision_token_conservation.py +398 -0
  753. package/vendor/ars/scripts/test_check_risk_register.py +336 -0
  754. package/vendor/ars/scripts/test_check_role_scoped_contract.py +1104 -0
  755. package/vendor/ars/scripts/test_check_rq_framing_patterns.py +110 -0
  756. package/vendor/ars/scripts/test_check_rubric_weight_consistency.py +32 -0
  757. package/vendor/ars/scripts/test_check_seeded_defect_fixtures.py +392 -0
  758. package/vendor/ars/scripts/test_check_setup_cross_model_parity.py +121 -0
  759. package/vendor/ars/scripts/test_check_spec_consistency.py +1081 -0
  760. package/vendor/ars/scripts/test_check_sprint_contract.py +458 -0
  761. package/vendor/ars/scripts/test_check_stage_capability_matrix.py +698 -0
  762. package/vendor/ars/scripts/test_check_submission_packet_manifest_integration.py +177 -0
  763. package/vendor/ars/scripts/test_check_surface_form_parity.py +417 -0
  764. package/vendor/ars/scripts/test_check_task_type.py +116 -0
  765. package/vendor/ars/scripts/test_check_tools_allowlist.py +835 -0
  766. package/vendor/ars/scripts/test_check_tortured_phrase_screening_integration.py +1306 -0
  767. package/vendor/ars/scripts/test_check_v3_10_134_write_scope.py +251 -0
  768. package/vendor/ars/scripts/test_check_v3_10_policy.py +547 -0
  769. package/vendor/ars/scripts/test_check_v3_6_7_pattern_protection.py +960 -0
  770. package/vendor/ars/scripts/test_check_v3_6_8_audit_scope_block.py +1000 -0
  771. package/vendor/ars/scripts/test_check_v3_6_8_cite_provenance_pipeline.py +454 -0
  772. package/vendor/ars/scripts/test_check_v3_6_8_frontmatter_trust_schema.py +581 -0
  773. package/vendor/ars/scripts/test_check_v3_6_8_mark_read_commands.py +120 -0
  774. package/vendor/ars/scripts/test_check_v3_6_8_pattern_protection.py +1138 -0
  775. package/vendor/ars/scripts/test_check_v3_7_3_three_layer_citation.py +566 -0
  776. package/vendor/ars/scripts/test_check_v3_8_annotation_literal_sync.py +262 -0
  777. package/vendor/ars/scripts/test_check_v3_9_0_triangulation.py +321 -0
  778. package/vendor/ars/scripts/test_check_v3_9_2_phase_boundary.py +190 -0
  779. package/vendor/ars/scripts/test_check_v3_9_4_temporal_verification.py +471 -0
  780. package/vendor/ars/scripts/test_check_version_consistency.py +1462 -0
  781. package/vendor/ars/scripts/test_check_workflow_classification.py +225 -0
  782. package/vendor/ars/scripts/test_chinese_literature_client.py +1889 -0
  783. package/vendor/ars/scripts/test_citation_existence_policy.py +480 -0
  784. package/vendor/ars/scripts/test_citation_verification_summary.py +342 -0
  785. package/vendor/ars/scripts/test_claim_audit_calibration.py +882 -0
  786. package/vendor/ars/scripts/test_claim_audit_finalizer.py +979 -0
  787. package/vendor/ars/scripts/test_claim_audit_pipeline.py +2398 -0
  788. package/vendor/ars/scripts/test_claim_audit_schema.py +1778 -0
  789. package/vendor/ars/scripts/test_claim_intent_manifest.py +666 -0
  790. package/vendor/ars/scripts/test_claim_registry_coverage.py +246 -0
  791. package/vendor/ars/scripts/test_claim_standing_discovery.py +579 -0
  792. package/vendor/ars/scripts/test_claim_standing_pipeline_wiring.py +290 -0
  793. package/vendor/ars/scripts/test_claim_standing_stance_assets.py +399 -0
  794. package/vendor/ars/scripts/test_claim_standing_stance_contracts.py +383 -0
  795. package/vendor/ars/scripts/test_claim_standing_stance_runner.py +349 -0
  796. package/vendor/ars/scripts/test_claim_standing_transmissions.py +605 -0
  797. package/vendor/ars/scripts/test_claim_strength_drift_disposition.py +517 -0
  798. package/vendor/ars/scripts/test_claim_verification_coverage_contract.py +104 -0
  799. package/vendor/ars/scripts/test_contamination_signals.py +1086 -0
  800. package/vendor/ars/scripts/test_content_coverage_advisory.py +1767 -0
  801. package/vendor/ars/scripts/test_cross_document_consistency_advisory.py +1270 -0
  802. package/vendor/ars/scripts/test_cross_model_codex_transport.py +1152 -0
  803. package/vendor/ars/scripts/test_cross_model_handoff.py +571 -0
  804. package/vendor/ars/scripts/test_cross_model_verification_guards.py +792 -0
  805. package/vendor/ars/scripts/test_crossref_client.py +393 -0
  806. package/vendor/ars/scripts/test_dispatch_e4_panel.py +4235 -0
  807. package/vendor/ars/scripts/test_e2e_claim_audit.py +540 -0
  808. package/vendor/ars/scripts/test_eval_harness_workflow.py +140 -0
  809. package/vendor/ars/scripts/test_evals_citation_extraction.py +150 -0
  810. package/vendor/ars/scripts/test_evals_lift_report_schema.py +108 -0
  811. package/vendor/ars/scripts/test_evidence_rows.py +2593 -0
  812. package/vendor/ars/scripts/test_experiment_provenance.py +915 -0
  813. package/vendor/ars/scripts/test_human_read_attestation_resolver.py +477 -0
  814. package/vendor/ars/scripts/test_ideation_diversity_assignment_gate.py +615 -0
  815. package/vendor/ars/scripts/test_indirect_prompt_injection_behavior_probe.py +250 -0
  816. package/vendor/ars/scripts/test_inquiry_branch_ledger.py +2296 -0
  817. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_10.py +248 -0
  818. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_7_3.py +545 -0
  819. package/vendor/ars/scripts/test_migrate_literature_corpus_to_v3_9_0.py +497 -0
  820. package/vendor/ars/scripts/test_normalize_compat_verdict.py +149 -0
  821. package/vendor/ars/scripts/test_openalex_client.py +490 -0
  822. package/vendor/ars/scripts/test_passport_yaml.py +104 -0
  823. package/vendor/ars/scripts/test_pattern_eval_runtime.py +1295 -0
  824. package/vendor/ars/scripts/test_pdf_read_preflight.py +1943 -0
  825. package/vendor/ars/scripts/test_policy_anchor_disclosure.py +666 -0
  826. package/vendor/ars/scripts/test_reading_probe_lint.py +218 -0
  827. package/vendor/ars/scripts/test_recompute_receipts.py +778 -0
  828. package/vendor/ars/scripts/test_render_claim_standing_view.py +192 -0
  829. package/vendor/ars/scripts/test_render_eval_comment.py +162 -0
  830. package/vendor/ars/scripts/test_render_harness_retirement_issue.py +110 -0
  831. package/vendor/ars/scripts/test_repro_lock_validation_drift.py +100 -0
  832. package/vendor/ars/scripts/test_research_workflow_profile.py +734 -0
  833. package/vendor/ars/scripts/test_resolve_human_subjects_authority.py +1219 -0
  834. package/vendor/ars/scripts/test_resolve_review_target_context.py +703 -0
  835. package/vendor/ars/scripts/test_resume_e4_record.py +315 -0
  836. package/vendor/ars/scripts/test_retraction_status.py +456 -0
  837. package/vendor/ars/scripts/test_review_criteria_binding.py +629 -0
  838. package/vendor/ars/scripts/test_review_panel_provenance.py +565 -0
  839. package/vendor/ars/scripts/test_review_pathway_rule_trace.py +821 -0
  840. package/vendor/ars/scripts/test_revision_roadmap.py +1255 -0
  841. package/vendor/ars/scripts/test_run_ci_pytest_manifest.py +186 -0
  842. package/vendor/ars/scripts/test_run_codex_audit_e2e.py +369 -0
  843. package/vendor/ars/scripts/test_run_evals.py +430 -0
  844. package/vendor/ars/scripts/test_run_guard_launcher.py +500 -0
  845. package/vendor/ars/scripts/test_run_ideation_diversity_no_call.py +1833 -0
  846. package/vendor/ars/scripts/test_run_indirect_prompt_injection_no_call.py +1889 -0
  847. package/vendor/ars/scripts/test_run_review_criteria_constructive_value.py +586 -0
  848. package/vendor/ars/scripts/test_run_role_topology_utility_dry_run.py +428 -0
  849. package/vendor/ars/scripts/test_score_review_criteria_constructive_value.py +340 -0
  850. package/vendor/ars/scripts/test_semantic_scholar_client.py +554 -0
  851. package/vendor/ars/scripts/test_slr_lineage_emission.py +230 -0
  852. package/vendor/ars/scripts/test_socratic_rq_non_generation_contract.py +173 -0
  853. package/vendor/ars/scripts/test_temporal_integrity_audit.py +438 -0
  854. package/vendor/ars/scripts/test_text_similarity.py +95 -0
  855. package/vendor/ars/scripts/test_title_fuzzy_false_positive.py +111 -0
  856. package/vendor/ars/scripts/test_tortured_phrase_screening.py +2959 -0
  857. package/vendor/ars/scripts/test_transport_fixture_citation_gate.py +338 -0
  858. package/vendor/ars/scripts/test_uncited_assertion.py +558 -0
  859. package/vendor/ars/scripts/test_v3_6_7_phase_6_6.py +1279 -0
  860. package/vendor/ars/scripts/test_validate_compliance_fixtures.py +36 -0
  861. package/vendor/ars/scripts/test_validate_ideation_diversity_assets.py +230 -0
  862. package/vendor/ars/scripts/test_venue_disclosure_contract.py +755 -0
  863. package/vendor/ars/scripts/test_verification_cache.py +280 -0
  864. package/vendor/ars/scripts/test_verification_gate.py +461 -0
  865. package/vendor/ars/scripts/test_verify_passport_cli.py +123 -0
  866. package/vendor/ars/scripts/test_verify_submission_package.py +1407 -0
  867. package/vendor/ars/scripts/test_version_records_schema.py +211 -0
  868. package/vendor/ars/scripts/tortured_phrase_screening.py +3502 -0
  869. package/vendor/ars/scripts/uncited_assertion_detector.py +254 -0
  870. package/vendor/ars/scripts/v3_6_7_inversion_manifest.json +9 -0
  871. package/vendor/ars/scripts/v3_6_8_inversion_manifest.json +10 -0
  872. package/vendor/ars/scripts/validate_claim_standing_stance_assets.py +249 -0
  873. package/vendor/ars/scripts/validate_compliance_fixtures.py +56 -0
  874. package/vendor/ars/scripts/validate_ideation_diversity_assets.py +303 -0
  875. package/vendor/ars/scripts/venue_disclosure_contract_harness.py +837 -0
  876. package/vendor/ars/scripts/verification_cache.py +276 -0
  877. package/vendor/ars/scripts/verification_gate/__init__.py +345 -0
  878. package/vendor/ars/scripts/verify_passport.py +133 -0
  879. package/vendor/ars/scripts/verify_submission_package.py +1657 -0
  880. package/vendor/ars/shared/agents/compliance_agent.md +136 -0
  881. package/vendor/ars/shared/artifact_reproducibility_pattern.md +173 -0
  882. package/vendor/ars/shared/benchmark_report.schema.json +81 -0
  883. package/vendor/ars/shared/benchmark_report_pattern.md +180 -0
  884. package/vendor/ars/shared/bibliographic_integrity_signals.md +142 -0
  885. package/vendor/ars/shared/collaboration_depth_rubric.md +154 -0
  886. package/vendor/ars/shared/compliance_checkpoint_protocol.md +162 -0
  887. package/vendor/ars/shared/compliance_report.schema.json +187 -0
  888. package/vendor/ars/shared/contracts/README.md +938 -0
  889. package/vendor/ars/shared/contracts/activity/adjudication_activity_input.schema.json +555 -0
  890. package/vendor/ars/shared/contracts/activity/adjudication_activity_store.schema.json +560 -0
  891. package/vendor/ars/shared/contracts/audit/audit_jsonl.schema.json +128 -0
  892. package/vendor/ars/shared/contracts/audit/audit_sidecar.schema.json +169 -0
  893. package/vendor/ars/shared/contracts/audit/audit_verdict.schema.json +133 -0
  894. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory.schema.json +480 -0
  895. package/vendor/ars/shared/contracts/audit/cross_document_consistency_advisory_draft.schema.json +564 -0
  896. package/vendor/ars/shared/contracts/audit/cross_document_source_manifest.schema.json +202 -0
  897. package/vendor/ars/shared/contracts/audit/tortured_phrase_advisory.schema.json +1362 -0
  898. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot.schema.json +208 -0
  899. package/vendor/ars/shared/contracts/audit/tortured_phrase_snapshot_manifest.schema.json +335 -0
  900. package/vendor/ars/shared/contracts/capability/stage_capability_matrix.json +434 -0
  901. package/vendor/ars/shared/contracts/claim_standing/candidate_ledger.schema.json +705 -0
  902. package/vendor/ars/shared/contracts/claim_standing/query_plan.schema.json +389 -0
  903. package/vendor/ars/shared/contracts/claim_standing/query_plan_v1_1.schema.json +782 -0
  904. package/vendor/ars/shared/contracts/claim_standing/retrieval_input.schema.json +440 -0
  905. package/vendor/ars/shared/contracts/claim_standing/stance_record.schema.json +460 -0
  906. package/vendor/ars/shared/contracts/claim_standing/transmission_ledger.schema.json +282 -0
  907. package/vendor/ars/shared/contracts/cross_model/codex_citation_receipt.schema.json +157 -0
  908. package/vendor/ars/shared/contracts/cross_model/codex_citation_request.schema.json +23 -0
  909. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_commitment.schema.json +55 -0
  910. package/vendor/ars/shared/contracts/cross_model/promotion_bakeoff_sealed_reveal.schema.json +50 -0
  911. package/vendor/ars/shared/contracts/degradation_registry.json +428 -0
  912. package/vendor/ars/shared/contracts/evaluator/full.json +126 -0
  913. package/vendor/ars/shared/contracts/evidence/claim_registry.schema.json +50 -0
  914. package/vendor/ars/shared/contracts/evidence/claim_registry_coverage_report.schema.json +79 -0
  915. package/vendor/ars/shared/contracts/evidence/evidence_row.schema.json +504 -0
  916. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_1.schema.json +364 -0
  917. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_2.schema.json +714 -0
  918. package/vendor/ars/shared/contracts/evidence/evidence_row_v1_3.schema.json +524 -0
  919. package/vendor/ars/shared/contracts/human_subjects/authority_profile_registry.schema.json +497 -0
  920. package/vendor/ars/shared/contracts/human_subjects/committee_correspondence.schema.json +253 -0
  921. package/vendor/ars/shared/contracts/human_subjects/content_coverage_advisory.schema.json +620 -0
  922. package/vendor/ars/shared/contracts/human_subjects/irb_context_record.schema.json +329 -0
  923. package/vendor/ars/shared/contracts/human_subjects/resolved_authority_context.schema.json +347 -0
  924. package/vendor/ars/shared/contracts/human_subjects/review_pathway_rule_trace.schema.json +265 -0
  925. package/vendor/ars/shared/contracts/human_subjects/review_pathway_trace_request.schema.json +127 -0
  926. package/vendor/ars/shared/contracts/human_subjects/submission_packet_inventory.schema.json +240 -0
  927. package/vendor/ars/shared/contracts/human_subjects/submission_packet_manifest.schema.json +999 -0
  928. package/vendor/ars/shared/contracts/passport/audit_artifact_entry.schema.json +266 -0
  929. package/vendor/ars/shared/contracts/passport/bibliographic_integrity_signal.schema.json +1676 -0
  930. package/vendor/ars/shared/contracts/passport/citation_provenance.schema.json +107 -0
  931. package/vendor/ars/shared/contracts/passport/citation_verification_summary.schema.json +164 -0
  932. package/vendor/ars/shared/contracts/passport/claim_audit_result.schema.json +124 -0
  933. package/vendor/ars/shared/contracts/passport/claim_drift.schema.json +58 -0
  934. package/vendor/ars/shared/contracts/passport/claim_intent_manifest.schema.json +107 -0
  935. package/vendor/ars/shared/contracts/passport/constraint_violation.schema.json +65 -0
  936. package/vendor/ars/shared/contracts/passport/experiment_alignment_result.schema.json +69 -0
  937. package/vendor/ars/shared/contracts/passport/experiment_provenance_entry.schema.json +169 -0
  938. package/vendor/ars/shared/contracts/passport/human_read_log.schema.json +86 -0
  939. package/vendor/ars/shared/contracts/passport/inquiry_ledger_ref.schema.json +22 -0
  940. package/vendor/ars/shared/contracts/passport/literature_corpus_entry.schema.json +650 -0
  941. package/vendor/ars/shared/contracts/passport/preregistration_artifact.schema.json +132 -0
  942. package/vendor/ars/shared/contracts/passport/rejection_log.schema.json +89 -0
  943. package/vendor/ars/shared/contracts/passport/reset_ledger_entry.schema.json +158 -0
  944. package/vendor/ars/shared/contracts/passport/temporal_audit_results.schema.json +208 -0
  945. package/vendor/ars/shared/contracts/passport/terminal_policies.schema.json +50 -0
  946. package/vendor/ars/shared/contracts/passport/timeline.schema.json +102 -0
  947. package/vendor/ars/shared/contracts/passport/uncited_assertion.schema.json +56 -0
  948. package/vendor/ars/shared/contracts/passport/uncited_audit_failure.schema.json +72 -0
  949. package/vendor/ars/shared/contracts/passport/user_attested_read_resolution.schema.json +87 -0
  950. package/vendor/ars/shared/contracts/passport/version_records.schema.json +138 -0
  951. package/vendor/ars/shared/contracts/patch/block_manifest.schema.json +45 -0
  952. package/vendor/ars/shared/contracts/patch/legacy/v1_0/revision_patch.schema.json +110 -0
  953. package/vendor/ars/shared/contracts/patch/revision_patch.schema.json +250 -0
  954. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_diagnostic.schema.json +39 -0
  955. package/vendor/ars/shared/contracts/pdf/pdf_content_classifier_worker.schema.json +88 -0
  956. package/vendor/ars/shared/contracts/pdf/pdf_read_preflight.schema.json +227 -0
  957. package/vendor/ars/shared/contracts/re_review/input_manifest.schema.json +161 -0
  958. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/input_manifest.schema.json +134 -0
  959. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/precommitment.schema.json +193 -0
  960. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/traceability.schema.json +841 -0
  961. package/vendor/ars/shared/contracts/re_review/legacy/v1_0/verdict_record.schema.json +244 -0
  962. package/vendor/ars/shared/contracts/re_review/precommitment.schema.json +193 -0
  963. package/vendor/ars/shared/contracts/re_review/traceability.schema.json +916 -0
  964. package/vendor/ars/shared/contracts/re_review/verdict_record.schema.json +245 -0
  965. package/vendor/ars/shared/contracts/research_workflow/inquiry_branch_ledger.schema.json +449 -0
  966. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile.schema.json +222 -0
  967. package/vendor/ars/shared/contracts/research_workflow/research_workflow_profile_selection_receipt.schema.json +111 -0
  968. package/vendor/ars/shared/contracts/review_target/constructive_review_findings.schema.json +172 -0
  969. package/vendor/ars/shared/contracts/review_target/criteria_registry.schema.json +97 -0
  970. package/vendor/ars/shared/contracts/review_target/review_criteria_binding_manifest.schema.json +235 -0
  971. package/vendor/ars/shared/contracts/review_target/review_criteria_source_receipt.schema.json +158 -0
  972. package/vendor/ars/shared/contracts/review_target/review_target_context.schema.json +106 -0
  973. package/vendor/ars/shared/contracts/review_target/review_target_declaration.schema.json +118 -0
  974. package/vendor/ars/shared/contracts/reviewer/full.json +114 -0
  975. package/vendor/ars/shared/contracts/reviewer/methodology_focus.json +75 -0
  976. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance.schema.json +263 -0
  977. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_carrier.schema.json +122 -0
  978. package/vendor/ars/shared/contracts/reviewer/review_panel_provenance_input.schema.json +120 -0
  979. package/vendor/ars/shared/contracts/revision/author_adjudication.schema.json +251 -0
  980. package/vendor/ars/shared/contracts/revision/author_adjudication_input.schema.json +25 -0
  981. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition.schema.json +97 -0
  982. package/vendor/ars/shared/contracts/revision/claim_strength_drift_disposition_input.schema.json +80 -0
  983. package/vendor/ars/shared/contracts/revision/claim_strength_drift_findings.schema.json +139 -0
  984. package/vendor/ars/shared/contracts/revision/claim_surface_manifest.schema.json +99 -0
  985. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization.schema.json +140 -0
  986. package/vendor/ars/shared/contracts/revision/integrity_correction_authorization_input.schema.json +28 -0
  987. package/vendor/ars/shared/contracts/revision/integrity_correction_list.schema.json +48 -0
  988. package/vendor/ars/shared/contracts/revision/integrity_pass_receipt.schema.json +16 -0
  989. package/vendor/ars/shared/contracts/revision/revision_evidence_bundle.schema.json +134 -0
  990. package/vendor/ars/shared/contracts/revision/revision_roadmap.schema.json +334 -0
  991. package/vendor/ars/shared/contracts/submission/format_profile.example.yaml +33 -0
  992. package/vendor/ars/shared/contracts/submission/format_profile.schema.json +102 -0
  993. package/vendor/ars/shared/contracts/submission/submission_verification_report.schema.json +233 -0
  994. package/vendor/ars/shared/contracts/submission/venue_profile.schema.json +114 -0
  995. package/vendor/ars/shared/contracts/writer/full.json +87 -0
  996. package/vendor/ars/shared/cross_model_verification.md +714 -0
  997. package/vendor/ars/shared/evals_lift_report.schema.json +141 -0
  998. package/vendor/ars/shared/ground_truth_isolation_pattern.md +275 -0
  999. package/vendor/ars/shared/handoff_schemas.md +1209 -0
  1000. package/vendor/ars/shared/human_subjects_authority_registry.json +1278 -0
  1001. package/vendor/ars/shared/mode_spectrum.md +57 -0
  1002. package/vendor/ars/shared/model_tiering.md +83 -0
  1003. package/vendor/ars/shared/policy_data/nature_policy.md +56 -0
  1004. package/vendor/ars/shared/prisma_trAIce_protocol.md +157 -0
  1005. package/vendor/ars/shared/raise_framework.md +129 -0
  1006. package/vendor/ars/shared/references/authority_content_coverage_advisory_protocol.md +275 -0
  1007. package/vendor/ars/shared/references/claim_standing_candidate_ledger_protocol.md +66 -0
  1008. package/vendor/ars/shared/references/claim_strength_ladder.md +93 -0
  1009. package/vendor/ars/shared/references/cross_document_consistency_advisory_protocol.md +263 -0
  1010. package/vendor/ars/shared/references/evidence_row_protocol.md +260 -0
  1011. package/vendor/ars/shared/references/firm_rules.md +90 -0
  1012. package/vendor/ars/shared/references/human_subjects_authority_protocol.md +274 -0
  1013. package/vendor/ars/shared/references/intent_clarification_protocol.md +168 -0
  1014. package/vendor/ars/shared/references/irb_terminology_glossary.md +229 -0
  1015. package/vendor/ars/shared/references/protected_hedging_phrases.md +118 -0
  1016. package/vendor/ars/shared/references/psychometric_terminology_glossary.md +109 -0
  1017. package/vendor/ars/shared/references/review_criteria_consumer_protocol.md +238 -0
  1018. package/vendor/ars/shared/references/review_pathway_rule_trace_protocol.md +166 -0
  1019. package/vendor/ars/shared/references/submission_packet_manifest_protocol.md +292 -0
  1020. package/vendor/ars/shared/references/word_count_conventions.md +124 -0
  1021. package/vendor/ars/shared/research_workflow_profiles/field_general.json +1 -0
  1022. package/vendor/ars/shared/review_criteria_registry.json +207 -0
  1023. package/vendor/ars/shared/review_criteria_sources/msr-2027-technical-papers.2026-08-24.json +46 -0
  1024. package/vendor/ars/shared/review_criteria_sources/sigsoft-empirical-standards.2026-08-24.json +31 -0
  1025. package/vendor/ars/shared/sprint_contract.schema.json +482 -0
  1026. package/vendor/ars/shared/style_calibration_protocol.md +151 -0
  1027. package/vendor/ars/shared/templates/codex_audit_multifile_template.md +263 -0
  1028. package/vendor/ars/tools/release-discipline/.toolkit-version +1 -0
  1029. package/vendor/ars/tools/release-discipline/README.md +4 -0
  1030. package/vendor/ars/tools/release-discipline/scripts/_release_doc_alignment_schema.py +1011 -0
  1031. package/vendor/ars/tools/release-discipline/scripts/check_command_invariants.py +497 -0
  1032. package/vendor/ars/tools/release-discipline/scripts/check_release_doc_alignment.py +263 -0
  1033. package/vendor/ars/tools/release-discipline/scripts/sync-toolkit.sh +147 -0
  1034. package/vendor/windows/NOTICE.md +12 -0
  1035. package/vendor/windows/arm64/fd.exe +0 -0
  1036. package/vendor/windows/arm64/licenses/fd/LICENSE-APACHE +201 -0
  1037. package/vendor/windows/arm64/licenses/fd/LICENSE-MIT +21 -0
  1038. package/vendor/windows/arm64/licenses/ripgrep/COPYING +3 -0
  1039. package/vendor/windows/arm64/licenses/ripgrep/LICENSE-MIT +21 -0
  1040. package/vendor/windows/arm64/licenses/ripgrep/UNLICENSE +24 -0
  1041. package/vendor/windows/arm64/rg.exe +0 -0
  1042. package/vendor/windows/x64/fd.exe +0 -0
  1043. package/vendor/windows/x64/licenses/fd/LICENSE-APACHE +201 -0
  1044. package/vendor/windows/x64/licenses/fd/LICENSE-MIT +21 -0
  1045. package/vendor/windows/x64/licenses/ripgrep/COPYING +3 -0
  1046. package/vendor/windows/x64/licenses/ripgrep/LICENSE-MIT +21 -0
  1047. package/vendor/windows/x64/licenses/ripgrep/UNLICENSE +24 -0
  1048. package/vendor/windows/x64/rg.exe +0 -0
@@ -0,0 +1,1974 @@
1
+ #!/usr/bin/env python3
2
+ """Check the hermetic #660 tortured-phrase screening integration boundary.
3
+
4
+ The matcher tests own behavioral replay. This static guard prevents the four
5
+ contract layers from drifting independently: closed schemas, runtime
6
+ epistemics and execution boundaries, byte-bound synthetic fixtures, and
7
+ documentation/CI wiring. It deliberately does not fetch a phrase list, run a
8
+ model or judge, or manufacture a held-out score.
9
+
10
+ Exit 0 on success, 1 on integration errors, and 2 on invocation errors.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import ast
16
+ import hashlib
17
+ import json
18
+ import os
19
+ import sys
20
+ import tomllib
21
+ from pathlib import Path
22
+ from typing import Any
23
+
24
+ from jsonschema import Draft202012Validator
25
+
26
+
27
+ REPO_ROOT = Path(__file__).resolve().parent.parent
28
+
29
+ SNAPSHOT_SCHEMA = Path("shared/contracts/audit/tortured_phrase_snapshot.schema.json")
30
+ MANIFEST_SCHEMA = Path(
31
+ "shared/contracts/audit/tortured_phrase_snapshot_manifest.schema.json"
32
+ )
33
+ ADVISORY_SCHEMA = Path("shared/contracts/audit/tortured_phrase_advisory.schema.json")
34
+ SIGNAL_SCHEMA = Path(
35
+ "shared/contracts/passport/bibliographic_integrity_signal.schema.json"
36
+ )
37
+ RUNTIME = Path("scripts/tortured_phrase_screening.py")
38
+ RUNTIME_TEST = Path("scripts/test_tortured_phrase_screening.py")
39
+ FIXTURE_ROOT = Path("scripts/fixtures/tortured_phrase_screening")
40
+ SNAPSHOT_FIXTURE = FIXTURE_ROOT / "snapshot.json"
41
+ MANIFEST_FIXTURE = FIXTURE_ROOT / "snapshot_manifest.json"
42
+ EXPECTATIONS_FIXTURE = FIXTURE_ROOT / "seed_expectations.json"
43
+ CITED_DETECTED_FIXTURE = Path(
44
+ "scripts/fixtures/bibliographic_integrity_signals/tortured_phrase_v1_2_detected.json"
45
+ )
46
+ CITED_MISSING_FIXTURE = Path(
47
+ "scripts/fixtures/bibliographic_integrity_signals/"
48
+ "tortured_phrase_v1_2_abstract_missing.json"
49
+ )
50
+ DESIGN_SPEC = Path("docs/design/2026-08-10-660-tortured-phrase-screening-spec.md")
51
+ SIGNAL_PROTOCOL = Path("shared/bibliographic_integrity_signals.md")
52
+ CONTRACT_README = Path("shared/contracts/README.md")
53
+ INTEGRITY_PROTOCOL = Path("academic-pipeline/references/integrity_review_protocol.md")
54
+ CORPUS_CONSUMER_PROTOCOL = Path(
55
+ "academic-pipeline/references/literature_corpus_consumers.md"
56
+ )
57
+ BIBLIOGRAPHY_AGENT = Path("deep-research/agents/bibliography_agent.md")
58
+ PIPELINE_SKILL = Path("academic-pipeline/SKILL.md")
59
+ PIPELINE_ORCHESTRATOR = Path(
60
+ "academic-pipeline/agents/pipeline_orchestrator_agent.md"
61
+ )
62
+ FORMATTER_AGENT = Path("academic-paper/agents/formatter_agent.md")
63
+ HANDOFF_SCHEMAS = Path("shared/handoff_schemas.md")
64
+ SIGNAL_RUNTIME = Path("scripts/bibliographic_integrity_signals.py")
65
+ CORPUS_CHECKER = Path("scripts/check_literature_corpus_schema.py")
66
+ CI_MANIFEST = Path("scripts/_ci_pytest_manifest.toml")
67
+ WORKFLOW = Path(".github/workflows/spec-consistency.yml")
68
+ HELDOUT_ROOT = Path("evals/heldout")
69
+ CONFORMANCE_README = HELDOUT_ROOT / "tortured_phrase_conformance/README.md"
70
+ MEASUREMENT_PLAN = HELDOUT_ROOT / "tortured_phrase_conformance/measurement_plan.md"
71
+ SUITE_REGISTRY = HELDOUT_ROOT / "suite_registry.json"
72
+ MEASUREMENT_CONTRACT = HELDOUT_ROOT / "MEASUREMENT_CONTRACT.md"
73
+ MEASUREMENT_REPORT = (
74
+ HELDOUT_ROOT / "tortured_phrase_conformance/measurement-2026-08-10.json"
75
+ )
76
+ MEASUREMENT_TRANSCRIPT = (
77
+ HELDOUT_ROOT
78
+ / "tortured_phrase_conformance/runs/2026-08-10/raw/pytest-transcript.json"
79
+ )
80
+ MEASUREMENT_EXECUTION_MANIFEST = (
81
+ HELDOUT_ROOT
82
+ / "tortured_phrase_conformance/runs/2026-08-10/execution-manifest.json"
83
+ )
84
+
85
+ FROZEN_MAIN_SHA = "86bf0e5c2cedb300d6d1c6428470cdcedfbf97df"
86
+ FROZEN_PLAN_SHA256 = (
87
+ "c5ca307f2e5941d8b6ed411169d7dc956d0290de7c75a54b25b8e04e070e0792"
88
+ )
89
+ MEASUREMENT_COMMAND = "python -m pytest -q scripts/test_tortured_phrase_screening.py"
90
+ MEASUREMENT_COMMAND_SHA256 = (
91
+ "3c85403d49ddbe4907b6277d2664c006b364c045fb1c1db412a817dcd855c110"
92
+ )
93
+ MEASUREMENT_TRANSCRIPT_SHA256 = (
94
+ "62252493e7c5b04e5a7276e60d54696c6df251f704f6237980f4932b9bb76541"
95
+ )
96
+ MEASUREMENT_EXECUTION_MANIFEST_SHA256 = (
97
+ "a3801e22c2482a3fba05e65b520ceeedacf7e4d8fdc57f8fce1bfd111d05e6c1"
98
+ )
99
+ MEASUREMENT_REPORT_SHA256 = (
100
+ "fdb3f4b1300dbe10a9982c7663668e997556868507e4bfcf7cd088f10990fd11"
101
+ )
102
+ MEASUREMENT_STARTED_AT = "2026-08-10T04:31:45.398248Z"
103
+ MEASUREMENT_COMPLETED_AT = "2026-08-10T04:31:50.553009Z"
104
+
105
+ SNAPSHOT_VERSION = "tortured-phrase-snapshot/1.0"
106
+ MANIFEST_VERSION = "tortured-phrase-snapshot-manifest/1.0"
107
+ ADVISORY_VERSION = "tortured-phrase-advisory/1.0"
108
+ SIGNAL_VERSION = "bibliographic-integrity-signal/1.2"
109
+ GRAMMAR_PROFILE = "ars-tortured-phrase-canonical-ast/1.0"
110
+ NORMALIZER_PROFILE = "ars-nfkc-casefold-token/1.0"
111
+ ADVISORY_LABEL = "Phrase-list screening advisory"
112
+
113
+ FROZEN_RUNTIME_SHA256 = {
114
+ RUNTIME: "4bb5290194d76f253ba2a23c41ce928d31a6953d73ad3a8686505710e44290c4",
115
+ SIGNAL_RUNTIME: "9c12c9cb426b62d36c88b344067a68b1ce5a17d114d2cbde4390f57eb4cbf2d8",
116
+ CORPUS_CHECKER: "8a1044f6fd6993ee5087b5bb395dcbc6a8b0a73be2d678897c875480332136de",
117
+ }
118
+
119
+ SNAPSHOT_ROOT_KEYS = {
120
+ "schema_version",
121
+ "snapshot_id",
122
+ "grammar_profile",
123
+ "normalizer_profile",
124
+ "rules",
125
+ }
126
+ MANIFEST_ROOT_KEYS = {
127
+ "schema_version",
128
+ "snapshot_id",
129
+ "source",
130
+ "supply_mode",
131
+ "snapshot_schema_version",
132
+ "snapshot_sha256",
133
+ "grammar_profile",
134
+ "normalizer_profile",
135
+ "preprocessor",
136
+ "unsupported_rule_count",
137
+ "rule_count",
138
+ "rights",
139
+ }
140
+ ADVISORY_ROOT_KEYS = {
141
+ "schema_version",
142
+ "layer",
143
+ "evaluation_status",
144
+ "surface",
145
+ "input_binding",
146
+ "check_status",
147
+ "finding",
148
+ "reason_code",
149
+ "counts",
150
+ "matches",
151
+ "boundary",
152
+ "report_sha256",
153
+ }
154
+ COUNTS_KEYS = {
155
+ "rules_evaluated",
156
+ "matched_rule_count",
157
+ "rule_match_count",
158
+ "unique_instance_count",
159
+ "segments_total",
160
+ "unknown_segments",
161
+ "matches_by_context",
162
+ }
163
+ MATCH_KEYS = {
164
+ "match_id",
165
+ "pattern_id",
166
+ "pattern_sha256",
167
+ "segment_id",
168
+ "context",
169
+ "disposition",
170
+ "source_span",
171
+ "matched_text",
172
+ "matched_text_sha256",
173
+ }
174
+ BOUNDARY_VALUES = {
175
+ "list_match_only": True,
176
+ "origin_inference": "not_performed",
177
+ "contextual_judgment": "not_performed",
178
+ "automatic_rewrite": False,
179
+ "absence_is_clean_certificate": False,
180
+ "native_pps_compatibility": "not_claimed",
181
+ "sharing_scope": "local_only",
182
+ }
183
+ CONTEXTS = {
184
+ "author_prose",
185
+ "quote",
186
+ "cited_title",
187
+ "reference_entry",
188
+ "code_or_verbatim",
189
+ "unknown",
190
+ "cited_abstract",
191
+ }
192
+
193
+ FORBIDDEN_IMPORT_ROOTS = {
194
+ "aiohttp",
195
+ "anthropic",
196
+ "cohere",
197
+ "http",
198
+ "httpx",
199
+ "mistralai",
200
+ "multiprocessing",
201
+ "openai",
202
+ "requests",
203
+ "socket",
204
+ "subprocess",
205
+ "urllib",
206
+ "urllib3",
207
+ }
208
+ FORBIDDEN_IMPORT_PREFIXES = {"http.client", "urllib.request"}
209
+ FORBIDDEN_CALLS = {
210
+ "__import__",
211
+ "compile",
212
+ "eval",
213
+ "exec",
214
+ "os.getenv",
215
+ "os.popen",
216
+ "os.system",
217
+ "subprocess.Popen",
218
+ "subprocess.call",
219
+ "subprocess.check_call",
220
+ "subprocess.check_output",
221
+ "subprocess.run",
222
+ "urllib.request.urlopen",
223
+ }
224
+ FORBIDDEN_PROCESS_CALL_TAILS = {
225
+ "create_subprocess_exec",
226
+ "create_subprocess_shell",
227
+ "execv",
228
+ "execve",
229
+ "spawnl",
230
+ "spawnle",
231
+ "spawnlp",
232
+ "spawnlpe",
233
+ "spawnv",
234
+ "spawnve",
235
+ "spawnvp",
236
+ "spawnvpe",
237
+ }
238
+ FORBIDDEN_FILE_TIME_TAILS = {"getctime", "getmtime", "lstat", "stat", "touch"}
239
+ FORBIDDEN_CLOCK_CALLS = {
240
+ "datetime.date.today",
241
+ "datetime.datetime.now",
242
+ "datetime.datetime.today",
243
+ "datetime.datetime.utcnow",
244
+ "time.monotonic",
245
+ "time.monotonic_ns",
246
+ "time.perf_counter",
247
+ "time.perf_counter_ns",
248
+ "time.process_time",
249
+ "time.time",
250
+ "time.time_ns",
251
+ "uuid.uuid1",
252
+ }
253
+ FORBIDDEN_SCAN_TAILS = {
254
+ "fwalk",
255
+ "glob",
256
+ "iglob",
257
+ "iterdir",
258
+ "listdir",
259
+ "rglob",
260
+ "scandir",
261
+ "walk",
262
+ }
263
+ FORBIDDEN_CLI_OPTIONS = {"--all", "--page", "--page-size"}
264
+
265
+ REQUIRED_DOC_TOKENS = {
266
+ DESIGN_SPEC: (
267
+ "DESIGN-FROZEN / UNMEASURED",
268
+ "HEURISTIC-INDICATOR",
269
+ "HEURISTIC-ADVISORY",
270
+ "one prior v1.2 row for the same",
271
+ "`literal`, `all`, `any`, and `near`",
272
+ "rule-level segment-scoped `exclude_if`",
273
+ "ABSTRACT_EMPTY",
274
+ "DOCUMENT_EMPTY",
275
+ "MAX_CORPUS_ENTRIES = 512",
276
+ "MAX_CORPUS_EXISTING_SIGNALS = 8192",
277
+ "MAX_STRUCTURE_DEPTH = 64",
278
+ "MAX_STRUCTURE_NODES = 200_000",
279
+ "MAX_PARSE_WORK_UNITS = 100_000",
280
+ "pre-normalization maximum of 4,096 raw code points per token",
281
+ "Opaque constructs are lexed strictly in source order",
282
+ "preceded by an odd run of backslashes are literal",
283
+ "`N+1` raises the resource-limit failure",
284
+ "leaves a pre-existing output byte-identical",
285
+ "category label is the neutral **“Phrase-list screening",
286
+ "advisory”**; positive wording appears only on a `detected` row",
287
+ "No #654 measurement row may be manufactured",
288
+ "no traversal flags",
289
+ "native PPS parser",
290
+ ),
291
+ SIGNAL_PROTOCOL: (
292
+ "Version 1.2 carries one current `tortured_phrase_match` row per",
293
+ "heuristic_advisory",
294
+ "HEURISTIC-INDICATOR",
295
+ "evaluation_status: UNMEASURED",
296
+ "ABSTRACT_MISSING",
297
+ "display.marker_token` is always `null",
298
+ ),
299
+ CONTRACT_README: (
300
+ "audit/tortured_phrase_snapshot.schema.json",
301
+ "audit/tortured_phrase_snapshot_manifest.schema.json",
302
+ "audit/tortured_phrase_advisory.schema.json",
303
+ "scripts/tortured_phrase_screening.py",
304
+ "no native PPS importer",
305
+ "ambient clock",
306
+ ),
307
+ INTEGRITY_PROTOCOL: (
308
+ "tortured-phrase-advisory/1.0",
309
+ "HEURISTIC-ADVISORY` / `UNMEASURED",
310
+ "Stage 2.5 or Stage 4.5 PASS/FAIL decision",
311
+ "ABSTRACT_MISSING",
312
+ ),
313
+ CORPUS_CONSUMER_PROTOCOL: (
314
+ "bibliographic-integrity-signal/1.2",
315
+ "each have one current row",
316
+ "Phase 1 consumers do not build, fetch, import, repair, or",
317
+ "redistribute a PPS list",
318
+ "HEURISTIC-ADVISORY` / `UNMEASURED",
319
+ ),
320
+ BIBLIOGRAPHY_AGENT: (
321
+ "scripts/tortured_phrase_screening.py enrich-passport",
322
+ "exactly one current v1.2 `tortured_phrase_match` row",
323
+ "no live model, external API, human or model judge, ambient clock",
324
+ "phrase-list match requiring review",
325
+ ),
326
+ PIPELINE_SKILL: (
327
+ "### Tortured-phrase advisory (#660)",
328
+ "one current v1.2 advisory row per `cited_title` and `cited_abstract`",
329
+ "HEURISTIC-ADVISORY` / `UNMEASURED",
330
+ "timestamps are explicit inputs",
331
+ ),
332
+ PIPELINE_ORCHESTRATOR: (
333
+ "scripts/tortured_phrase_screening.py",
334
+ "Pass `checked_at` and `recorded_at` as explicit RFC 3339 inputs",
335
+ "tortured-phrase-advisory/1.0",
336
+ "evaluation_status: UNMEASURED",
337
+ "schema-valid degraded advisory and then exit 1",
338
+ ),
339
+ FORMATTER_AGENT: (
340
+ "v1.2 `tortured_phrase_match` row",
341
+ "neutral **Phrase-list screening advisory**",
342
+ "ABSTRACT_EMPTY",
343
+ "single bounded page of at most 25 match-detail rows",
344
+ "Do not re-run matching",
345
+ "HEURISTIC-ADVISORY` / `UNMEASURED",
346
+ ),
347
+ HANDOFF_SCHEMAS: (
348
+ "bibliographic-integrity-signal/1.2",
349
+ "one current row for `cited_title` and one for",
350
+ "`cited_abstract`; the surfaces never share a rolled-up status",
351
+ "HEURISTIC-INDICATOR",
352
+ "tortured-phrase-advisory/1.0",
353
+ ),
354
+ }
355
+ REQUIRED_CONSUMER_TOKENS = {
356
+ SIGNAL_RUNTIME: (
357
+ "HEURISTIC-INDICATOR",
358
+ "tortured_phrase_context",
359
+ "Bibliographic Integrity Advisories",
360
+ ),
361
+ CORPUS_CHECKER: (
362
+ "validate_cited_signal_binding",
363
+ "tortured_phrase_match",
364
+ "multiple current ",
365
+ "tortured-phrase rows for surface",
366
+ ),
367
+ }
368
+
369
+
370
+ class DuplicateKeyError(ValueError):
371
+ """Strict JSON duplicate-key failure."""
372
+
373
+
374
+ def _pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
375
+ result: dict[str, Any] = {}
376
+ for key, value in pairs:
377
+ if key in result:
378
+ raise DuplicateKeyError(f"duplicate JSON key {key!r}")
379
+ result[key] = value
380
+ return result
381
+
382
+
383
+ def _load_json_bytes(path: Path) -> tuple[dict[str, Any], bytes]:
384
+ raw = path.read_bytes()
385
+ if raw.startswith(b"\xef\xbb\xbf"):
386
+ raise ValueError("UTF-8 BOM is forbidden")
387
+ text = raw.decode("utf-8", errors="strict")
388
+ value = json.loads(
389
+ text,
390
+ object_pairs_hook=_pairs,
391
+ parse_constant=lambda token: (_ for _ in ()).throw(
392
+ ValueError(f"non-finite JSON constant {token!r}")
393
+ ),
394
+ )
395
+ if not isinstance(value, dict):
396
+ raise ValueError("top level must be an object")
397
+ return value, raw
398
+
399
+
400
+ def _load_json(path: Path) -> dict[str, Any]:
401
+ return _load_json_bytes(path)[0]
402
+
403
+
404
+ def _closed_fields(
405
+ schema: dict[str, Any], expected: set[str], label: str, errors: list[str]
406
+ ) -> None:
407
+ if schema.get("additionalProperties") is not False:
408
+ errors.append(f"{label}: object must remain closed")
409
+ if set(schema.get("required", ())) != expected:
410
+ errors.append(f"{label}: required field set drifted")
411
+ if set(schema.get("properties", {})) != expected:
412
+ errors.append(f"{label}: property field set drifted")
413
+
414
+
415
+ def _consts(
416
+ schema: dict[str, Any], expected: dict[str, Any], label: str, errors: list[str]
417
+ ) -> None:
418
+ properties = schema.get("properties", {})
419
+ for name, value in expected.items():
420
+ if properties.get(name, {}).get("const") != value:
421
+ errors.append(f"{label}: {name} must equal {value!r}")
422
+
423
+
424
+ def _property_names(value: Any) -> set[str]:
425
+ names: set[str] = set()
426
+ if isinstance(value, dict):
427
+ properties = value.get("properties")
428
+ if isinstance(properties, dict):
429
+ names.update(properties)
430
+ for child in value.values():
431
+ names.update(_property_names(child))
432
+ elif isinstance(value, list):
433
+ for child in value:
434
+ names.update(_property_names(child))
435
+ return names
436
+
437
+
438
+ def _schema_errors(root: Path) -> list[str]:
439
+ errors: list[str] = []
440
+ schemas: dict[Path, dict[str, Any]] = {}
441
+ for relative in (SNAPSHOT_SCHEMA, MANIFEST_SCHEMA, ADVISORY_SCHEMA, SIGNAL_SCHEMA):
442
+ try:
443
+ schema = _load_json(root / relative)
444
+ Draft202012Validator.check_schema(schema)
445
+ schemas[relative] = schema
446
+ except (OSError, UnicodeError, ValueError, DuplicateKeyError) as exc:
447
+ errors.append(f"{relative}: cannot load/check schema: {exc}")
448
+ except Exception as exc: # jsonschema.SchemaError without API coupling.
449
+ errors.append(f"{relative}: cannot load/check schema: {exc}")
450
+ if len(schemas) != 4:
451
+ return errors
452
+
453
+ snapshot = schemas[SNAPSHOT_SCHEMA]
454
+ _closed_fields(snapshot, SNAPSHOT_ROOT_KEYS, str(SNAPSHOT_SCHEMA), errors)
455
+ _consts(
456
+ snapshot,
457
+ {
458
+ "schema_version": SNAPSHOT_VERSION,
459
+ "grammar_profile": GRAMMAR_PROFILE,
460
+ "normalizer_profile": NORMALIZER_PROFILE,
461
+ },
462
+ str(SNAPSHOT_SCHEMA),
463
+ errors,
464
+ )
465
+ definitions = snapshot.get("$defs", {})
466
+ expression_refs = {
467
+ branch.get("$ref")
468
+ for branch in definitions.get("expression", {}).get("oneOf", ())
469
+ if isinstance(branch, dict)
470
+ }
471
+ if expression_refs != {
472
+ "#/$defs/literal_expression",
473
+ "#/$defs/all_expression",
474
+ "#/$defs/any_expression",
475
+ "#/$defs/near_expression",
476
+ }:
477
+ errors.append(f"{SNAPSHOT_SCHEMA}: expression operator set drifted")
478
+ expression_shapes = {
479
+ "literal_expression": ({"op", "value"}, {"op", "value"}),
480
+ "all_expression": (
481
+ {"op", "terms", "max_span_tokens"},
482
+ {"op", "terms", "max_span_tokens"},
483
+ ),
484
+ "any_expression": ({"op", "alternatives"}, {"op", "alternatives"}),
485
+ "near_expression": (
486
+ {"op", "left", "right", "max_gap_tokens", "ordered"},
487
+ {"op", "left", "right", "max_gap_tokens", "ordered"},
488
+ ),
489
+ "exclusion": (
490
+ {"expression", "within_tokens"},
491
+ {"expression", "within_tokens"},
492
+ ),
493
+ "rule": ({"rule_id", "expression"}, {"rule_id", "expression", "exclude_if"}),
494
+ }
495
+ for name, (required, properties) in expression_shapes.items():
496
+ definition = definitions.get(name, {})
497
+ if definition.get("additionalProperties") is not False:
498
+ errors.append(f"{SNAPSHOT_SCHEMA}: $defs.{name} must remain closed")
499
+ if set(definition.get("required", ())) != required:
500
+ errors.append(f"{SNAPSHOT_SCHEMA}: $defs.{name} required fields drifted")
501
+ if set(definition.get("properties", {})) != properties:
502
+ errors.append(f"{SNAPSHOT_SCHEMA}: $defs.{name} properties drifted")
503
+ for name, key in (("all_expression", "terms"), ("any_expression", "alternatives")):
504
+ array = definitions.get(name, {}).get("properties", {}).get(key, {})
505
+ if (array.get("minItems"), array.get("maxItems")) != (2, 8):
506
+ errors.append(f"{SNAPSHOT_SCHEMA}: {name}.{key} must contain 2..8 nodes")
507
+ exclusion = definitions.get("rule", {}).get("properties", {}).get("exclude_if", {})
508
+ if (exclusion.get("minItems"), exclusion.get("maxItems")) != (1, 8):
509
+ errors.append(f"{SNAPSHOT_SCHEMA}: rule.exclude_if must contain 1..8 exclusions")
510
+ forbidden_schema_fields = {
511
+ "not",
512
+ "regex",
513
+ "wildcard",
514
+ "severity",
515
+ "score",
516
+ "probability",
517
+ "confidence",
518
+ "origin",
519
+ "contamination",
520
+ }
521
+ forbidden = _property_names(snapshot) & forbidden_schema_fields
522
+ if forbidden:
523
+ errors.append(f"{SNAPSHOT_SCHEMA}: forbidden fields {sorted(forbidden)}")
524
+
525
+ manifest = schemas[MANIFEST_SCHEMA]
526
+ _closed_fields(manifest, MANIFEST_ROOT_KEYS, str(MANIFEST_SCHEMA), errors)
527
+ _consts(
528
+ manifest,
529
+ {
530
+ "schema_version": MANIFEST_VERSION,
531
+ "snapshot_schema_version": SNAPSHOT_VERSION,
532
+ "grammar_profile": GRAMMAR_PROFILE,
533
+ "normalizer_profile": NORMALIZER_PROFILE,
534
+ },
535
+ str(MANIFEST_SCHEMA),
536
+ errors,
537
+ )
538
+ if set(manifest.get("properties", {}).get("supply_mode", {}).get("enum", ())) != {
539
+ "user_supplied",
540
+ "synthetic_fixture",
541
+ }:
542
+ errors.append(f"{MANIFEST_SCHEMA}: supply_mode vocabulary drifted")
543
+ manifest_defs = manifest.get("$defs", {})
544
+ for name, fields in (
545
+ ("source", {"name", "version", "as_of", "locator"}),
546
+ ("preprocessor", {"name", "version", "native_grammar", "reduction_notes"}),
547
+ (
548
+ "rights",
549
+ {"basis", "redistribution_status", "reference", "user_declaration"},
550
+ ),
551
+ ):
552
+ _closed_fields(
553
+ manifest_defs.get(name, {}), fields, f"{MANIFEST_SCHEMA}: $defs.{name}", errors
554
+ )
555
+
556
+ advisory = schemas[ADVISORY_SCHEMA]
557
+ _closed_fields(advisory, ADVISORY_ROOT_KEYS, str(ADVISORY_SCHEMA), errors)
558
+ _consts(
559
+ advisory,
560
+ {
561
+ "schema_version": ADVISORY_VERSION,
562
+ "layer": "HEURISTIC-ADVISORY",
563
+ "evaluation_status": "UNMEASURED",
564
+ "surface": "own_draft",
565
+ },
566
+ str(ADVISORY_SCHEMA),
567
+ errors,
568
+ )
569
+ advisory_defs = advisory.get("$defs", {})
570
+ _closed_fields(
571
+ advisory_defs.get("counts", {}), COUNTS_KEYS, f"{ADVISORY_SCHEMA}: $defs.counts", errors
572
+ )
573
+ _closed_fields(
574
+ advisory_defs.get("match", {}), MATCH_KEYS, f"{ADVISORY_SCHEMA}: $defs.match", errors
575
+ )
576
+ boundary = advisory_defs.get("boundary", {})
577
+ _closed_fields(
578
+ boundary, set(BOUNDARY_VALUES), f"{ADVISORY_SCHEMA}: $defs.boundary", errors
579
+ )
580
+ _consts(boundary, BOUNDARY_VALUES, f"{ADVISORY_SCHEMA}: $defs.boundary", errors)
581
+ contexts = set(
582
+ advisory_defs.get("match", {})
583
+ .get("properties", {})
584
+ .get("context", {})
585
+ .get("enum", ())
586
+ )
587
+ if contexts != CONTEXTS:
588
+ errors.append(f"{ADVISORY_SCHEMA}: match context vocabulary drifted")
589
+ if advisory.get("properties", {}).get("matches", {}).get("maxItems") != 4096:
590
+ errors.append(f"{ADVISORY_SCHEMA}: full machine match bound drifted")
591
+ advisory_reasons = set(advisory_defs.get("reason_code", {}).get("enum", ()))
592
+ if "DOCUMENT_EMPTY" not in advisory_reasons:
593
+ errors.append(f"{ADVISORY_SCHEMA}: reason_code must include DOCUMENT_EMPTY")
594
+
595
+ signal = schemas[SIGNAL_SCHEMA]
596
+ versions = set(signal.get("properties", {}).get("schema_version", {}).get("enum", ()))
597
+ if SIGNAL_VERSION not in versions:
598
+ errors.append(f"{SIGNAL_SCHEMA}: missing additive {SIGNAL_VERSION} carrier")
599
+ phrase_context = signal.get("properties", {}).get("tortured_phrase_context", {})
600
+ expected_phrase_fields = {
601
+ "layer",
602
+ "evaluation_status",
603
+ "surface",
604
+ "surface_binding",
605
+ "snapshot",
606
+ "reason_code",
607
+ "counts",
608
+ "matches",
609
+ "boundary",
610
+ }
611
+ _closed_fields(
612
+ phrase_context,
613
+ expected_phrase_fields,
614
+ f"{SIGNAL_SCHEMA}: properties.tortured_phrase_context",
615
+ errors,
616
+ )
617
+ _consts(
618
+ phrase_context,
619
+ {"layer": "HEURISTIC-ADVISORY", "evaluation_status": "UNMEASURED"},
620
+ f"{SIGNAL_SCHEMA}: properties.tortured_phrase_context",
621
+ errors,
622
+ )
623
+ if set(
624
+ phrase_context.get("properties", {}).get("surface", {}).get("enum", ())
625
+ ) != {"cited_title", "cited_abstract"}:
626
+ errors.append(f"{SIGNAL_SCHEMA}: citation surface vocabulary drifted")
627
+ phrase_reasons = set(
628
+ phrase_context.get("properties", {}).get("reason_code", {}).get("enum", ())
629
+ )
630
+ if "ABSTRACT_EMPTY" not in phrase_reasons:
631
+ errors.append(f"{SIGNAL_SCHEMA}: reason_code must include ABSTRACT_EMPTY")
632
+
633
+ version_branch: dict[str, Any] | None = None
634
+ type_branch: dict[str, Any] | None = None
635
+ for branch in signal.get("allOf", ()):
636
+ if not isinstance(branch, dict):
637
+ continue
638
+ condition = branch.get("if", {}).get("properties", {})
639
+ if condition.get("schema_version", {}).get("const") == SIGNAL_VERSION:
640
+ version_branch = branch
641
+ if condition.get("signal_type", {}).get("const") == "tortured_phrase_match":
642
+ type_branch = branch
643
+ then = version_branch.get("then", {}) if version_branch else {}
644
+ then_properties = then.get("properties", {})
645
+ if (
646
+ "tortured_phrase_context" not in set(then.get("required", ()))
647
+ or then_properties.get("signal_type", {}).get("const") != "tortured_phrase_match"
648
+ or then_properties.get("epistemic_class", {}).get("const")
649
+ != "heuristic_advisory"
650
+ or then_properties.get("epistemic_label", {}).get("const")
651
+ != "HEURISTIC-INDICATOR"
652
+ or then_properties.get("display", {})
653
+ .get("properties", {})
654
+ .get("summary_label", {})
655
+ .get("const")
656
+ != ADVISORY_LABEL
657
+ ):
658
+ errors.append(f"{SIGNAL_SCHEMA}: v1.2 tortured-phrase profile drifted")
659
+ not_checked_reasons: set[str] = set()
660
+ for branch in signal.get("allOf", ()):
661
+ if not isinstance(branch, dict):
662
+ continue
663
+ then_properties_for_branch = branch.get("then", {}).get("properties", {})
664
+ if (
665
+ then_properties_for_branch.get("check_status", {}).get("const")
666
+ == "not_checked"
667
+ and then_properties_for_branch.get("finding", {}).get("const")
668
+ == "unresolved"
669
+ ):
670
+ not_checked_reasons.update(
671
+ branch.get("if", {})
672
+ .get("properties", {})
673
+ .get("tortured_phrase_context", {})
674
+ .get("properties", {})
675
+ .get("reason_code", {})
676
+ .get("enum", ())
677
+ )
678
+ if "ABSTRACT_EMPTY" not in not_checked_reasons:
679
+ errors.append(
680
+ f"{SIGNAL_SCHEMA}: ABSTRACT_EMPTY must map to not_checked/unresolved"
681
+ )
682
+ type_properties = type_branch.get("then", {}).get("properties", {}) if type_branch else {}
683
+ terminal = type_properties.get("terminal_policy", {}).get("properties", {})
684
+ display = type_properties.get("display", {}).get("properties", {})
685
+ if (
686
+ type_properties.get("epistemic_class", {}).get("const")
687
+ != "heuristic_advisory"
688
+ or type_properties.get("epistemic_label", {}).get("const")
689
+ != "HEURISTIC-INDICATOR"
690
+ or terminal.get("eligible", {}).get("const") is not False
691
+ or terminal.get("owner", {}).get("const") != "none"
692
+ or terminal.get("current_effect", {}).get("const") != "advisory_only"
693
+ or display.get("marker_token", {}).get("type") != "null"
694
+ ):
695
+ errors.append(f"{SIGNAL_SCHEMA}: heuristic/advisory-only policy boundary drifted")
696
+ return errors
697
+
698
+
699
+ def _fixture_errors(root: Path) -> list[str]:
700
+ errors: list[str] = []
701
+ try:
702
+ snapshot, snapshot_raw = _load_json_bytes(root / SNAPSHOT_FIXTURE)
703
+ manifest = _load_json(root / MANIFEST_FIXTURE)
704
+ expectations = _load_json(root / EXPECTATIONS_FIXTURE)
705
+ cited_detected = _load_json(root / CITED_DETECTED_FIXTURE)
706
+ cited_missing = _load_json(root / CITED_MISSING_FIXTURE)
707
+ snapshot_schema = _load_json(root / SNAPSHOT_SCHEMA)
708
+ manifest_schema = _load_json(root / MANIFEST_SCHEMA)
709
+ signal_schema = _load_json(root / SIGNAL_SCHEMA)
710
+ except (OSError, UnicodeError, ValueError, DuplicateKeyError) as exc:
711
+ return [f"#660 fixture load failed: {exc}"]
712
+
713
+ for value, schema, label in (
714
+ (snapshot, snapshot_schema, SNAPSHOT_FIXTURE),
715
+ (manifest, manifest_schema, MANIFEST_FIXTURE),
716
+ (cited_detected, signal_schema, CITED_DETECTED_FIXTURE),
717
+ (cited_missing, signal_schema, CITED_MISSING_FIXTURE),
718
+ ):
719
+ validator = Draft202012Validator(
720
+ schema, format_checker=Draft202012Validator.FORMAT_CHECKER
721
+ )
722
+ validation_errors = sorted(
723
+ error.message for error in validator.iter_errors(value)
724
+ )
725
+ if validation_errors:
726
+ errors.append(f"{label}: schema validation failed: {validation_errors[0]}")
727
+
728
+ snapshot_sha = hashlib.sha256(snapshot_raw).hexdigest()
729
+ manifest_sha = hashlib.sha256((root / MANIFEST_FIXTURE).read_bytes()).hexdigest()
730
+ if manifest.get("snapshot_sha256") != snapshot_sha:
731
+ errors.append(f"{MANIFEST_FIXTURE}: snapshot_sha256 does not bind exact bytes")
732
+ if expectations.get("snapshot_sha256") != snapshot_sha:
733
+ errors.append(f"{EXPECTATIONS_FIXTURE}: snapshot_sha256 does not bind exact bytes")
734
+ if not (
735
+ snapshot.get("snapshot_id")
736
+ == manifest.get("snapshot_id")
737
+ == expectations.get("snapshot_id")
738
+ ):
739
+ errors.append("#660 fixtures: snapshot_id join drifted")
740
+ rules = snapshot.get("rules", [])
741
+ if manifest.get("rule_count") != len(rules):
742
+ errors.append(f"{MANIFEST_FIXTURE}: rule_count does not bind snapshot rules")
743
+ if manifest.get("unsupported_rule_count") != 0:
744
+ errors.append(f"{MANIFEST_FIXTURE}: partial/unsupported rule fixture is forbidden")
745
+ if not rules or any(
746
+ not isinstance(rule, dict)
747
+ or not isinstance(rule.get("rule_id"), str)
748
+ or not rule["rule_id"].startswith("syn_")
749
+ for rule in rules
750
+ ):
751
+ errors.append(f"{SNAPSHOT_FIXTURE}: every fixture rule must be explicitly synthetic")
752
+ source = manifest.get("source", {})
753
+ preprocessor = manifest.get("preprocessor", {})
754
+ rights = manifest.get("rights", {})
755
+ if (
756
+ manifest.get("supply_mode") != "synthetic_fixture"
757
+ or rights
758
+ != {
759
+ "basis": "synthetic_fixture",
760
+ "redistribution_status": "permitted",
761
+ "reference": None,
762
+ "user_declaration": None,
763
+ }
764
+ or not str(source.get("name", "")).lower().startswith("ars synthetic")
765
+ or not str(source.get("locator", "")).startswith("fixture://")
766
+ or not str(preprocessor.get("native_grammar", "")).startswith("synthetic-")
767
+ ):
768
+ errors.append(f"{MANIFEST_FIXTURE}: synthetic-only provenance/rights boundary drifted")
769
+ if (
770
+ expectations.get("label_scope") != "mechanical_matcher_conformance_only"
771
+ or expectations.get("empirical_accuracy_claimed") is not False
772
+ or expectations.get("contextual_false_positive_labels_provided") is not False
773
+ or expectations.get("contextual_false_negative_labels_provided") is not False
774
+ ):
775
+ errors.append(f"{EXPECTATIONS_FIXTURE}: synthetic UNMEASURED claim ceiling drifted")
776
+ input_paths = {
777
+ item.get("path")
778
+ for item in expectations.get("inputs", ())
779
+ if isinstance(item, dict)
780
+ }
781
+ if input_paths != {"own_draft.md", "own_draft.tex", "corpus_input.yaml"}:
782
+ errors.append(f"{EXPECTATIONS_FIXTURE}: conformance input inventory drifted")
783
+ for fixture, expected in (
784
+ (
785
+ cited_detected,
786
+ {
787
+ "surface": "cited_title",
788
+ "check_status": "checked",
789
+ "finding": "detected",
790
+ "reason_code": "CHECK_COMPLETED",
791
+ },
792
+ ),
793
+ (
794
+ cited_missing,
795
+ {
796
+ "surface": "cited_abstract",
797
+ "check_status": "not_checked",
798
+ "finding": "unresolved",
799
+ "reason_code": "ABSTRACT_MISSING",
800
+ },
801
+ ),
802
+ ):
803
+ context = fixture.get("tortured_phrase_context", {})
804
+ binding = context.get("snapshot", {}) if isinstance(context, dict) else {}
805
+ if (
806
+ fixture.get("schema_version") != SIGNAL_VERSION
807
+ or fixture.get("signal_type") != "tortured_phrase_match"
808
+ or fixture.get("epistemic_class") != "heuristic_advisory"
809
+ or fixture.get("epistemic_label") != "HEURISTIC-INDICATOR"
810
+ or fixture.get("check_status") != expected["check_status"]
811
+ or fixture.get("finding") != expected["finding"]
812
+ or context.get("layer") != "HEURISTIC-ADVISORY"
813
+ or context.get("evaluation_status") != "UNMEASURED"
814
+ or context.get("surface") != expected["surface"]
815
+ or context.get("reason_code") != expected["reason_code"]
816
+ or binding.get("snapshot_sha256") != snapshot_sha
817
+ or binding.get("manifest_sha256") != manifest_sha
818
+ or fixture.get("terminal_policy", {}).get("eligible") is not False
819
+ or fixture.get("display", {}).get("marker_token") is not None
820
+ or fixture.get("display", {}).get("summary_label") != ADVISORY_LABEL
821
+ ):
822
+ errors.append("#660 cited v1.2 fixtures: carrier/replay/claim binding drifted")
823
+ for relative, tokens in (
824
+ (FIXTURE_ROOT / "own_draft.md", ("luminous turnip", "crystal\u00adfern", "silver-\nleaf")),
825
+ (FIXTURE_ROOT / "own_draft.tex", ("luminous turnip", "SILVER-LEAF")),
826
+ (
827
+ FIXTURE_ROOT / "corpus_input.yaml",
828
+ ("fixture_complete_2026", "fixture_missing_2026", "fixture_negative_2026"),
829
+ ),
830
+ ):
831
+ try:
832
+ text = (root / relative).read_text(encoding="utf-8")
833
+ except (OSError, UnicodeError) as exc:
834
+ errors.append(f"{relative}: cannot read synthetic input: {exc}")
835
+ continue
836
+ missing = [token for token in tokens if token not in text]
837
+ if missing:
838
+ errors.append(f"{relative}: missing conformance markers {missing}")
839
+ return errors
840
+
841
+
842
+ def _function_map(tree: ast.Module) -> dict[str, ast.FunctionDef | ast.AsyncFunctionDef]:
843
+ return {
844
+ node.name: node
845
+ for node in tree.body
846
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
847
+ }
848
+
849
+
850
+ def _assignment_value(tree: ast.Module, name: str) -> Any:
851
+ for node in tree.body:
852
+ if not isinstance(node, (ast.Assign, ast.AnnAssign)):
853
+ continue
854
+ targets = node.targets if isinstance(node, ast.Assign) else [node.target]
855
+ if not any(isinstance(target, ast.Name) and target.id == name for target in targets):
856
+ continue
857
+ try:
858
+ return ast.literal_eval(node.value)
859
+ except (TypeError, ValueError):
860
+ return None
861
+ return None
862
+
863
+
864
+ def _import_aliases(tree: ast.Module) -> dict[str, str]:
865
+ aliases: dict[str, str] = {}
866
+ for node in ast.walk(tree):
867
+ if isinstance(node, ast.Import):
868
+ for item in node.names:
869
+ aliases[item.asname or item.name.split(".", 1)[0]] = item.name
870
+ elif isinstance(node, ast.ImportFrom) and node.module:
871
+ for item in node.names:
872
+ aliases[item.asname or item.name] = f"{node.module}.{item.name}"
873
+ return aliases
874
+
875
+
876
+ def _qualified(node: ast.AST, aliases: dict[str, str]) -> str | None:
877
+ if isinstance(node, ast.Name):
878
+ return aliases.get(node.id, node.id)
879
+ if isinstance(node, ast.Attribute):
880
+ prefix = _qualified(node.value, aliases)
881
+ return f"{prefix}.{node.attr}" if prefix else node.attr
882
+ return None
883
+
884
+
885
+ def _arg_names(function: ast.FunctionDef | ast.AsyncFunctionDef) -> set[str]:
886
+ return {
887
+ argument.arg
888
+ for argument in (
889
+ function.args.posonlyargs + function.args.args + function.args.kwonlyargs
890
+ )
891
+ }
892
+
893
+
894
+ def _limit_comparison_count(
895
+ function: ast.FunctionDef | ast.AsyncFunctionDef, constant_name: str
896
+ ) -> int:
897
+ return sum(
898
+ 1
899
+ for node in ast.walk(function)
900
+ if isinstance(node, ast.Compare)
901
+ and any(
902
+ isinstance(child, ast.Name)
903
+ and isinstance(child.ctx, ast.Load)
904
+ and child.id == constant_name
905
+ for child in ast.walk(node)
906
+ )
907
+ )
908
+
909
+
910
+ def _strict_limit_guard(
911
+ function: ast.FunctionDef | ast.AsyncFunctionDef,
912
+ constant_name: str,
913
+ *,
914
+ length_of: str | None = None,
915
+ value_name: str | None = None,
916
+ ) -> ast.If | None:
917
+ """Return an exact ``value > LIMIT: raise MatchLimitError`` guard."""
918
+ if (length_of is None) == (value_name is None):
919
+ raise ValueError("select exactly one limit-guard left-hand shape")
920
+ for node in ast.walk(function):
921
+ if not isinstance(node, ast.If) or not isinstance(node.test, ast.Compare):
922
+ continue
923
+ comparison = node.test
924
+ if (
925
+ len(comparison.ops) != 1
926
+ or not isinstance(comparison.ops[0], ast.Gt)
927
+ or len(comparison.comparators) != 1
928
+ or not isinstance(comparison.comparators[0], ast.Name)
929
+ or comparison.comparators[0].id != constant_name
930
+ ):
931
+ continue
932
+ left = comparison.left
933
+ if length_of is not None:
934
+ left_matches = (
935
+ isinstance(left, ast.Call)
936
+ and isinstance(left.func, ast.Name)
937
+ and left.func.id == "len"
938
+ and len(left.args) == 1
939
+ and isinstance(left.args[0], ast.Name)
940
+ and left.args[0].id == length_of
941
+ and not left.keywords
942
+ )
943
+ else:
944
+ left_matches = isinstance(left, ast.Name) and left.id == value_name
945
+ raises_limit = any(
946
+ isinstance(child, ast.Raise)
947
+ and isinstance(child.exc, ast.Call)
948
+ and isinstance(child.exc.func, ast.Name)
949
+ and child.exc.func.id == "MatchLimitError"
950
+ for statement in node.body
951
+ for child in ast.walk(statement)
952
+ )
953
+ if left_matches and raises_limit:
954
+ return node
955
+ return None
956
+
957
+
958
+ def _existing_signal_count_is_aggregate_sum(
959
+ function: ast.FunctionDef | ast.AsyncFunctionDef,
960
+ ) -> bool:
961
+ for node in ast.walk(function):
962
+ if not isinstance(node, (ast.Assign, ast.AnnAssign)):
963
+ continue
964
+ targets = node.targets if isinstance(node, ast.Assign) else [node.target]
965
+ if not any(
966
+ isinstance(target, ast.Name) and target.id == "existing_signal_count"
967
+ for target in targets
968
+ ):
969
+ continue
970
+ value = node.value
971
+ return bool(
972
+ isinstance(value, ast.Call)
973
+ and isinstance(value.func, ast.Name)
974
+ and value.func.id == "sum"
975
+ and any(
976
+ isinstance(child, ast.Call)
977
+ and isinstance(child.func, ast.Name)
978
+ and child.func.id == "len"
979
+ for child in ast.walk(value)
980
+ )
981
+ and any(
982
+ isinstance(child, ast.Constant)
983
+ and child.value == "bibliographic_integrity_signals"
984
+ for child in ast.walk(value)
985
+ )
986
+ )
987
+ return False
988
+
989
+
990
+ def _call_lines(
991
+ function: ast.FunctionDef | ast.AsyncFunctionDef,
992
+ aliases: dict[str, str],
993
+ call_name: str,
994
+ ) -> list[int]:
995
+ return sorted(
996
+ node.lineno
997
+ for node in ast.walk(function)
998
+ if isinstance(node, ast.Call)
999
+ and _qualified(node.func, aliases) == call_name
1000
+ )
1001
+
1002
+
1003
+ def _dict_binds_name(
1004
+ function: ast.FunctionDef | ast.AsyncFunctionDef, key: str, name: str
1005
+ ) -> bool:
1006
+ for node in ast.walk(function):
1007
+ if not isinstance(node, ast.Dict):
1008
+ continue
1009
+ for key_node, value_node in zip(node.keys, node.values):
1010
+ if (
1011
+ isinstance(key_node, ast.Constant)
1012
+ and key_node.value == key
1013
+ and isinstance(value_node, ast.Name)
1014
+ and isinstance(value_node.ctx, ast.Load)
1015
+ and value_node.id == name
1016
+ ):
1017
+ return True
1018
+ return False
1019
+
1020
+
1021
+ def _string_literals(function: ast.FunctionDef | ast.AsyncFunctionDef) -> set[str]:
1022
+ return {
1023
+ node.value
1024
+ for node in ast.walk(function)
1025
+ if isinstance(node, ast.Constant) and isinstance(node.value, str)
1026
+ }
1027
+
1028
+
1029
+ def _transitive_hermetic_errors(root: Path, relative: Path) -> list[str]:
1030
+ """Apply the hermetic boundary to an imported executable helper module."""
1031
+
1032
+ try:
1033
+ source = (root / relative).read_text(encoding="utf-8")
1034
+ tree = ast.parse(source, filename=str(relative))
1035
+ except (OSError, UnicodeError, SyntaxError) as exc:
1036
+ return [f"{relative}: cannot parse transitive runtime helper: {exc}"]
1037
+ errors: list[str] = []
1038
+ aliases = _import_aliases(tree)
1039
+ for node in ast.walk(tree):
1040
+ imported: list[str] = []
1041
+ if isinstance(node, ast.Import):
1042
+ imported = [item.name for item in node.names]
1043
+ elif isinstance(node, ast.ImportFrom) and node.module:
1044
+ imported = [node.module]
1045
+ for name in imported:
1046
+ if (
1047
+ name.split(".", 1)[0] in FORBIDDEN_IMPORT_ROOTS
1048
+ or any(
1049
+ name == prefix or name.startswith(prefix + ".")
1050
+ for prefix in FORBIDDEN_IMPORT_PREFIXES
1051
+ )
1052
+ ):
1053
+ errors.append(
1054
+ f"{relative}: forbidden transitive model/network/process import {name}"
1055
+ )
1056
+ if isinstance(node, ast.Call):
1057
+ name = _qualified(node.func, aliases)
1058
+ if name in FORBIDDEN_CALLS:
1059
+ errors.append(
1060
+ f"{relative}: forbidden transitive model/network/process call {name}"
1061
+ )
1062
+ if name in FORBIDDEN_CLOCK_CALLS:
1063
+ errors.append(f"{relative}: forbidden transitive ambient clock call {name}")
1064
+ tail = name.rsplit(".", 1)[-1] if name else None
1065
+ if tail in FORBIDDEN_PROCESS_CALL_TAILS:
1066
+ errors.append(f"{relative}: forbidden transitive process call {name}")
1067
+ if tail in FORBIDDEN_FILE_TIME_TAILS:
1068
+ errors.append(f"{relative}: forbidden transitive file-time call {name}")
1069
+ if tail in FORBIDDEN_SCAN_TAILS:
1070
+ errors.append(f"{relative}: forbidden transitive discovery call {name}")
1071
+ if isinstance(node, ast.Attribute) and _qualified(node, aliases) == "os.environ":
1072
+ errors.append(f"{relative}: transitive ambient environment access is forbidden")
1073
+ return errors
1074
+
1075
+
1076
+ def _runtime_errors(root: Path) -> list[str]:
1077
+ errors: list[str] = []
1078
+ try:
1079
+ source = (root / RUNTIME).read_text(encoding="utf-8")
1080
+ tree = ast.parse(source, filename=str(RUNTIME))
1081
+ except (OSError, UnicodeError, SyntaxError) as exc:
1082
+ return [f"{RUNTIME}: cannot parse: {exc}"]
1083
+
1084
+ errors.extend(_transitive_hermetic_errors(root, SIGNAL_RUNTIME))
1085
+
1086
+ functions = _function_map(tree)
1087
+ required_functions = {
1088
+ "load_snapshot",
1089
+ "build_own_draft_report",
1090
+ "validate_own_draft_report",
1091
+ "render_own_draft_report",
1092
+ "build_cited_signal",
1093
+ "validate_cited_signal_binding",
1094
+ "enrich_passport",
1095
+ "main",
1096
+ }
1097
+ missing = required_functions - set(functions)
1098
+ if missing:
1099
+ errors.append(f"{RUNTIME}: missing public functions {sorted(missing)}")
1100
+ for name, expected in (
1101
+ ("SNAPSHOT_VERSION", SNAPSHOT_VERSION),
1102
+ ("MANIFEST_VERSION", MANIFEST_VERSION),
1103
+ ("ADVISORY_VERSION", ADVISORY_VERSION),
1104
+ ("SIGNAL_VERSION", SIGNAL_VERSION),
1105
+ ("GRAMMAR_PROFILE", GRAMMAR_PROFILE),
1106
+ ("NORMALIZER_PROFILE", NORMALIZER_PROFILE),
1107
+ ("LAYER", "HEURISTIC-ADVISORY"),
1108
+ ("EVALUATION_STATUS", "UNMEASURED"),
1109
+ ("SUMMARY_LABEL", "Phrase-list match requiring review"),
1110
+ ("ADVISORY_LABEL", ADVISORY_LABEL),
1111
+ ("MAX_NODE_WITNESSES", 512),
1112
+ ("MAX_NODE_COMBINATIONS", 100_000),
1113
+ ("MAX_PARSE_INTERVALS", 4096),
1114
+ ("MAX_SEGMENTS", 4096),
1115
+ ("MAX_PARSE_WORK_UNITS", 100_000),
1116
+ ("MAX_RAW_TOKEN_CODEPOINTS", 4096),
1117
+ ("MAX_CORPUS_ENTRIES", 512),
1118
+ ("MAX_CORPUS_EXISTING_SIGNALS", 8192),
1119
+ ("MAX_STRUCTURE_DEPTH", 64),
1120
+ ("MAX_STRUCTURE_NODES", 200_000),
1121
+ ("MAX_RENDER_PAGE_SIZE", 25),
1122
+ ):
1123
+ if _assignment_value(tree, name) != expected:
1124
+ errors.append(f"{RUNTIME}: {name} must equal {expected!r}")
1125
+
1126
+ aliases = _import_aliases(tree)
1127
+ for node in ast.walk(tree):
1128
+ imported: list[str] = []
1129
+ if isinstance(node, ast.Import):
1130
+ imported = [item.name for item in node.names]
1131
+ elif isinstance(node, ast.ImportFrom) and node.module:
1132
+ imported = [node.module]
1133
+ for name in imported:
1134
+ if (
1135
+ name.split(".", 1)[0] in FORBIDDEN_IMPORT_ROOTS
1136
+ or any(
1137
+ name == prefix or name.startswith(prefix + ".")
1138
+ for prefix in FORBIDDEN_IMPORT_PREFIXES
1139
+ )
1140
+ ):
1141
+ errors.append(f"{RUNTIME}: forbidden model/network/process import {name}")
1142
+ if isinstance(node, ast.Call):
1143
+ name = _qualified(node.func, aliases)
1144
+ if name in FORBIDDEN_CALLS:
1145
+ errors.append(f"{RUNTIME}: forbidden model/network/process call {name}")
1146
+ if name in FORBIDDEN_CLOCK_CALLS:
1147
+ errors.append(f"{RUNTIME}: forbidden ambient clock call {name}")
1148
+ tail = name.rsplit(".", 1)[-1] if name else None
1149
+ if tail in FORBIDDEN_PROCESS_CALL_TAILS:
1150
+ errors.append(f"{RUNTIME}: forbidden process call {name}")
1151
+ if tail in FORBIDDEN_FILE_TIME_TAILS:
1152
+ errors.append(f"{RUNTIME}: forbidden ambient file-time call {name}")
1153
+ if tail in FORBIDDEN_SCAN_TAILS:
1154
+ errors.append(f"{RUNTIME}: forbidden ambient discovery call {name}")
1155
+ if isinstance(node, ast.Attribute):
1156
+ name = _qualified(node, aliases)
1157
+ if name == "os.environ":
1158
+ errors.append(f"{RUNTIME}: ambient environment access is forbidden")
1159
+
1160
+ option_strings = {
1161
+ argument.value
1162
+ for node in ast.walk(tree)
1163
+ if isinstance(node, ast.Call)
1164
+ and isinstance(node.func, ast.Attribute)
1165
+ and node.func.attr == "add_argument"
1166
+ for argument in node.args
1167
+ if isinstance(argument, ast.Constant) and isinstance(argument.value, str)
1168
+ }
1169
+ forbidden_options = option_strings & FORBIDDEN_CLI_OPTIONS
1170
+ if forbidden_options:
1171
+ errors.append(f"{RUNTIME}: forbidden renderer options {sorted(forbidden_options)}")
1172
+ render = functions.get("render_own_draft_report")
1173
+ bounded_slice = False
1174
+ if render is not None:
1175
+ for node in ast.walk(render):
1176
+ if not isinstance(node, ast.Subscript) or not isinstance(node.slice, ast.Slice):
1177
+ continue
1178
+ if (
1179
+ isinstance(node.value, ast.Name)
1180
+ and node.value.id == "matches"
1181
+ and isinstance(node.slice.upper, ast.Name)
1182
+ and node.slice.upper.id == "MAX_RENDER_PAGE_SIZE"
1183
+ and node.slice.lower is None
1184
+ and node.slice.step is None
1185
+ ):
1186
+ bounded_slice = True
1187
+ if not bounded_slice:
1188
+ errors.append(f"{RUNTIME}: own-draft renderer must slice matches at the fixed cap")
1189
+ bounded_iteration = bool(
1190
+ render
1191
+ and any(
1192
+ isinstance(node, ast.For)
1193
+ and isinstance(node.iter, ast.Name)
1194
+ and node.iter.id == "selected"
1195
+ for node in ast.walk(render)
1196
+ )
1197
+ )
1198
+ unbounded_iteration = bool(
1199
+ render
1200
+ and any(
1201
+ isinstance(node, ast.For)
1202
+ and isinstance(node.iter, ast.Name)
1203
+ and node.iter.id == "matches"
1204
+ for node in ast.walk(render)
1205
+ )
1206
+ )
1207
+ if not bounded_iteration or unbounded_iteration:
1208
+ errors.append(f"{RUNTIME}: own-draft renderer must iterate only the fixed slice")
1209
+ limit_sites = (
1210
+ ("_minimal_witnesses", "MAX_NODE_WITNESSES", 1),
1211
+ ("_literal_witnesses", "MAX_NODE_WITNESSES", 1),
1212
+ ("evaluate_expression", "MAX_NODE_WITNESSES", 2),
1213
+ ("evaluate_expression", "MAX_NODE_COMBINATIONS", 2),
1214
+ ("_append_parse_interval", "MAX_PARSE_INTERVALS", 1),
1215
+ ("_append_opaque_opener", "MAX_PARSE_INTERVALS", 1),
1216
+ ("segment_document", "MAX_PARSE_INTERVALS", 1),
1217
+ ("tokenize", "MAX_RAW_TOKEN_CODEPOINTS", 1),
1218
+ ("build_own_draft_report", "MAX_SEGMENTS", 1),
1219
+ ("_preflight_json_structure", "MAX_STRUCTURE_DEPTH", 1),
1220
+ ("_preflight_json_structure", "MAX_STRUCTURE_NODES", 1),
1221
+ ("_preflight_yaml_structure", "MAX_STRUCTURE_DEPTH", 1),
1222
+ ("_preflight_yaml_structure", "MAX_STRUCTURE_NODES", 1),
1223
+ ("_reject_nonfinite_recursive", "MAX_STRUCTURE_DEPTH", 1),
1224
+ ("_reject_nonfinite_recursive", "MAX_STRUCTURE_NODES", 3),
1225
+ )
1226
+ for function_name, constant_name, minimum in limit_sites:
1227
+ function = functions.get(function_name)
1228
+ count = (
1229
+ _limit_comparison_count(function, constant_name)
1230
+ if function is not None
1231
+ else 0
1232
+ )
1233
+ if count < minimum:
1234
+ errors.append(
1235
+ f"{RUNTIME}: {function_name} must enforce {constant_name} "
1236
+ f"in at least {minimum} comparison(s)"
1237
+ )
1238
+ tokenize_function = functions.get("tokenize")
1239
+ raw_token_guard = (
1240
+ _strict_limit_guard(
1241
+ tokenize_function,
1242
+ "MAX_RAW_TOKEN_CODEPOINTS",
1243
+ length_of="buffer",
1244
+ )
1245
+ if tokenize_function is not None
1246
+ else None
1247
+ )
1248
+ if raw_token_guard is None:
1249
+ errors.append(
1250
+ f"{RUNTIME}: tokenize must enforce MAX_RAW_TOKEN_CODEPOINTS "
1251
+ "with the strict N/N+1 guard"
1252
+ )
1253
+ enricher = functions.get("enrich_passport")
1254
+ strict_json = functions.get("_strict_json_bytes")
1255
+ structure_guard = functions.get("_reject_nonfinite_recursive")
1256
+ if structure_guard is None:
1257
+ errors.append(f"{RUNTIME}: missing bounded iterative structure guard")
1258
+ if strict_json is None or not _call_lines(
1259
+ strict_json, aliases, "_reject_nonfinite_recursive"
1260
+ ):
1261
+ errors.append(f"{RUNTIME}: strict JSON loader must apply the structure guard")
1262
+ if enricher is None or not _call_lines(
1263
+ enricher, aliases, "_reject_nonfinite_recursive"
1264
+ ):
1265
+ errors.append(f"{RUNTIME}: direct passport enricher must apply the structure guard")
1266
+ entry_guard = (
1267
+ _strict_limit_guard(
1268
+ enricher,
1269
+ "MAX_CORPUS_ENTRIES",
1270
+ length_of="corpus",
1271
+ )
1272
+ if enricher is not None
1273
+ else None
1274
+ )
1275
+ signal_guard = (
1276
+ _strict_limit_guard(
1277
+ enricher,
1278
+ "MAX_CORPUS_EXISTING_SIGNALS",
1279
+ value_name="existing_signal_count",
1280
+ )
1281
+ if enricher is not None
1282
+ else None
1283
+ )
1284
+ if entry_guard is None:
1285
+ errors.append(
1286
+ f"{RUNTIME}: enrich_passport must enforce MAX_CORPUS_ENTRIES "
1287
+ "with the strict N/N+1 guard"
1288
+ )
1289
+ if signal_guard is None:
1290
+ errors.append(
1291
+ f"{RUNTIME}: enrich_passport must enforce "
1292
+ "MAX_CORPUS_EXISTING_SIGNALS with the strict N/N+1 guard"
1293
+ )
1294
+ if enricher is not None and not _existing_signal_count_is_aggregate_sum(enricher):
1295
+ errors.append(
1296
+ f"{RUNTIME}: existing_signal_count must aggregate every pre-existing "
1297
+ "bibliographic_integrity_signals row"
1298
+ )
1299
+ copy_lines = (
1300
+ _call_lines(enricher, aliases, "copy.deepcopy")
1301
+ if enricher is not None
1302
+ else []
1303
+ )
1304
+ if (
1305
+ len(copy_lines) != 1
1306
+ or entry_guard is None
1307
+ or signal_guard is None
1308
+ or (entry_guard.end_lineno or entry_guard.lineno) >= copy_lines[0]
1309
+ or (signal_guard.end_lineno or signal_guard.lineno) >= copy_lines[0]
1310
+ ):
1311
+ errors.append(
1312
+ f"{RUNTIME}: both corpus cardinality guards must run before "
1313
+ "copy.deepcopy and matching"
1314
+ )
1315
+ if enricher is not None and any(
1316
+ _call_lines(enricher, aliases, writer)
1317
+ for writer in ("_atomic_write_passport", "_atomic_write_json", "_atomic_write_bytes")
1318
+ ):
1319
+ errors.append(f"{RUNTIME}: enrich_passport must not mutate output paths")
1320
+
1321
+ main_function = functions.get("main")
1322
+ enrich_lines = (
1323
+ _call_lines(main_function, aliases, "enrich_passport")
1324
+ if main_function is not None
1325
+ else []
1326
+ )
1327
+ passport_write_lines = (
1328
+ _call_lines(main_function, aliases, "_atomic_write_passport")
1329
+ if main_function is not None
1330
+ else []
1331
+ )
1332
+ if (
1333
+ len(enrich_lines) != 1
1334
+ or len(passport_write_lines) != 1
1335
+ or passport_write_lines[0] <= enrich_lines[0]
1336
+ ):
1337
+ errors.append(
1338
+ f"{RUNTIME}: main must write the passport only after enrich_passport "
1339
+ "returns successfully"
1340
+ )
1341
+ cited_builder = functions.get("build_cited_signal")
1342
+ if cited_builder is None or not _dict_binds_name(
1343
+ cited_builder, "summary_label", "ADVISORY_LABEL"
1344
+ ):
1345
+ errors.append(
1346
+ f"{RUNTIME}: build_cited_signal must bind summary_label to ADVISORY_LABEL"
1347
+ )
1348
+ own_builder = functions.get("build_own_draft_report")
1349
+ if own_builder is None or "DOCUMENT_EMPTY" not in _string_literals(own_builder):
1350
+ errors.append(f"{RUNTIME}: empty draft must emit DOCUMENT_EMPTY")
1351
+ cited_surface = functions.get("_cited_surface_result")
1352
+ if cited_surface is None or "ABSTRACT_EMPTY" not in _string_literals(cited_surface):
1353
+ errors.append(f"{RUNTIME}: empty abstract must emit ABSTRACT_EMPTY")
1354
+ for name in ("build_own_draft_report", "enrich_passport"):
1355
+ function = functions.get(name)
1356
+ if function is not None and not {"checked_at", "recorded_at"}.issubset(
1357
+ _arg_names(function)
1358
+ ):
1359
+ errors.append(f"{RUNTIME}: {name} requires explicit checked_at/recorded_at")
1360
+ for token in (
1361
+ "A match does not establish papermill, AI, or author origin",
1362
+ "not a clean-text certificate",
1363
+ "one fixed page capped at",
1364
+ ):
1365
+ if token not in source:
1366
+ errors.append(f"{RUNTIME}: missing claim/render boundary {token!r}")
1367
+ return errors
1368
+
1369
+
1370
+ def _frozen_runtime_errors(root: Path) -> list[str]:
1371
+ """Bind every executable #660 projection surface to reviewed exact bytes."""
1372
+
1373
+ errors: list[str] = []
1374
+ for relative, expected in FROZEN_RUNTIME_SHA256.items():
1375
+ try:
1376
+ actual = hashlib.sha256((root / relative).read_bytes()).hexdigest()
1377
+ except OSError as exc:
1378
+ errors.append(f"{relative}: cannot read frozen runtime bytes: {exc}")
1379
+ continue
1380
+ if actual != expected:
1381
+ errors.append(
1382
+ f"{relative}: frozen runtime sha256 drifted; "
1383
+ f"expected {expected}, got {actual}"
1384
+ )
1385
+ return errors
1386
+
1387
+
1388
+ def _text_binding_errors(root: Path) -> list[str]:
1389
+ errors: list[str] = []
1390
+ for relative, tokens in {**REQUIRED_DOC_TOKENS, **REQUIRED_CONSUMER_TOKENS}.items():
1391
+ try:
1392
+ text = (root / relative).read_text(encoding="utf-8")
1393
+ except (OSError, UnicodeError) as exc:
1394
+ errors.append(f"{relative}: cannot read: {exc}")
1395
+ continue
1396
+ missing = [token for token in tokens if token not in text]
1397
+ if missing:
1398
+ errors.append(f"{relative}: missing #660 integration tokens {missing}")
1399
+ return errors
1400
+
1401
+
1402
+ def _consumer_ast_errors(root: Path) -> list[str]:
1403
+ errors: list[str] = []
1404
+ try:
1405
+ tree = ast.parse(
1406
+ (root / CORPUS_CHECKER).read_text(encoding="utf-8"),
1407
+ filename=str(CORPUS_CHECKER),
1408
+ )
1409
+ except (OSError, UnicodeError, SyntaxError) as exc:
1410
+ return [f"{CORPUS_CHECKER}: cannot parse consumer binding: {exc}"]
1411
+ calls = [
1412
+ node
1413
+ for node in ast.walk(tree)
1414
+ if isinstance(node, ast.Call)
1415
+ and isinstance(node.func, ast.Name)
1416
+ and node.func.id == "validate_cited_signal_binding"
1417
+ ]
1418
+ if len(calls) != 1:
1419
+ errors.append(
1420
+ f"{CORPUS_CHECKER}: must call validate_cited_signal_binding exactly once"
1421
+ )
1422
+ return errors
1423
+
1424
+
1425
+ def _squash_whitespace(value: str) -> str:
1426
+ return " ".join(value.split())
1427
+
1428
+
1429
+ def _measurement_plan_errors(root: Path) -> list[str]:
1430
+ errors: list[str] = []
1431
+ try:
1432
+ registry = _load_json(root / SUITE_REGISTRY)
1433
+ except (OSError, UnicodeError, ValueError, DuplicateKeyError) as exc:
1434
+ errors.append(f"{SUITE_REGISTRY}: cannot load strict registry JSON: {exc}")
1435
+ else:
1436
+ if registry.get("tortured_phrase_conformance") != "mechanical_match":
1437
+ errors.append(
1438
+ f"{SUITE_REGISTRY}: tortured_phrase_conformance must map exactly "
1439
+ "to mechanical_match"
1440
+ )
1441
+
1442
+ texts: dict[Path, str] = {}
1443
+ for relative in (CONFORMANCE_README, MEASUREMENT_PLAN, MEASUREMENT_CONTRACT):
1444
+ try:
1445
+ texts[relative] = (root / relative).read_text(encoding="utf-8")
1446
+ except (OSError, UnicodeError) as exc:
1447
+ errors.append(f"{relative}: cannot read frozen measurement plan binding: {exc}")
1448
+
1449
+ contract = texts.get(MEASUREMENT_CONTRACT, "")
1450
+ mirror_prefix = "| `tortured_phrase_conformance` | `mechanical_match` |"
1451
+ if contract.count(mirror_prefix) != 1:
1452
+ errors.append(
1453
+ f"{MEASUREMENT_CONTRACT}: registry mirror must contain exactly one "
1454
+ "tortured_phrase_conformance/mechanical_match row"
1455
+ )
1456
+
1457
+ plan = _squash_whitespace(texts.get(MEASUREMENT_PLAN, ""))
1458
+ plan_tokens = (
1459
+ "Status: PRE-REGISTERED / NOT RUN",
1460
+ "first commit reachable",
1461
+ "use that same 40-hex main-history commit for both "
1462
+ "`subject.config.suite_commit` and "
1463
+ "`preregistration.frozen_commit`",
1464
+ "No retry is permitted",
1465
+ "Primary metric: `synthetic_conformance_test_pass_rate`",
1466
+ "It uses zero judges, no agreement statistic, no adjudication, and no "
1467
+ "experimental arms",
1468
+ "A passing row may say only: “the pinned deterministic runtime passed the "
1469
+ "pinned repository-owned synthetic conformance suite.”",
1470
+ "It remains `UNMEASURED` for contextual validity and real-world "
1471
+ "false-positive/false-negative performance",
1472
+ "It cannot certify clean text or infer paper-mill, AI, misconduct, "
1473
+ "contamination, quality, acceptance, or origin",
1474
+ )
1475
+ missing_plan = [token for token in plan_tokens if token not in plan]
1476
+ if missing_plan:
1477
+ errors.append(f"{MEASUREMENT_PLAN}: frozen plan tokens drifted {missing_plan}")
1478
+
1479
+ readme = _squash_whitespace(texts.get(CONFORMANCE_README, ""))
1480
+ readme_tokens = (
1481
+ f"The frozen post-main measurement was executed once on 2026-08-10 "
1482
+ f"against commit `{FROZEN_MAIN_SHA}`",
1483
+ "190 of 190 collected tests passed",
1484
+ "uses zero judges",
1485
+ "exact execution evidence",
1486
+ "The supported conclusion is only that the pinned deterministic runtime "
1487
+ "passed the pinned repository-owned synthetic conformance suite",
1488
+ "real-world false-positive/false-negative performance remain `UNMEASURED`",
1489
+ "contextual false-positive/false-negative labels",
1490
+ "not empirical false-positive or false-negative rates",
1491
+ "only a synthetic grammar/normalization/parser/replay conformance statement",
1492
+ )
1493
+ missing_readme = [token for token in readme_tokens if token not in readme]
1494
+ if missing_readme:
1495
+ errors.append(
1496
+ f"{CONFORMANCE_README}: UNMEASURED/contextual claim ceiling drifted "
1497
+ f"{missing_readme}"
1498
+ )
1499
+ return errors
1500
+
1501
+
1502
+ def _json_values_equal(actual: Any, expected: Any) -> bool:
1503
+ """Compare JSON values without Python's bool/int or int/float coercions."""
1504
+
1505
+ if type(actual) is not type(expected):
1506
+ return False
1507
+ if isinstance(actual, dict):
1508
+ return set(actual) == set(expected) and all(
1509
+ _json_values_equal(actual[key], expected[key]) for key in actual
1510
+ )
1511
+ if isinstance(actual, list):
1512
+ return len(actual) == len(expected) and all(
1513
+ _json_values_equal(left, right)
1514
+ for left, right in zip(actual, expected, strict=True)
1515
+ )
1516
+ return bool(actual == expected)
1517
+
1518
+
1519
+ def _exact_frozen_object_errors(
1520
+ actual: dict[str, Any],
1521
+ expected: dict[str, Any],
1522
+ label: Path,
1523
+ ) -> list[str]:
1524
+ """Compare a closed evidence object while keeping diagnostics field-local."""
1525
+
1526
+ errors: list[str] = []
1527
+ actual_keys = set(actual)
1528
+ expected_keys = set(expected)
1529
+ if actual_keys != expected_keys:
1530
+ errors.append(
1531
+ f"{label}: closed field set drifted; expected "
1532
+ f"{sorted(expected_keys)}, got {sorted(actual_keys)}"
1533
+ )
1534
+ for field in sorted(actual_keys & expected_keys):
1535
+ if not _json_values_equal(actual[field], expected[field]):
1536
+ errors.append(f"{label}: frozen field {field!r} drifted")
1537
+ return errors
1538
+
1539
+
1540
+ def _canonical_json_bytes(value: dict[str, Any]) -> bytes:
1541
+ return (
1542
+ json.dumps(
1543
+ value,
1544
+ ensure_ascii=False,
1545
+ sort_keys=True,
1546
+ separators=(",", ":"),
1547
+ allow_nan=False,
1548
+ ).encode("utf-8")
1549
+ + b"\n"
1550
+ )
1551
+
1552
+
1553
+ def _walk_heldout_json_files(root: Path) -> tuple[list[Path], list[str]]:
1554
+ """Mirror held-out discovery for the closed one-row #660 cardinality rule."""
1555
+
1556
+ heldout = root / HELDOUT_ROOT
1557
+ found: list[Path] = []
1558
+ walk_errors: list[str] = []
1559
+ visited: set[Path] = set()
1560
+ repo_real = root.resolve()
1561
+ heldout_real = heldout.resolve()
1562
+
1563
+ def walk(directory: Path) -> None:
1564
+ try:
1565
+ real = directory.resolve()
1566
+ except OSError as exc:
1567
+ walk_errors.append(f"{directory}: cannot resolve directory: {exc}")
1568
+ return
1569
+ if real in visited:
1570
+ return
1571
+ if not (real.is_relative_to(heldout_real) or real.is_relative_to(repo_real)):
1572
+ walk_errors.append(
1573
+ f"{directory}: symlinked directory resolves outside the repository"
1574
+ )
1575
+ return
1576
+ visited.add(real)
1577
+ try:
1578
+ entries = sorted(os.scandir(directory), key=lambda entry: entry.name)
1579
+ except OSError as exc:
1580
+ walk_errors.append(f"{directory}: unreadable directory: {exc}")
1581
+ return
1582
+ for entry in entries:
1583
+ path = directory / entry.name
1584
+ try:
1585
+ is_dir = entry.is_dir(follow_symlinks=True)
1586
+ except OSError:
1587
+ is_dir = False
1588
+ if is_dir:
1589
+ walk(path)
1590
+ continue
1591
+ if path.suffix.lower() != ".json":
1592
+ continue
1593
+ try:
1594
+ file_real = path.resolve()
1595
+ except OSError as exc:
1596
+ walk_errors.append(f"{path}: cannot resolve JSON file: {exc}")
1597
+ continue
1598
+ if not (
1599
+ file_real.is_relative_to(heldout_real)
1600
+ or file_real.is_relative_to(repo_real)
1601
+ ):
1602
+ walk_errors.append(
1603
+ f"{path}: file symlink resolves outside the repository"
1604
+ )
1605
+ continue
1606
+ found.append(path)
1607
+
1608
+ if heldout.exists():
1609
+ walk(heldout)
1610
+ return found, walk_errors
1611
+
1612
+
1613
+ def _expected_measurement_transcript() -> dict[str, Any]:
1614
+ return {
1615
+ "schema_version": "tortured-phrase-conformance-transcript/1.0",
1616
+ "command_utf8": MEASUREMENT_COMMAND,
1617
+ "started_at": MEASUREMENT_STARTED_AT,
1618
+ "completed_at": MEASUREMENT_COMPLETED_AT,
1619
+ "exit_code": 0,
1620
+ "environment": {
1621
+ "python_implementation": "CPython",
1622
+ "python_version": "3.11.15",
1623
+ "pytest_version": "9.0.3",
1624
+ "jsonschema_version": "4.26.0",
1625
+ "ruamel_yaml_version": "0.17.21",
1626
+ },
1627
+ "stdout_utf8": (
1628
+ "........................................................................ "
1629
+ "[ 37%]\n"
1630
+ "........................................................................ "
1631
+ "[ 75%]\n"
1632
+ ".............................................. "
1633
+ "[100%]\n"
1634
+ "190 passed in 4.28s\n"
1635
+ ),
1636
+ "stderr_utf8": "",
1637
+ }
1638
+
1639
+
1640
+ def _expected_execution_manifest() -> dict[str, Any]:
1641
+ return {
1642
+ "schema_version": "heldout-execution-manifest/1.0",
1643
+ "suite": "tortured_phrase_conformance",
1644
+ "created_at": MEASUREMENT_COMPLETED_AT,
1645
+ "write_once": True,
1646
+ "calls": [
1647
+ {
1648
+ "call_id": "tpc-2026-08-10-pytest",
1649
+ "sequence_index": 1,
1650
+ "started_at": MEASUREMENT_STARTED_AT,
1651
+ "completed_at": MEASUREMENT_COMPLETED_AT,
1652
+ "prompt_sha256": MEASUREMENT_COMMAND_SHA256,
1653
+ "output_sha256": MEASUREMENT_TRANSCRIPT_SHA256,
1654
+ "attempt": 1,
1655
+ }
1656
+ ],
1657
+ }
1658
+
1659
+
1660
+ def _expected_measurement_report(manifest_sha256: str) -> dict[str, Any]:
1661
+ return {
1662
+ "measurement_contract": "heldout-measurement/1.1",
1663
+ "suite": "tortured_phrase_conformance",
1664
+ "suite_class": "mechanical_match",
1665
+ "measurement_date": "2026-08-10",
1666
+ "decision_relevant": True,
1667
+ "subject": {
1668
+ "model_id": "deterministic-runtime/tortured_phrase_screening.py",
1669
+ "config": {"suite_commit": FROZEN_MAIN_SHA},
1670
+ },
1671
+ "judge_plan": {"exception": "mechanical_suite"},
1672
+ "judges": [],
1673
+ "aggregate": {
1674
+ "headline": {
1675
+ "metric_name": "synthetic_conformance_test_pass_rate",
1676
+ "value": 1.0,
1677
+ "construction_rule": (
1678
+ "passed_tests divided by collected_tests only when exit_status "
1679
+ "is 0, all collected tests pass, and failed, error, skipped, "
1680
+ "xfailed, and xpassed counts are zero."
1681
+ ),
1682
+ "estimand_status": "point_estimate",
1683
+ },
1684
+ "agreement": {
1685
+ "rate": None,
1686
+ "divergent_items": [],
1687
+ "note": (
1688
+ "No judges are used for this mechanical suite, so agreement "
1689
+ "is not applicable."
1690
+ ),
1691
+ },
1692
+ },
1693
+ "replicates": {
1694
+ "per_item": 1,
1695
+ "rule_ref": (
1696
+ "evals/heldout/tortured_phrase_conformance/measurement_plan.md"
1697
+ "#frozen-metric-and-verdict"
1698
+ ),
1699
+ "spread": None,
1700
+ "exception": (
1701
+ "The deterministic exact-byte replay is not rerun to manufacture "
1702
+ "variance."
1703
+ ),
1704
+ },
1705
+ "adjudication": {"applies": False},
1706
+ "preregistration": {
1707
+ "plan_ref": str(MEASUREMENT_PLAN),
1708
+ "plan_sha256": FROZEN_PLAN_SHA256,
1709
+ "frozen_commit": FROZEN_MAIN_SHA,
1710
+ "frozen_before_dispatch": True,
1711
+ "rubric_and_plan_frozen_together": True,
1712
+ "amendments_append_only": True,
1713
+ "amendments": [],
1714
+ },
1715
+ "execution_manifest": {
1716
+ "ref": str(MEASUREMENT_EXECUTION_MANIFEST),
1717
+ "sha256": manifest_sha256,
1718
+ "write_once": True,
1719
+ "claims": [],
1720
+ },
1721
+ "attempts": {
1722
+ "atomicity": (
1723
+ "The exact registered command was dispatched once, with no retry "
1724
+ "permitted."
1725
+ ),
1726
+ "partial_published": False,
1727
+ "blocked_runs": [],
1728
+ },
1729
+ "raw_outputs": {
1730
+ "retained": True,
1731
+ "paths": [str(MEASUREMENT_TRANSCRIPT)],
1732
+ },
1733
+ "results": {
1734
+ "design": "single-arm deterministic synthetic conformance",
1735
+ "arm_roles": {
1736
+ "treatment_or_cohort_arms": [],
1737
+ "variant_packet_arms": [],
1738
+ },
1739
+ "passed_tests": 190,
1740
+ "collected_tests": 190,
1741
+ "exit_status": 0,
1742
+ "synthetic_conformance_test_pass_rate": 1.0,
1743
+ },
1744
+ "verdict": (
1745
+ "The pinned deterministic runtime passed the pinned repository-owned "
1746
+ "synthetic conformance suite."
1747
+ ),
1748
+ "caveats": [
1749
+ "Contextual validity and real-world false-positive/false-negative "
1750
+ "performance remain UNMEASURED.",
1751
+ "This result cannot certify clean text or infer paper-mill, AI, "
1752
+ "misconduct, contamination, quality, acceptance, or origin.",
1753
+ ],
1754
+ }
1755
+
1756
+
1757
+ def _measurement_errors(root: Path) -> list[str]:
1758
+ """Bind the one audited #660 measurement row and its exact evidence chain.
1759
+
1760
+ ``FROZEN_MAIN_SHA`` is the commit whose main ancestry and pre-dispatch freeze
1761
+ were established by the human/git-history audit. This integration checker
1762
+ deliberately remains process-free. The shared held-out report checker owns
1763
+ the separate R3/R4 Git-object existence checks; here both commit fields are
1764
+ closed to that audited object so neither can drift independently.
1765
+ """
1766
+
1767
+ errors: list[str] = []
1768
+ values: dict[Path, dict[str, Any]] = {}
1769
+ raw_bytes: dict[Path, bytes] = {}
1770
+ for relative in (
1771
+ MEASUREMENT_REPORT,
1772
+ MEASUREMENT_TRANSCRIPT,
1773
+ MEASUREMENT_EXECUTION_MANIFEST,
1774
+ ):
1775
+ try:
1776
+ value, raw = _load_json_bytes(root / relative)
1777
+ except (OSError, UnicodeError, ValueError, DuplicateKeyError) as exc:
1778
+ errors.append(
1779
+ f"{relative}: cannot load canonical #660 measurement artifact: {exc}"
1780
+ )
1781
+ else:
1782
+ values[relative] = value
1783
+ raw_bytes[relative] = raw
1784
+
1785
+ heldout_files, walk_errors = _walk_heldout_json_files(root)
1786
+ errors.extend(f"{HELDOUT_ROOT}: #660 row discovery failed: {error}" for error in walk_errors)
1787
+ for path in heldout_files:
1788
+ relative = path.relative_to(root)
1789
+ if relative in {
1790
+ MEASUREMENT_REPORT,
1791
+ MEASUREMENT_TRANSCRIPT,
1792
+ MEASUREMENT_EXECUTION_MANIFEST,
1793
+ }:
1794
+ continue
1795
+ try:
1796
+ candidate, _ = _load_json_bytes(path)
1797
+ except (OSError, UnicodeError, ValueError, DuplicateKeyError) as exc:
1798
+ if "tortured_phrase_conformance" in path.parts:
1799
+ errors.append(
1800
+ f"{relative}: cannot inspect the closed #660 row set: {exc}"
1801
+ )
1802
+ continue
1803
+ if "measurement_contract" in candidate and (
1804
+ candidate.get("suite") == "tortured_phrase_conformance"
1805
+ or "tortured_phrase_conformance" in path.parts
1806
+ ):
1807
+ errors.append(
1808
+ f"{relative}: second #660 measurement row is forbidden; "
1809
+ f"the only canonical row is {MEASUREMENT_REPORT}"
1810
+ )
1811
+
1812
+ try:
1813
+ plan_sha256 = hashlib.sha256((root / MEASUREMENT_PLAN).read_bytes()).hexdigest()
1814
+ except OSError as exc:
1815
+ errors.append(f"{MEASUREMENT_PLAN}: cannot hash frozen plan bytes: {exc}")
1816
+ else:
1817
+ if plan_sha256 != FROZEN_PLAN_SHA256:
1818
+ errors.append(
1819
+ f"{MEASUREMENT_PLAN}: frozen plan sha256 drifted; expected "
1820
+ f"{FROZEN_PLAN_SHA256}, got {plan_sha256}"
1821
+ )
1822
+
1823
+ command_sha256 = hashlib.sha256(MEASUREMENT_COMMAND.encode("utf-8")).hexdigest()
1824
+ if command_sha256 != MEASUREMENT_COMMAND_SHA256:
1825
+ errors.append(
1826
+ "#660 registered command bytes no longer match "
1827
+ f"MEASUREMENT_COMMAND_SHA256 {MEASUREMENT_COMMAND_SHA256}"
1828
+ )
1829
+
1830
+ transcript = values.get(MEASUREMENT_TRANSCRIPT)
1831
+ transcript_raw = raw_bytes.get(MEASUREMENT_TRANSCRIPT)
1832
+ if transcript is not None and transcript_raw is not None:
1833
+ canonical_transcript = _canonical_json_bytes(transcript)
1834
+ if transcript_raw != canonical_transcript:
1835
+ errors.append(
1836
+ f"{MEASUREMENT_TRANSCRIPT}: bytes must be canonical sorted compact "
1837
+ "JSON with exactly one terminal LF"
1838
+ )
1839
+ transcript_sha256 = hashlib.sha256(transcript_raw).hexdigest()
1840
+ if transcript_sha256 != MEASUREMENT_TRANSCRIPT_SHA256:
1841
+ errors.append(
1842
+ f"{MEASUREMENT_TRANSCRIPT}: frozen transcript sha256 drifted; "
1843
+ f"expected {MEASUREMENT_TRANSCRIPT_SHA256}, got {transcript_sha256}"
1844
+ )
1845
+ errors.extend(
1846
+ _exact_frozen_object_errors(
1847
+ transcript,
1848
+ _expected_measurement_transcript(),
1849
+ MEASUREMENT_TRANSCRIPT,
1850
+ )
1851
+ )
1852
+
1853
+ manifest = values.get(MEASUREMENT_EXECUTION_MANIFEST)
1854
+ manifest_raw = raw_bytes.get(MEASUREMENT_EXECUTION_MANIFEST)
1855
+ manifest_sha256 = ""
1856
+ if manifest is not None and manifest_raw is not None:
1857
+ if manifest_raw != _canonical_json_bytes(manifest):
1858
+ errors.append(
1859
+ f"{MEASUREMENT_EXECUTION_MANIFEST}: bytes must be canonical sorted "
1860
+ "compact JSON with exactly one terminal LF"
1861
+ )
1862
+ manifest_sha256 = hashlib.sha256(manifest_raw).hexdigest()
1863
+ if manifest_sha256 != MEASUREMENT_EXECUTION_MANIFEST_SHA256:
1864
+ errors.append(
1865
+ f"{MEASUREMENT_EXECUTION_MANIFEST}: frozen manifest sha256 drifted; "
1866
+ f"expected {MEASUREMENT_EXECUTION_MANIFEST_SHA256}, got "
1867
+ f"{manifest_sha256}"
1868
+ )
1869
+ errors.extend(
1870
+ _exact_frozen_object_errors(
1871
+ manifest,
1872
+ _expected_execution_manifest(),
1873
+ MEASUREMENT_EXECUTION_MANIFEST,
1874
+ )
1875
+ )
1876
+
1877
+ report = values.get(MEASUREMENT_REPORT)
1878
+ report_raw = raw_bytes.get(MEASUREMENT_REPORT)
1879
+ if report is not None and report_raw is not None:
1880
+ if report_raw != _canonical_json_bytes(report):
1881
+ errors.append(
1882
+ f"{MEASUREMENT_REPORT}: bytes must be canonical sorted compact JSON "
1883
+ "with exactly one terminal LF"
1884
+ )
1885
+ report_sha256 = hashlib.sha256(report_raw).hexdigest()
1886
+ if report_sha256 != MEASUREMENT_REPORT_SHA256:
1887
+ errors.append(
1888
+ f"{MEASUREMENT_REPORT}: frozen report sha256 drifted; expected "
1889
+ f"{MEASUREMENT_REPORT_SHA256}, got {report_sha256}"
1890
+ )
1891
+ if report is not None and manifest_sha256:
1892
+ errors.extend(
1893
+ _exact_frozen_object_errors(
1894
+ report,
1895
+ _expected_measurement_report(manifest_sha256),
1896
+ MEASUREMENT_REPORT,
1897
+ )
1898
+ )
1899
+ return errors
1900
+
1901
+
1902
+ def _ci_errors(root: Path) -> list[str]:
1903
+ errors: list[str] = []
1904
+ try:
1905
+ with (root / CI_MANIFEST).open("rb") as handle:
1906
+ manifest = tomllib.load(handle)
1907
+ except (OSError, tomllib.TOMLDecodeError) as exc:
1908
+ errors.append(f"{CI_MANIFEST}: cannot load: {exc}")
1909
+ manifest = {}
1910
+ entries = manifest.get("pytest", [])
1911
+ expected = {
1912
+ "660-tortured-phrase-screening": str(RUNTIME_TEST),
1913
+ "660-tortured-phrase-integration": "scripts/test_check_tortured_phrase_screening_integration.py",
1914
+ }
1915
+ for identifier, path in expected.items():
1916
+ matches = [
1917
+ item
1918
+ for item in entries
1919
+ if isinstance(item, dict) and item.get("id") == identifier
1920
+ ]
1921
+ if len(matches) != 1 or matches[0].get("path") != path:
1922
+ errors.append(f"{CI_MANIFEST}: missing exact {identifier!r} -> {path!r} binding")
1923
+ if not (root / path).is_file():
1924
+ errors.append(f"{CI_MANIFEST}: bound test path does not exist: {path}")
1925
+ try:
1926
+ workflow = (root / WORKFLOW).read_text(encoding="utf-8")
1927
+ except (OSError, UnicodeError) as exc:
1928
+ errors.append(f"{WORKFLOW}: cannot read: {exc}")
1929
+ workflow = ""
1930
+ command = "python3 scripts/check_tortured_phrase_screening_integration.py"
1931
+ if workflow.count(command) != 1:
1932
+ errors.append(f"{WORKFLOW}: direct #660 integration checker must run exactly once")
1933
+ if "python3 scripts/run_ci_pytest_manifest.py" not in workflow:
1934
+ errors.append(f"{WORKFLOW}: unified pytest-manifest runner binding is missing")
1935
+ return errors
1936
+
1937
+
1938
+ def run_checks(root: Path = REPO_ROOT) -> list[str]:
1939
+ """Return stable, de-duplicated integration errors for ``root``."""
1940
+
1941
+ errors = [
1942
+ *_schema_errors(root),
1943
+ *_fixture_errors(root),
1944
+ *_frozen_runtime_errors(root),
1945
+ *_runtime_errors(root),
1946
+ *_text_binding_errors(root),
1947
+ *_consumer_ast_errors(root),
1948
+ *_measurement_plan_errors(root),
1949
+ *_measurement_errors(root),
1950
+ *_ci_errors(root),
1951
+ ]
1952
+ return sorted(set(errors))
1953
+
1954
+
1955
+ def main(argv: list[str] | None = None) -> int:
1956
+ parser = argparse.ArgumentParser(description=__doc__)
1957
+ parser.add_argument(
1958
+ "--root", type=Path, default=REPO_ROOT, help="Repository root to inspect."
1959
+ )
1960
+ try:
1961
+ args = parser.parse_args(argv)
1962
+ except SystemExit as exc:
1963
+ return int(exc.code)
1964
+ errors = run_checks(args.root)
1965
+ if errors:
1966
+ for error in errors:
1967
+ print(f"ERROR: {error}", file=sys.stderr)
1968
+ return 1
1969
+ print("#660 tortured-phrase screening integration: ok")
1970
+ return 0
1971
+
1972
+
1973
+ if __name__ == "__main__":
1974
+ raise SystemExit(main())