arbiter-engine 0.2.4__tar.gz → 0.2.6__tar.gz

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 (330) hide show
  1. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/workflows/release.yml +3 -3
  2. arbiter_engine-0.2.6/.github/workflows/tests.yml +292 -0
  3. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/BRIDGES.md +68 -0
  4. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/CHANGELOG.md +1341 -1
  5. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/CITATION.cff +2 -2
  6. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/COMPATIBILITY.md +84 -12
  7. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/MODELING.md +506 -12
  8. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/PKG-INFO +175 -33
  9. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/README.md +174 -32
  10. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/ROADMAP.md +26 -1
  11. arbiter_engine-0.2.6/STANCE.md +115 -0
  12. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/__init__.py +2 -0
  13. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/api.py +657 -45
  14. arbiter_engine-0.2.6/arbiter_engine/assumptions.py +282 -0
  15. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/axiom_thresholds.py +1 -1
  16. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/causal/leadlag.py +21 -5
  17. arbiter_engine-0.2.6/arbiter_engine/examples/pump_tank_dynamics.yaml +132 -0
  18. arbiter_engine-0.2.6/arbiter_engine/examples/pump_tank_planning.yaml +162 -0
  19. arbiter_engine-0.2.6/arbiter_engine/examples/substation_feeder.yaml +138 -0
  20. arbiter_engine-0.2.6/arbiter_engine/examples/substation_feeder_surprises.yaml +120 -0
  21. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/fire_frequency.py +33 -5
  22. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/contract.py +2 -1
  23. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/shadow.py +8 -6
  24. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/observation_production.py +21 -2
  25. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/inference/runner.py +74 -13
  26. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/interfaces.py +4 -4
  27. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/mcp/server.py +74 -37
  28. arbiter_engine-0.2.6/arbiter_engine/ontology/__init__.py +72 -0
  29. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/homeostasis.py +9 -1
  30. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/domain_loader.py +382 -16
  31. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/entail.py +103 -5
  32. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/loader.py +179 -30
  33. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/reasoner.py +7 -4
  34. arbiter_engine-0.2.6/arbiter_engine/ontology/schemas/health_meta_ontology.ttl +260 -0
  35. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/projection/projector.py +12 -1
  36. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/projection/runner.py +41 -4
  37. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/impact_estimator.py +1 -1
  38. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/residual/predict_vs_mirror.py +490 -82
  39. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6/arbiter_engine}/schema/envelope.schema.json +230 -2
  40. arbiter_engine-0.2.6/arbiter_engine/scripts/surprise_benchmark.py +167 -0
  41. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/subenvelope.py +107 -31
  42. arbiter_engine-0.2.6/arbiter_engine/surprises.py +578 -0
  43. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/temporal/temporal_edge.py +56 -6
  44. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/action_clears_problem.py +1 -1
  45. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/actions.py +56 -5
  46. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/builder.py +150 -16
  47. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/hypothesis_generator.py +1 -1
  48. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/hypothesis_production.py +2 -2
  49. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/kernel_pipeline_executor.py +1 -1
  50. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/monte_carlo_predictor.py +33 -50
  51. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/optimization_production.py +2 -2
  52. arbiter_engine-0.2.6/arbiter_engine/twin/planner.py +850 -0
  53. arbiter_engine-0.2.6/arbiter_engine/twin/rollout.py +1571 -0
  54. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/topology.py +285 -4
  55. arbiter_engine-0.2.6/arbiter_engine/twin/transition_learner.py +439 -0
  56. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/traverser.py +840 -57
  57. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/traverser_production.py +2 -2
  58. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/types.py +64 -1
  59. arbiter_engine-0.2.6/examples/pump_tank_dynamics.yaml +132 -0
  60. arbiter_engine-0.2.6/examples/pump_tank_planning.yaml +162 -0
  61. arbiter_engine-0.2.6/examples/substation_feeder.yaml +138 -0
  62. arbiter_engine-0.2.6/examples/substation_feeder_surprises.yaml +120 -0
  63. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/pyproject.toml +1 -1
  64. {arbiter_engine-0.2.4/arbiter_engine → arbiter_engine-0.2.6}/schema/envelope.schema.json +230 -2
  65. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/conftest.py +41 -0
  66. arbiter_engine-0.2.6/tests/test_a_calibration_says_how_many_trajectories_it_saw.py +217 -0
  67. arbiter_engine-0.2.6/tests/test_a_chain_of_lags_says_how_it_was_composed.py +200 -0
  68. arbiter_engine-0.2.6/tests/test_a_changelog_section_says_whether_you_can_install_it.py +135 -0
  69. arbiter_engine-0.2.6/tests/test_a_clean_rollout_still_counts_what_it_evaluated.py +133 -0
  70. arbiter_engine-0.2.6/tests/test_a_companion_beside_the_models_is_not_one.py +159 -0
  71. arbiter_engine-0.2.6/tests/test_a_correct_gain_is_not_contradicted_by_a_lagged_series.py +198 -0
  72. arbiter_engine-0.2.6/tests/test_a_coupling_block_is_checked_too.py +315 -0
  73. arbiter_engine-0.2.6/tests/test_a_coupling_is_graded_on_its_own_projections.py +249 -0
  74. arbiter_engine-0.2.6/tests/test_a_coupling_learns_how_its_projections_fared.py +227 -0
  75. arbiter_engine-0.2.6/tests/test_a_declared_offset_waits_for_the_delay.py +125 -0
  76. arbiter_engine-0.2.6/tests/test_a_declared_source_matches_the_guide.py +81 -0
  77. arbiter_engine-0.2.6/tests/test_a_declared_spread_reaches_the_value.py +178 -0
  78. arbiter_engine-0.2.6/tests/test_a_decline_states_the_number_it_computed.py +142 -0
  79. arbiter_engine-0.2.6/tests/test_a_forecast_is_graded_at_its_horizon.py +180 -0
  80. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_is_measured_against_a_random_walk.py +10 -2
  81. arbiter_engine-0.2.6/tests/test_a_forecast_keeps_its_doubt.py +175 -0
  82. arbiter_engine-0.2.6/tests/test_a_forecast_keeps_its_doubt_when_its_median_stands_still.py +179 -0
  83. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecaster_is_judged_by_the_same_eight_axioms.py +31 -20
  84. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_freeze_is_found_inside_its_window.py +18 -3
  85. arbiter_engine-0.2.6/tests/test_a_lazy_import_did_not_move_a_name.py +257 -0
  86. arbiter_engine-0.2.6/tests/test_a_margin_is_measured_against_every_line.py +168 -0
  87. arbiter_engine-0.2.6/tests/test_a_pair_can_beat_the_best_single_action.py +228 -0
  88. arbiter_engine-0.2.6/tests/test_a_plan_files_the_row_that_is_a_forecast.py +229 -0
  89. arbiter_engine-0.2.6/tests/test_a_proposed_spread_says_what_it_assumed.py +183 -0
  90. arbiter_engine-0.2.6/tests/test_a_ranking_says_how_close_the_call_was.py +181 -0
  91. arbiter_engine-0.2.6/tests/test_a_refused_block_says_which_rule_it_was_on.py +119 -0
  92. arbiter_engine-0.2.6/tests/test_a_refused_coupling_is_a_question_not_a_silence.py +311 -0
  93. arbiter_engine-0.2.6/tests/test_a_response_model_nobody_recognises_is_not_exponential.py +220 -0
  94. arbiter_engine-0.2.6/tests/test_a_rollout_can_be_graded_later.py +269 -0
  95. arbiter_engine-0.2.6/tests/test_a_rollout_carries_a_transient_past_the_action_step.py +260 -0
  96. arbiter_engine-0.2.6/tests/test_a_second_action_on_a_moved_property_superposes.py +182 -0
  97. arbiter_engine-0.2.6/tests/test_a_sentence_the_changelog_closed_is_gone.py +111 -0
  98. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_set_aside_forecast_says_who_set_it_aside.py +3 -3
  99. arbiter_engine-0.2.6/tests/test_a_source_pinned_at_zero_passes_no_doubt_on.py +101 -0
  100. arbiter_engine-0.2.6/tests/test_a_spread_nobody_declared_is_not_a_declared_zero.py +137 -0
  101. arbiter_engine-0.2.6/tests/test_a_surprise_the_store_never_saw_is_not_a_miss.py +411 -0
  102. arbiter_engine-0.2.6/tests/test_a_tie_break_knows_which_side_of_the_line.py +178 -0
  103. arbiter_engine-0.2.6/tests/test_a_tie_is_broken_by_the_declared_margin.py +189 -0
  104. arbiter_engine-0.2.6/tests/test_a_transition_into_an_acted_property_still_arrives.py +184 -0
  105. arbiter_engine-0.2.6/tests/test_a_two_stage_chain_composes_exactly.py +196 -0
  106. arbiter_engine-0.2.6/tests/test_a_value_is_final_before_anything_reads_it.py +178 -0
  107. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_warning_is_a_finding_on_every_surface.py +1 -1
  108. arbiter_engine-0.2.6/tests/test_a_what_if_is_evaluated_at_the_horizon_it_asked_for.py +131 -0
  109. arbiter_engine-0.2.6/tests/test_an_action_may_arrive_as_a_mapping.py +134 -0
  110. arbiter_engine-0.2.6/tests/test_an_action_on_a_coupled_property_reads_the_value_it_has.py +285 -0
  111. arbiter_engine-0.2.6/tests/test_an_action_outlives_the_forecast_it_overrides.py +223 -0
  112. arbiter_engine-0.2.6/tests/test_an_action_that_never_runs_says_so.py +326 -0
  113. arbiter_engine-0.2.6/tests/test_an_imagined_breach_is_not_a_live_one_in_the_telemetry.py +113 -0
  114. arbiter_engine-0.2.6/tests/test_an_invented_time_course_says_so.py +252 -0
  115. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_an_undeclared_transition_projects_nothing.py +13 -3
  116. arbiter_engine-0.2.6/tests/test_every_assumption_stamp_has_one_name.py +210 -0
  117. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_declared_tool_has_a_wrapper.py +12 -5
  118. arbiter_engine-0.2.6/tests/test_every_discipline_decline_has_one_name.py +168 -0
  119. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_shipped_example_actually_runs.py +99 -2
  120. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_simulation_decline_has_an_input.py +277 -2
  121. arbiter_engine-0.2.6/tests/test_importing_the_package_does_not_pull_an_optional_extra.py +185 -0
  122. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_mcp_roundtrip.py +15 -1
  123. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_no_cell_is_judged_twice.py +2 -1
  124. arbiter_engine-0.2.6/tests/test_no_test_anchors_time_at_import.py +132 -0
  125. arbiter_engine-0.2.6/tests/test_one_declared_spread_is_counted_once.py +470 -0
  126. arbiter_engine-0.2.6/tests/test_one_question_gets_one_projection.py +168 -0
  127. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_role_comes_from_the_model.py +1 -1
  128. arbiter_engine-0.2.6/tests/test_the_causal_verb_has_a_model_to_run_against.py +187 -0
  129. arbiter_engine-0.2.6/tests/test_the_engine_declares_no_domain_it_does_not_serve.py +114 -0
  130. arbiter_engine-0.2.6/tests/test_the_engine_races_its_own_forecasts.py +263 -0
  131. arbiter_engine-0.2.6/tests/test_the_engine_says_what_its_approximation_cost.py +267 -0
  132. arbiter_engine-0.2.6/tests/test_the_engine_scores_its_own_declared_spread.py +281 -0
  133. arbiter_engine-0.2.6/tests/test_the_evidence_floor_is_declared_or_disclosed.py +289 -0
  134. arbiter_engine-0.2.6/tests/test_the_ingest_tag_names_the_caller_not_the_funnel.py +158 -0
  135. arbiter_engine-0.2.6/tests/test_the_lane_cleans_up_after_itself.py +103 -0
  136. arbiter_engine-0.2.6/tests/test_the_ledger_is_reachable_without_a_deep_import.py +171 -0
  137. arbiter_engine-0.2.6/tests/test_the_namespaces_point_at_a_graph_that_ships.py +232 -0
  138. arbiter_engine-0.2.6/tests/test_the_policy_document_and_the_changelog_agree.py +134 -0
  139. arbiter_engine-0.2.6/tests/test_the_published_cascade_formula_is_the_one_that_runs.py +184 -0
  140. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_rate_arm_declines_what_it_used_to_guess.py +15 -2
  141. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_readme_name_count_is_derived.py +19 -11
  142. arbiter_engine-0.2.6/tests/test_the_readme_names_the_forms_load_model_takes.py +115 -0
  143. arbiter_engine-0.2.6/tests/test_the_schema_names_every_sub_envelope.py +123 -0
  144. arbiter_engine-0.2.6/tests/test_the_schema_names_what_a_sub_envelope_carries.py +195 -0
  145. arbiter_engine-0.2.6/tests/test_the_stance_page_says_what_no_other_page_says.py +284 -0
  146. arbiter_engine-0.2.6/tests/test_the_verb_that_used_the_number_names_it.py +182 -0
  147. arbiter_engine-0.2.6/tests/test_the_world_model_can_be_exercised_over_mcp.py +237 -0
  148. arbiter_engine-0.2.6/tests/test_trend_widens_and_does_not_point.py +145 -0
  149. arbiter_engine-0.2.6/tests/test_two_actions_at_two_instants_are_not_one.py +233 -0
  150. arbiter_engine-0.2.6/tests/test_two_bare_series_are_joinable.py +170 -0
  151. arbiter_engine-0.2.6/tests/test_two_claims_on_one_edge_are_two_questions.py +149 -0
  152. arbiter_engine-0.2.6/tests/test_two_offset_couplings_from_one_source_are_both_charged.py +213 -0
  153. arbiter_engine-0.2.6/tests/test_two_plans_that_cost_the_same_compare_equal.py +172 -0
  154. arbiter_engine-0.2.6/tests/test_two_rules_can_close_a_loop_neither_closes_alone.py +166 -0
  155. arbiter_engine-0.2.6/tests/test_two_settings_of_one_property_do_not_add.py +262 -0
  156. arbiter_engine-0.2.4/.github/workflows/tests.yml +0 -116
  157. arbiter_engine-0.2.4/arbiter_engine/ontology/__init__.py +0 -18
  158. arbiter_engine-0.2.4/arbiter_engine/twin/planner.py +0 -420
  159. arbiter_engine-0.2.4/arbiter_engine/twin/rollout.py +0 -426
  160. arbiter_engine-0.2.4/arbiter_engine/twin/transition_learner.py +0 -223
  161. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.gitattributes +0 -0
  162. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  163. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/PUBLISH_FROM_CI +0 -0
  164. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  165. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/workflows/verify-published.yml +0 -0
  166. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.github/workflows/verify-tag-artifact.yml +0 -0
  167. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/.gitignore +0 -0
  168. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/AI_ATTRIBUTION.md +0 -0
  169. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/AUTHORS.md +0 -0
  170. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/CODE_OF_CONDUCT.md +0 -0
  171. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/CONTRIBUTING.md +0 -0
  172. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/LICENSE +0 -0
  173. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/NOTICE +0 -0
  174. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/PRIVACY.md +0 -0
  175. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/SECURITY.md +0 -0
  176. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/SUPPORT.md +0 -0
  177. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/TRADEMARK.md +0 -0
  178. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/causal/__init__.py +0 -0
  179. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/causal/discovery.py +0 -0
  180. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/causal/granger.py +0 -0
  181. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/clock.py +0 -0
  182. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/derived/__init__.py +0 -0
  183. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/derived/indicator.py +0 -0
  184. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/derived/parser.py +0 -0
  185. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/envelope.py +0 -0
  186. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/examples/battery_pack.yaml +0 -0
  187. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/examples/factory_line.yaml +0 -0
  188. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/examples/kubernetes_node.yaml +0 -0
  189. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/examples/margin_book.yaml +0 -0
  190. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/examples/water_tank.yaml +0 -0
  191. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/__init__.py +0 -0
  192. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/envelope.py +0 -0
  193. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/ingest.py +0 -0
  194. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/forecast/monitor.py +0 -0
  195. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/__init__.py +0 -0
  196. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/calendar.py +0 -0
  197. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/observation.py +0 -0
  198. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/observation_source_wiring.py +0 -0
  199. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/readiness.py +0 -0
  200. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/history/sqlite_store.py +0 -0
  201. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/inference/__init__.py +0 -0
  202. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/inference/causal.py +0 -0
  203. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/inference/ve.py +0 -0
  204. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/mcp/__init__.py +0 -0
  205. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axiom_verdicts_production.py +0 -0
  206. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/__init__.py +0 -0
  207. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/boundedness.py +0 -0
  208. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/connectivity.py +0 -0
  209. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/conservation.py +0 -0
  210. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/consistency.py +0 -0
  211. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/extensions.py +0 -0
  212. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/monotonicity.py +0 -0
  213. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/peers.py +0 -0
  214. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/responsiveness.py +0 -0
  215. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/roles.py +0 -0
  216. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/axioms/stability.py +0 -0
  217. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/ontology/prediction_production.py +0 -0
  218. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/projection/__init__.py +0 -0
  219. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/__init__.py +0 -0
  220. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/lp_confidence.py +0 -0
  221. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/mcts_root_cause.py +0 -0
  222. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/root_cause.py +0 -0
  223. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/propagation/weight_learner.py +0 -0
  224. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/rca/__init__.py +0 -0
  225. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/rca/greedy_set_cover.py +0 -0
  226. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/replay.py +0 -0
  227. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/residual/__init__.py +0 -0
  228. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/residual/sqlite_ledger.py +0 -0
  229. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/scripts/__init__.py +0 -0
  230. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/scripts/benchmark_check.py +0 -0
  231. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/temporal/__init__.py +0 -0
  232. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/temporal/trend_projection.py +0 -0
  233. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/__init__.py +0 -0
  234. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/gap.py +0 -0
  235. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/pipeline_production.py +0 -0
  236. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/arbiter_engine/twin/topology_optimizer.py +0 -0
  237. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/README.md +0 -0
  238. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/alpha1_evidence_pack.md +0 -0
  239. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/customer_deployment_runbook.md +0 -0
  240. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/extended_fault_scenarios.md +0 -0
  241. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/l5_surprise_synthesis.md +0 -0
  242. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/observability_handoff_guide.md +0 -0
  243. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/tech_brief.md +0 -0
  244. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/evidence/use-case-catalogue.md +0 -0
  245. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/examples/battery_pack.yaml +0 -0
  246. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/examples/factory_line.yaml +0 -0
  247. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/examples/kubernetes_node.yaml +0 -0
  248. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/examples/margin_book.yaml +0 -0
  249. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/examples/water_tank.yaml +0 -0
  250. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_balance_may_cross_an_entity_boundary.py +0 -0
  251. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_bound_can_belong_to_one_instance.py +0 -0
  252. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_calibration_figure_names_its_population.py +0 -0
  253. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_check_that_cannot_run_says_so.py +0 -0
  254. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_check_that_declines_is_heard.py +0 -0
  255. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_checker_asks_no_entity_type.py +0 -0
  256. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_bad_state_is_not_silent.py +0 -0
  257. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_calendar_is_actually_read.py +0 -0
  258. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_edge_reaches_the_published_surface.py +0 -0
  259. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_floor_is_checked_on_every_path.py +0 -0
  260. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_gain_moves_the_downstream_value.py +0 -0
  261. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_declared_number_is_the_first_breach.py +0 -0
  262. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_derived_indicator_is_computed_not_fed.py +0 -0
  263. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_discipline_reports_its_own_denominator.py +0 -0
  264. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_dropped_declaration_is_not_silent.py +0 -0
  265. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_filed_source_says_who_is_not_a_producer.py +0 -0
  266. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_batch_is_filed_or_accounted_for.py +0 -0
  267. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_check_that_refused_says_so_out_loud.py +0 -0
  268. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_is_scored_not_just_stored.py +0 -0
  269. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_states_its_own_distribution.py +0 -0
  270. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_forecast_widens_and_says_what_it_assumed.py +0 -0
  271. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_latency_without_a_threshold_says_so.py +0 -0
  272. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_lead_lag_p_value_means_what_it_says.py +0 -0
  273. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_learned_gain_is_a_proposal.py +0 -0
  274. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_nested_block_is_checked_too.py +0 -0
  275. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_per_instance_bound_reaches_every_reader.py +0 -0
  276. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_plan_ranks_only_when_told_how.py +0 -0
  277. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_posterior_is_arithmetic_not_assumption.py +0 -0
  278. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_prediction_ledger_outlives_the_process.py +0 -0
  279. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_projection_declines_rather_than_guessing.py +0 -0
  280. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_reading_can_be_impossible_without_being_extreme.py +0 -0
  281. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_rollout_steps_the_model_forward.py +0 -0
  282. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_starved_join_says_which_operand_starved.py +0 -0
  283. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_window_cannot_see_past_the_frozen_clock.py +0 -0
  284. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_withdrawn_check_is_not_silent.py +0 -0
  285. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_a_zero_allowance_still_reports.py +0 -0
  286. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_absent_data_regressions.py +0 -0
  287. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_agreement_declines_what_it_used_to_guess.py +0 -0
  288. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_an_imagined_finding_is_not_a_live_one.py +0 -0
  289. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_closed_reader.py +0 -0
  290. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_connectivity_required_property.py +0 -0
  291. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_conservation_absent_output.py +0 -0
  292. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_cross_signal_consistency.py +0 -0
  293. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_decline_contract.py +0 -0
  294. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_did_you_mean_is_case_insensitive.py +0 -0
  295. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_discovery_proposes_and_never_promotes.py +0 -0
  296. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_documented_paths_the_suite_never_ran.py +0 -0
  297. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_entailment_derives_and_refuses.py +0 -0
  298. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_envelope_schema.py +0 -0
  299. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_decline_reason_has_a_producer.py +0 -0
  300. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_forecast_gets_a_yardstick.py +0 -0
  301. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_every_reader_takes_the_same_history.py +0 -0
  302. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_gated_cell_declines.py +0 -0
  303. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_history_outlives_the_process_and_the_weekend.py +0 -0
  304. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_homeostasis_setpoint.py +0 -0
  305. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_lower_bounds.py +0 -0
  306. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_mcp_feeders.py +0 -0
  307. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_monotonicity_reversals.py +0 -0
  308. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_no_axiom_retires_a_check.py +0 -0
  309. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_no_identifier_names_a_private_record.py +0 -0
  310. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_one_set_of_names_the_model_reads.py +0 -0
  311. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_slow_oscillation.py +0 -0
  312. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_axioms_run_over_the_forecast_itself.py +0 -0
  313. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_clock_can_be_moved.py +0 -0
  314. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_config_blocks_are_documented.py +0 -0
  315. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_documented_priorities_are_the_computed_ones.py +0 -0
  316. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_engine_invents_no_indicators.py +0 -0
  317. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_engines_own_forecast_is_not_a_producers.py +0 -0
  318. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_envelope_legs_are_documented.py +0 -0
  319. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_forecasts_leg_says_how_many_were_expected.py +0 -0
  320. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_indicator_keys_are_documented.py +0 -0
  321. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_legal_files_ship_together.py +0 -0
  322. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_question_ranking_is_one_scale.py +0 -0
  323. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_readme_decline_count_is_derived.py +0 -0
  324. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_rename_table_names_real_things.py +0 -0
  325. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_sample_floor_says_whether_it_is_reachable.py +0 -0
  326. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_the_session_keeps_its_own_ledger.py +0 -0
  327. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_threshold_overrides.py +0 -0
  328. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_timestamped_ingestion.py +0 -0
  329. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_traverse_vocabularies.py +0 -0
  330. {arbiter_engine-0.2.4 → arbiter_engine-0.2.6}/tests/test_unread_properties.py +0 -0
@@ -154,9 +154,9 @@ jobs:
154
154
  # upload is the one that cannot be taken back, and a version number on this
155
155
  # index can never be reused.
156
156
  #
157
- # That division is the repository's own. `build-engine.sh` says it in as many
158
- # words: it builds and verifies, it does not push, because the irreversible
159
- # step stays with the operator. Automating the upload would have removed that
157
+ # That division is the repository's own, and the tooling that derives this
158
+ # package says it in as many words: it builds and verifies, it does not
159
+ # push, because the irreversible step stays with the operator. Automating the upload would have removed that
160
160
  # division; the approval gate is what puts it back.
161
161
  # -------------------------------------------------------------------------
162
162
  publish:
@@ -0,0 +1,292 @@
1
+ # The engine's own suite, on every change.
2
+ #
3
+ # The sibling workflow verifies the PUBLISHED package on a schedule; this one
4
+ # is the gate on the way in. Until it existed the package shipped no tests at
5
+ # all, and every regression guard it had lived in a downstream consumer's
6
+ # integration suite -- which meant the engine's protection depended on somebody
7
+ # else's project continuing to exist, and a defect reached six releases and
8
+ # seven issues before anybody upstream could have seen it.
9
+ #
10
+ # THREE LESSONS ARE PRE-APPLIED HERE, each of which cost a real defect in a
11
+ # project that consumes this one. They are the reason this file is longer than
12
+ # `run pytest`.
13
+ #
14
+ # NOTE ON FORMATTING: no hanging indents in these comments. The publication
15
+ # path collapses leading whitespace inside a config-file comment, so an
16
+ # indented continuation would arrive here looking different from how it was
17
+ # written -- and the check that compares the two is worth more than the
18
+ # indent.
19
+ #
20
+ # 1. pytest is installed EXPLICITLY. A CI step that installs nothing runs a
21
+ # bare interpreter. The consuming project's checks job was red on every push
22
+ # for months of subjective time because the runner had no pytest, so no test
23
+ # ever ran server-side -- and nobody reads a job that has never been green.
24
+ #
25
+ # 2. EXIT CODE 5 FAILS. pytest exits 5 when it collects nothing, and a module
26
+ # that skips at import collects nothing. That is the permissive value, and
27
+ # leaving it permissive is how a canary job stayed green for four runs having
28
+ # executed zero tests. "No tests ran" is precisely the hole this workflow
29
+ # exists to close, so it is spelled as a failure below rather than left to a
30
+ # shell's default.
31
+ #
32
+ # 3. THE MATRIX REACHES 3.12. `datetime.utcnow()` gained its DeprecationWarning
33
+ # in 3.12, and `filterwarnings = error::DeprecationWarning` in pyproject.toml
34
+ # is inert below it. A green run on the 3.10 floor proves nothing about that
35
+ # gate; a run that never left 3.10 would report a passing check for a rule that
36
+ # had not been evaluated. 3.10 is here because it is the declared floor, not
37
+ # because it tests the warning.
38
+
39
+ name: tests
40
+
41
+ # NO BRANCH FILTER, and that is the fix rather than the shortcut. The first
42
+ # version read `branches: [main]` and this repository publishes on `master`, so
43
+ # the job was registered, valid, and unable to fire on a push -- zero runs,
44
+ # nothing red, nothing to read. This file's own header argues that a job nobody
45
+ # reads is worse than none; a job that cannot run is worse still, because it
46
+ # looks like coverage from every angle except the one that counts.
47
+ #
48
+ # A branch name here would be a second copy of a fact that lives in the
49
+ # publishing procedure, and the two would drift exactly once, silently. There
50
+ # is one branch; matching every push cannot be wrong about which.
51
+ on:
52
+ push:
53
+ pull_request:
54
+ workflow_dispatch:
55
+
56
+ permissions:
57
+ contents: read
58
+
59
+ jobs:
60
+ suite:
61
+ runs-on: ubuntu-latest
62
+ strategy:
63
+ fail-fast: false
64
+ matrix:
65
+ python-version: ['3.10', '3.12', '3.13']
66
+
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+
70
+ - uses: actions/setup-python@v5
71
+ with:
72
+ python-version: ${{ matrix.python-version }}
73
+
74
+ # The package, not the working tree. `pytest` resolves `arbiter_engine`
75
+ # from site-packages, so this exercises what a user installs -- a module
76
+ # left out of the wheel fails here rather than in their traceback.
77
+ #
78
+ # The `mcp` extra is installed deliberately. The transport binding is
79
+ # skipped without it, and a component whose only test is skipped
80
+ # everywhere wears the same green as one that is covered. That shim
81
+ # already shipped once having never been executed.
82
+ #
83
+ # `jsonschema` is installed for the same reason, and it took an
84
+ # outside reader to notice that the paragraph above stopped one line
85
+ # short of it. TEN tests gate on that import, and until now no lane
86
+ # installed it: this job ran `.[mcp]` and pytest, and the reproduction
87
+ # our own documents imply runs numpy, pyyaml and pytest. So the
88
+ # machine-readable contract that `meta.schema_version` advertises had
89
+ # never been put in front of a validator here -- including the single
90
+ # check that `schema/envelope.schema.json` parses as a 2020-12 schema at
91
+ # all, which has no derivation-based substitute and skipped in silence
92
+ # through every release. It is a TEST requirement and not a dependency:
93
+ # the engine still runs on numpy and pyyaml, and the pin below is what
94
+ # keeps that true.
95
+ #
96
+ # `rdf` joined `mcp` on 2026-09-23, for the same reason `jsonschema` is on
97
+ # the line below it. The extra is ADVERTISED in `pyproject.toml`, so
98
+ # `pip install arbiter-engine[rdf]` is a supported install -- and no lane
99
+ # had ever installed it, so the whole RDF path ran nowhere and the one
100
+ # graph the loader's namespaces refer to was never loaded by anything.
101
+ # That is the same defect this step already carries a paragraph about:
102
+ # a dependency a caller is invited to install, exercised on no lane.
103
+ #
104
+ # 4. pytest IS RANGE-PINNED, and the range is a claim this lane has
105
+ # tested. It was unpinned until 2026-09-24, so a fresh runner resolved
106
+ # whatever was newest that morning. pytest 9.1 deprecated a class-scoped
107
+ # fixture written as an instance method; `filterwarnings =
108
+ # error:DeprecationWarning` in pyproject.toml turns that into an ERROR;
109
+ # and one file in this suite used the pattern. The three together made
110
+ # the published lane go red with nothing in the tree having changed --
111
+ # green on a runner with an older cached pytest, red on a fresh one. The
112
+ # same *true where I stood, false where it is read* shape the release
113
+ # checks already close on the tree, arriving on the test RUNNER instead.
114
+ # The floor is where the suite is verified; the ceiling is the next
115
+ # major, which the canary job below reaches on purpose.
116
+ - name: Install the package and the suite's requirements
117
+ run: |
118
+ python -m pip install --upgrade pip
119
+ python -m pip install .[mcp,rdf]
120
+ python -m pip install 'pytest>=8,<10' jsonschema
121
+
122
+ # NAMES THE VERSION IT MEASURED. A range says what is allowed; the log
123
+ # has to say what actually ran, or a reader of a green check cannot tell
124
+ # which end of the range produced it.
125
+ - name: Say which pytest this run used
126
+ run: python -m pytest --version
127
+
128
+ # `set +e` is load-bearing, not tidiness. GitHub runs `run:` steps under
129
+ # `bash -e`, so a failing pytest would end the step at that line and the
130
+ # exit-5 branch below would never execute -- a handler that reads
131
+ # correctly and cannot run. Verified by running it, because reading it
132
+ # was how it looked fine.
133
+ #
134
+ # `-rs` prints the reason for every skip, and the output is
135
+ # TEE'd so the step after can read this run's summary instead of
136
+ # producing another one. Two reasons, and the second is the real one:
137
+ # a second run costs twenty seconds per matrix entry, and it grades a
138
+ # DIFFERENT EXECUTION than the one this job just accepted.
139
+ #
140
+ # `${PIPESTATUS[0]}`, not `$?`. Through a pipe, `$?` is tee's status --
141
+ # tee succeeds when pytest fails, so the naive form turns every red
142
+ # suite green and the exit-5 branch below never fires.
143
+ - name: Run the suite, and fail if it ran nothing
144
+ run: |
145
+ set +e
146
+ pytest -q -rs --tb=short | tee "${RUNNER_TEMP:-/tmp}/pytest-summary.txt"
147
+ rc=${PIPESTATUS[0]}
148
+ if [ "$rc" -eq 5 ]; then
149
+ echo "::error::pytest exited 5 -- it collected no tests. A suite that runs nothing reports the same green as one that passes."
150
+ exit 1
151
+ fi
152
+ exit "$rc"
153
+
154
+ # Asserts the outcome, not the mechanism. The step above could pass with
155
+ # a handful of tests if collection silently narrowed, so the count is
156
+ # read back and held against a floor. A bare count would be a number to
157
+ # maintain; a floor only ever goes red when coverage SHRINKS.
158
+ - name: The suite is not quietly shrinking
159
+ run: |
160
+ set +e
161
+ COLLECTED=$(pytest --collect-only -q 2>/dev/null | tail -1 | grep -oE '^[0-9]+')
162
+ echo "collected: $COLLECTED"
163
+ if [ -z "$COLLECTED" ] || [ "$COLLECTED" -lt 60 ]; then
164
+ echo "::error::collected ${COLLECTED:-0} tests; the suite has lost coverage"
165
+ exit 1
166
+ fi
167
+
168
+ # and the mirror image of the step above. A floor on COLLECTED
169
+ # catches a suite that shrinks; nothing caught a suite that goes QUIET,
170
+ # and going quiet is what actually happened -- ten tests turned into
171
+ # skips when an optional import went missing, and the pass count moved
172
+ # by ten in a number nobody reads to the digit.
173
+ #
174
+ # THE CEILING IS MEASURED, not chosen. With the package installed, the
175
+ # skips that remain are structural: three axioms declare a floor of one
176
+ # and have no below-the-floor case to construct, and two parametrized
177
+ # tests receive an empty axiom set. That is five. Without the package
178
+ # installed four more appear, which is nine, and nine is the ceiling so
179
+ # that a job on a runner that resolves the install differently does not
180
+ # go red for a reason that is not this one.
181
+ #
182
+ # WHAT IT CANNOT SEE: one test going quiet. A tier is what this catches
183
+ # -- losing `jsonschema` again puts the count at fifteen. Losing the
184
+ # `mcp` binding puts it at six and passes here, which is why that extra
185
+ # is pinned in the install rather than watched from here.
186
+ #
187
+ # It reads the GRADED run's summary rather than running the
188
+ # suite again. The first version ran it a second time, which measured
189
+ # twenty seconds per matrix entry and, worse, asked its question of an
190
+ # execution this job had never accepted.
191
+ #
192
+ # AND IT REFUSES WHEN IT CANNOT ANSWER. A missing or unrecognisable
193
+ # summary used to leave `SKIPPED` defaulting to zero, which is the
194
+ # failure mode this whole step exists to catch, one level up: a check
195
+ # that cannot see anything reporting the same green as one that looked.
196
+ - name: The suite is not quietly going skipped
197
+ run: |
198
+ set +e
199
+ SUMMARY=$(tail -1 "${RUNNER_TEMP:-/tmp}/pytest-summary.txt" 2>/dev/null)
200
+ if ! echo "$SUMMARY" | grep -qE '[0-9]+ (passed|failed|error)'; then
201
+ echo "::error::no pytest summary from the graded run, so this check cannot answer -- and a check that cannot answer must not pass."
202
+ exit 1
203
+ fi
204
+ echo "summary: $SUMMARY"
205
+ SKIPPED=$(echo "$SUMMARY" | grep -oE '[0-9]+ skipped' | grep -oE '^[0-9]+')
206
+ SKIPPED=${SKIPPED:-0}
207
+ echo "skipped: $SKIPPED"
208
+ if [ "$SKIPPED" -gt 9 ]; then
209
+ echo "::error::$SKIPPED tests skipped; a tier of the suite has gone quiet. The reasons are in the run step above -- an optional import that stops resolving takes its whole tier with it and reports the same green."
210
+ exit 1
211
+ fi
212
+
213
+ # The step above COUNTS; this one NAMES. A ceiling cannot see a
214
+ # swap -- one test going quiet while another starts passing leaves the
215
+ # number exactly where it was -- and the comment above already says what a
216
+ # single quiet test costs here: losing the `mcp` binding puts the count at
217
+ # six and passes.
218
+ #
219
+ # An outside report then measured exactly six against this commit, on this
220
+ # install recipe, and nothing this project ships could say which test it
221
+ # was. The only SINGLE-test optional import in the suite is that binding:
222
+ # `jsonschema` gates ten and `yaml` gates whole modules, so six is not a
223
+ # number the other two can produce. The SDK binding had almost certainly
224
+ # gone unrun again -- and *almost certainly* is the wrong grade for a
225
+ # component that already shipped once having never been executed.
226
+ #
227
+ # KEYED ON THE FILE, not the line. Line numbers move whenever a file is
228
+ # edited, and a guard going red for an edit above the skip teaches people
229
+ # to update it without reading it. WHAT THAT COSTS, written down rather
230
+ # than left to be discovered: two tests trading places inside ONE file are
231
+ # invisible here. Anything arriving, leaving, or moving between files is
232
+ # named.
233
+ #
234
+ # It reads the GRADED run's summary, for the reason the step above gives.
235
+ - name: The skips are the ones we expect, by name
236
+ run: |
237
+ set +e
238
+ SUMMARY_FILE="${RUNNER_TEMP:-/tmp}/pytest-summary.txt"
239
+ if [ ! -s "$SUMMARY_FILE" ]; then
240
+ echo "::error::no summary from the graded run, so the skip set cannot be read -- and a check that cannot answer must not pass."
241
+ exit 1
242
+ fi
243
+ EXPECTED=$(printf '%s\n' \
244
+ "3 tests/test_absent_data_regressions.py" \
245
+ "2 tests/test_threshold_overrides.py")
246
+ ACTUAL=$(awk '/^SKIPPED \[[0-9]+\]/ {
247
+ n = $2; gsub(/[^0-9]/, "", n);
248
+ split($3, part, ":"); count[part[1]] += n
249
+ }
250
+ END { for (f in count) printf "%d %s\n", count[f], f }' \
251
+ "$SUMMARY_FILE" | sort -k2)
252
+ echo "expected skips:"; printf '%s\n' "$EXPECTED"
253
+ echo "actual skips:"; printf '%s\n' "$ACTUAL"
254
+ if [ "$EXPECTED" != "$ACTUAL" ]; then
255
+ echo "::error::the skip set moved. Lines with < are expected and absent; lines with > are skipping and were not expected to. A test that starts skipping stops being evidence while still counting as collected."
256
+ diff <(printf '%s\n' "$EXPECTED") <(printf '%s\n' "$ACTUAL")
257
+ exit 1
258
+ fi
259
+
260
+ # THE CEILING, REACHED ON PURPOSE RATHER THAN HIT BY SURPRISE.
261
+ #
262
+ # The job above pins pytest below the next major so the gate is a gate. That
263
+ # alone would reproduce the defect it was written for one major later: a
264
+ # lane that never sees a new pytest cannot tell you a new pytest breaks it,
265
+ # and the reason the 9.1 errors arrived unannounced is that nothing here had
266
+ # ever run anything but whatever was newest.
267
+ #
268
+ # So one job installs the newest, on one interpreter, and is ALLOWED TO
269
+ # FAIL. Its red is a notice, not a gate: it says the range in the job above
270
+ # is now a claim about the past, and somebody should widen it deliberately
271
+ # after reading what moved. A gate that goes red for a reason nobody chose
272
+ # gets switched off; a notice that does is doing its job.
273
+ newest-pytest:
274
+ runs-on: ubuntu-latest
275
+ continue-on-error: true
276
+ steps:
277
+ - uses: actions/checkout@v4
278
+ - uses: actions/setup-python@v5
279
+ with:
280
+ python-version: '3.13'
281
+ - run: |
282
+ python -m pip install --upgrade pip
283
+ python -m pip install .[mcp,rdf]
284
+ python -m pip install --upgrade pytest jsonschema
285
+ - name: Say which pytest this run used
286
+ run: python -m pytest --version
287
+ # No exit-5 handling and no skip-set comparison: this lane is not the
288
+ # grade. It answers one question -- does the suite still pass on a
289
+ # pytest the pinned range excludes -- and anything more would be a
290
+ # second copy of the job above, drifting from it.
291
+ - name: The suite, on a pytest the gate does not admit
292
+ run: python -m pytest tests/ -q
@@ -265,6 +265,74 @@ one is inferred from an unknown.
265
265
 
266
266
  ---
267
267
 
268
+ ## 2a. The discipline vocabularies, which are not that one
269
+
270
+ Sec. 2 is titled *the decline vocabulary* and there are eight of them. The
271
+ fourteen above are the ones `check` uses to refuse an axiom evaluation. Each
272
+ sub-envelope -- `simulation`, `shadow`, `projection`, `discovery`,
273
+ `entailment`, `inference`, `forecasts` -- refuses out of its OWN closed set.
274
+ `COMPATIBILITY.md` says so, warns that reading a reason from one set against
275
+ another is how a closed enum stops being closed, and grants a patch release
276
+ permission to add a member to any of them.
277
+
278
+ **Until now no document said what they contain.** A reader told the sets are
279
+ separate, told not to mix them, and told they may grow had no way to see one,
280
+ and this guide -- the one that calls a decline vocabulary a requirements
281
+ document -- named only the fourteen.
282
+
283
+ What that costs is measurable. An outside comparison written in September 2026
284
+ reproduced every vocabulary this project had published -- the fourteen above,
285
+ the six gap types, the eight raced outcomes, the twenty assumption stamps -- by
286
+ exact membership. Its own table of *the closed vocabularies* then listed five
287
+ sets and none of these seven, and three members of the `simulation` set turned
288
+ up in its prose instead, beside a gap type, in a list read against the
289
+ fourteen. That is precisely the mistake `COMPATIBILITY.md` warns against, made
290
+ by a reader who got everything else exactly right, because what they needed in
291
+ order to avoid it was not published.
292
+
293
+ Ninety-three names across seven sets. Each row below is complete: what it folds
294
+ in, plus what is its own, is the whole set.
295
+
296
+ | sub-envelope | members | folds in | its own |
297
+ |---|---:|---|---|
298
+ | `simulation` | 39 | the fourteen, `projection` | `budget_exhausted`, `contradictory_actions`, `counterfactual_not_a_prediction`, `coupling_uninstantiated`, `cycle_unsupported`, `gain_not_adopted`, `malformed_action`, `malformed_request`, `missing_declaration`, `missing_dynamics`, `missing_entity`, `no_candidates`, `no_declared_tolerance`, `no_objective`, `settle_exceeds_step`, `unknown_action`, `unknown_parameter`, `wrong_entity_type` |
299
+ | `shadow` | 18 | the fourteen | `internal_error`, `no_report_probability`, `not_a_producers_submission`, `tail_not_declared` |
300
+ | `projection` | 9 | -- | `covariance_unbounded`, `insufficient_samples`, `internal_error`, `model_inconsistent`, `model_missing`, `no_lookback`, `no_report_probability`, `no_threshold`, `unidentifiable_parameter` |
301
+ | `discovery` | 8 | -- | `faithfulness_unverifiable`, `insufficient_samples`, `internal_error`, `latent_confounding_possible`, `no_significance_level`, `nonstationary_series`, `orientation_undetermined`, `untested_pair` |
302
+ | `entailment` | 7 | -- | `binding_budget_exhausted`, `depth_exceeded`, `internal_error`, `malformed_rule`, `open_world_undecidable`, `recursion_unsupported`, `rule_unreachable` |
303
+ | `inference` | 7 | -- | `cpt_missing`, `cycle_unsupported`, `evidence_conflict`, `internal_error`, `no_report_probability`, `not_identifiable`, `treewidth_exceeded` |
304
+ | `forecasts` | 5 | -- | `forecast_missing`, `internal_error`, `model_unknown`, `stale_forecast`, `ungradeable` |
305
+
306
+ Read every one of them three-valued, as `COMPATIBILITY.md` says: **a member you
307
+ do not recognise means this engine is newer than your reader**, not that the
308
+ record is malformed. A reader that switches exhaustively and raises on the
309
+ default will break, and the sets have each grown at least once.
310
+
311
+ Three things the shape of the table is telling you:
312
+
313
+ * **`simulation` is the large one because it inherits twice.** A rollout runs
314
+ the eight axioms over every imagined state, so every axiom decline can reach
315
+ it; and `seed_mode="projected"` runs the declared projector, so every
316
+ projection decline can too. Its eighteen own members are the ones about
317
+ actions, couplings and the walk itself.
318
+ * **A member appearing in two sets is the same word, not the same claim.**
319
+ `cycle_unsupported` in `simulation` is a topology the walk will not step;
320
+ in `inference` it is a graph the elimination order cannot handle.
321
+ `internal_error` is in six of the seven and means the same thing in all of
322
+ them, which is why it is not folded anywhere.
323
+ * **A withdrawn member is recorded, not deleted.** `forecasts` once held
324
+ `no_tolerance` and `entailment` two more; they were withdrawn when it was
325
+ shown no input could reach them, and the reasoning stays in
326
+ `subenvelope.py` beside the sets. A member nobody can construct an input for
327
+ makes the set a worse instrument.
328
+
329
+ This table is DERIVED from `subenvelope.py`, not transcribed beside it, and a
330
+ test fails when the two disagree. A table maintained by hand next to a
331
+ frozenset is a second copy of one closed set, which is the drift the module
332
+ itself refuses one level further in.
333
+
334
+ ---
335
+
268
336
  ## 3. The read surface that is not `check`
269
337
 
270
338
  The vocabulary above is everything the engine refuses to **judge**. It is not