arbiter-engine 0.2.7__tar.gz → 0.2.8__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.
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/workflows/release.yml +26 -14
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/CHANGELOG.md +39 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/CITATION.cff +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/MODELING.md +15 -2
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/PKG-INFO +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/api.py +25 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/assumptions.py +19 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/water_tank.yaml +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/inference/hypothesis.py +23 -2
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/inference/runner.py +79 -8
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/scripts/benchmark_check.py +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/traverser.py +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/alpha1_evidence_pack.md +2 -2
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/l5_surprise_synthesis.md +3 -3
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/water_tank.yaml +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/pyproject.toml +1 -1
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecaster_is_judged_by_the_same_eight_axioms.py +1 -1
- arbiter_engine-0.2.8/tests/test_a_posterior_says_which_reading_it_left_out.py +207 -0
- arbiter_engine-0.2.8/tests/test_the_alpha_figure_comes_from_the_record.py +108 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_evidence_floor_is_declared_or_disclosed.py +23 -7
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_stance_page_says_what_no_other_page_says.py +14 -51
- arbiter_engine-0.2.7/.github/PUBLISH_FROM_CI +0 -43
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.gitattributes +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/workflows/tests.yml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/workflows/verify-published.yml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.github/workflows/verify-tag-artifact.yml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/.gitignore +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/AI_ATTRIBUTION.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/AUTHORS.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/BRIDGES.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/CODE_OF_CONDUCT.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/COMPATIBILITY.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/CONTRIBUTING.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/LICENSE +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/NOTICE +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/PRIVACY.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/README.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/ROADMAP.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/SECURITY.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/STANCE.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/SUPPORT.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/TRADEMARK.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/axiom_thresholds.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/causal/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/causal/discovery.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/causal/granger.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/causal/leadlag.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/clock.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/derived/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/derived/indicator.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/derived/parser.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/envelope.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/battery_pack.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/factory_line.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/kubernetes_node.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/margin_book.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/pump_tank_dynamics.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/pump_tank_planning.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/substation_feeder.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/examples/substation_feeder_surprises.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/fire_frequency.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/contract.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/envelope.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/ingest.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/monitor.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/forecast/shadow.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/calendar.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/observation.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/observation_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/observation_source_wiring.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/readiness.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/history/sqlite_store.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/inference/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/inference/causal.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/inference/ve.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/interfaces.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/mcp/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/mcp/server.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axiom_verdicts_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/boundedness.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/connectivity.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/conservation.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/consistency.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/extensions.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/homeostasis.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/monotonicity.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/peers.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/responsiveness.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/roles.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/axioms/stability.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/domain_loader.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/entail.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/loader.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/prediction_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/reasoner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/ontology/schemas/health_meta_ontology.ttl +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/producers/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/producers/baseline_learner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/projection/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/projection/projector.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/projection/runner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/impact_estimator.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/lp_confidence.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/mcts_root_cause.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/root_cause.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/propagation/weight_learner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/rca/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/rca/greedy_set_cover.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/replay.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/residual/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/residual/predict_vs_mirror.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/residual/sqlite_ledger.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/schema/envelope.schema.json +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/scripts/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/scripts/surprise_benchmark.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/subenvelope.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/surprises.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/temporal/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/temporal/temporal_edge.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/temporal/trend_projection.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/__init__.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/action_clears_problem.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/actions.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/builder.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/gap.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/hypothesis_generator.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/hypothesis_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/kernel_pipeline_executor.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/monte_carlo_predictor.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/optimization_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/pipeline_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/planner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/rollout.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/topology.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/topology_optimizer.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/transition_learner.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/twin/traverser_production.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/arbiter_engine/types.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/README.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/customer_deployment_runbook.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/extended_fault_scenarios.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/observability_handoff_guide.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/tech_brief.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/evidence/use-case-catalogue.md +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/battery_pack.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/factory_line.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/kubernetes_node.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/margin_book.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/pump_tank_dynamics.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/pump_tank_planning.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/substation_feeder.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/examples/substation_feeder_surprises.yaml +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/schema/envelope.schema.json +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/conftest.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_balance_may_cross_an_entity_boundary.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_bound_can_belong_to_one_instance.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_calibration_figure_names_its_population.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_calibration_says_how_many_trajectories_it_saw.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_chain_of_lags_says_how_it_was_composed.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_changelog_section_says_whether_you_can_install_it.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_check_that_cannot_run_says_so.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_check_that_declines_is_heard.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_checker_asks_no_entity_type.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_clean_rollout_still_counts_what_it_evaluated.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_companion_beside_the_models_is_not_one.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_correct_gain_is_not_contradicted_by_a_lagged_series.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_coupling_block_is_checked_too.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_coupling_is_graded_on_its_own_projections.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_coupling_learns_how_its_projections_fared.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_bad_state_is_not_silent.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_calendar_is_actually_read.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_edge_reaches_the_published_surface.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_floor_is_checked_on_every_path.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_gain_moves_the_downstream_value.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_number_is_the_first_breach.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_offset_waits_for_the_delay.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_source_matches_the_guide.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_declared_spread_reaches_the_value.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_decline_states_the_number_it_computed.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_derived_indicator_is_computed_not_fed.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_discipline_reports_its_own_denominator.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_dropped_declaration_is_not_silent.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_filed_source_says_who_is_not_a_producer.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_finding_says_where_to_look_next.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_batch_is_filed_or_accounted_for.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_check_that_refused_says_so_out_loud.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_is_graded_at_its_horizon.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_is_measured_against_a_random_walk.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_is_scored_not_just_stored.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_keeps_its_doubt.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_keeps_its_doubt_when_its_median_stands_still.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_states_its_own_distribution.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_forecast_widens_and_says_what_it_assumed.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_freeze_is_found_inside_its_window.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_latency_without_a_threshold_says_so.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_lazy_import_did_not_move_a_name.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_lead_lag_p_value_means_what_it_says.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_learned_gain_is_a_proposal.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_margin_is_measured_against_every_line.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_nested_block_is_checked_too.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_pair_can_beat_the_best_single_action.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_per_instance_bound_reaches_every_reader.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_plan_files_the_row_that_is_a_forecast.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_plan_ranks_only_when_told_how.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_posterior_is_arithmetic_not_assumption.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_prediction_ledger_outlives_the_process.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_projection_declines_rather_than_guessing.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_proposal_says_what_adopting_it_would_have_caught.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_proposed_spread_says_what_it_assumed.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_ranking_says_how_close_the_call_was.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_reading_can_be_impossible_without_being_extreme.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_refused_block_says_which_rule_it_was_on.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_refused_coupling_is_a_question_not_a_silence.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_response_model_nobody_recognises_is_not_exponential.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_rollout_can_be_graded_later.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_rollout_carries_a_transient_past_the_action_step.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_rollout_steps_the_model_forward.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_second_action_on_a_moved_property_superposes.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_sentence_the_changelog_closed_is_gone.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_set_aside_forecast_says_who_set_it_aside.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_source_pinned_at_zero_passes_no_doubt_on.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_spread_nobody_declared_is_not_a_declared_zero.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_starved_join_says_which_operand_starved.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_surprise_the_store_never_saw_is_not_a_miss.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_tie_break_knows_which_side_of_the_line.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_tie_is_broken_by_the_declared_margin.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_transition_into_an_acted_property_still_arrives.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_two_stage_chain_composes_exactly.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_value_is_final_before_anything_reads_it.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_vertical_may_adopt_and_this_engine_may_not.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_warning_is_a_finding_on_every_surface.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_what_if_is_evaluated_at_the_horizon_it_asked_for.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_window_cannot_see_past_the_frozen_clock.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_withdrawn_check_is_not_silent.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_a_zero_allowance_still_reports.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_absent_data_regressions.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_agreement_declines_what_it_used_to_guess.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_action_may_arrive_as_a_mapping.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_action_on_a_coupled_property_reads_the_value_it_has.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_action_outlives_the_forecast_it_overrides.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_action_that_never_runs_says_so.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_imagined_breach_is_not_a_live_one_in_the_telemetry.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_imagined_finding_is_not_a_live_one.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_invented_time_course_says_so.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_an_undeclared_transition_projects_nothing.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_closed_reader.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_connectivity_required_property.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_conservation_absent_output.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_cross_signal_consistency.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_decline_contract.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_did_you_mean_is_case_insensitive.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_discovery_proposes_and_never_promotes.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_documented_paths_the_suite_never_ran.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_entailment_derives_and_refuses.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_envelope_schema.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_assumption_stamp_has_one_name.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_declared_tool_has_a_wrapper.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_decline_reason_has_a_producer.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_discipline_decline_has_one_name.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_forecast_gets_a_yardstick.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_reader_takes_the_same_history.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_shipped_example_actually_runs.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_every_simulation_decline_has_an_input.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_gated_cell_declines.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_history_outlives_the_process_and_the_weekend.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_homeostasis_setpoint.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_importing_the_package_does_not_pull_an_optional_extra.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_lower_bounds.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_mcp_feeders.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_mcp_roundtrip.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_monotonicity_reversals.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_no_axiom_retires_a_check.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_no_cell_is_judged_twice.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_no_identifier_names_a_private_record.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_no_test_anchors_time_at_import.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_one_declared_spread_is_counted_once.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_one_question_gets_one_projection.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_one_set_of_names_the_model_reads.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_role_comes_from_the_model.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_slow_oscillation.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_axioms_run_over_the_forecast_itself.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_causal_verb_has_a_model_to_run_against.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_clock_can_be_moved.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_config_blocks_are_documented.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_documented_priorities_are_the_computed_ones.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_declares_no_domain_it_does_not_serve.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_invents_no_indicators.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_races_its_own_forecasts.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_says_what_its_approximation_cost.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_scores_its_own_declared_spread.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engine_ships_an_opponent_worth_beating.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_engines_own_forecast_is_not_a_producers.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_envelope_legs_are_documented.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_forecasts_leg_says_how_many_were_expected.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_indicator_keys_are_documented.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_ingest_tag_names_the_caller_not_the_funnel.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_lane_cleans_up_after_itself.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_ledger_is_reachable_without_a_deep_import.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_legal_files_ship_together.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_namespaces_point_at_a_graph_that_ships.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_policy_document_and_the_changelog_agree.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_published_cascade_formula_is_the_one_that_runs.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_question_ranking_is_one_scale.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_rate_arm_declines_what_it_used_to_guess.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_readme_decline_count_is_derived.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_readme_name_count_is_derived.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_readme_names_the_forms_load_model_takes.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_rename_table_names_real_things.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_sample_floor_says_whether_it_is_reachable.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_schema_names_every_sub_envelope.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_schema_names_what_a_sub_envelope_carries.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_session_keeps_its_own_ledger.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_verb_that_used_the_number_names_it.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_the_world_model_can_be_exercised_over_mcp.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_threshold_overrides.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_timestamped_ingestion.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_traverse_vocabularies.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_trend_widens_and_does_not_point.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_actions_at_two_instants_are_not_one.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_bare_series_are_joinable.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_claims_on_one_edge_are_two_questions.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_offset_couplings_from_one_source_are_both_charged.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_plans_that_cost_the_same_compare_equal.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_rules_can_close_a_loop_neither_closes_alone.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_two_settings_of_one_property_do_not_add.py +0 -0
- {arbiter_engine-0.2.7 → arbiter_engine-0.2.8}/tests/test_unread_properties.py +0 -0
|
@@ -109,15 +109,26 @@ jobs:
|
|
|
109
109
|
GH_TOKEN: ${{ github.token }}
|
|
110
110
|
run: gh release upload "$GITHUB_REF_NAME" dist/* --clobber
|
|
111
111
|
|
|
112
|
-
# PUBLISHING IS
|
|
113
|
-
#
|
|
112
|
+
# PUBLISHING IS DONE BY HAND, BY RULING, and the marker is a file rather
|
|
113
|
+
# than a setting so the change that turns it back on is reviewable.
|
|
114
114
|
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
# already
|
|
120
|
-
#
|
|
115
|
+
# It was ON from 2026-09-03 to 2026-09-25 and never published a file. The
|
|
116
|
+
# job below runs on the TAG; the release runbook uploads BEFORE the tag,
|
|
117
|
+
# so the repository never advertises a version the index does not serve.
|
|
118
|
+
# For a release made that way the publish job can only ever meet a version
|
|
119
|
+
# already on the index, so approving it could only fail -- and fourteen tag
|
|
120
|
+
# runs, v0.1.11 through v0.2.7, sat waiting with no conclusion instead.
|
|
121
|
+
# That is the two paths being mutually exclusive, not somebody forgetting
|
|
122
|
+
# to click.
|
|
123
|
+
#
|
|
124
|
+
# BOTH SETTINGS IT NEEDS STILL EXIST, and settings do not show in a diff,
|
|
125
|
+
# so they are stated here rather than lost with the marker. A `pypi`
|
|
126
|
+
# environment with a required reviewer (measured 2026-09-25), and a PyPI
|
|
127
|
+
# trusted publisher naming this repository, this workflow and that
|
|
128
|
+
# environment (verified at registration on 2026-09-03; no upload has ever
|
|
129
|
+
# used it). Turning publishing back on is a change to the UPLOAD ORDER
|
|
130
|
+
# first -- tag, then publish -- and the marker second. The marker alone
|
|
131
|
+
# restores exactly the waits described above.
|
|
121
132
|
- name: Is publishing from CI enabled?
|
|
122
133
|
id: gate
|
|
123
134
|
run: |
|
|
@@ -126,12 +137,13 @@ jobs:
|
|
|
126
137
|
else
|
|
127
138
|
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
|
128
139
|
echo "::notice::CI built these artifacts from the tag and attached them" \
|
|
129
|
-
"to the Release. Publishing to the index is
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
140
|
+
"to the Release. Publishing to the index is done by hand, before" \
|
|
141
|
+
"the tag, so this repository never advertises a version the index" \
|
|
142
|
+
"does not serve. The 'pypi' environment and the PyPI trusted" \
|
|
143
|
+
"publisher both still exist. To hand publishing to CI, change the" \
|
|
144
|
+
"release order to tag-then-publish FIRST, then add" \
|
|
145
|
+
".github/PUBLISH_FROM_CI: the marker alone brings back a publish" \
|
|
146
|
+
"job that can only meet a version already on the index."
|
|
135
147
|
fi
|
|
136
148
|
|
|
137
149
|
# The bytes that were attached, kept for the publish job. NOT a rebuild
|
|
@@ -34,6 +34,45 @@ useful-looking document and the less trustworthy one.
|
|
|
34
34
|
|
|
35
35
|
## [Unreleased]
|
|
36
36
|
|
|
37
|
+
## [0.2.8] — 2026-09-25
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **`target_reading_set_aside` (`TARGET_READING_SET_ASIDE`), a stamp on every
|
|
42
|
+
`inference` answer whose target had a reading of its own.** `infer` answers whether everything ELSE implicates
|
|
43
|
+
the target, so the target's own reading is left out -- and nothing said so. A
|
|
44
|
+
supply at 9.0 kV, below its own critical floor, got the posterior it gets at a
|
|
45
|
+
healthy 11.0 kV. `checked.target_reading` now carries what the reading would
|
|
46
|
+
have set (`faulty` or `clean`) and the target's own worst severity at any
|
|
47
|
+
level. No posterior changes.
|
|
48
|
+
- **Each `hypothesize` candidate carries `own_reading`**, the same row for that
|
|
49
|
+
candidate: `None` when it was unread, which is the case `evidence_needed` is
|
|
50
|
+
written for. Measured before it: a feeder read CLEAN ranked first at 0.962
|
|
51
|
+
with its own current named as the evidence needed.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **`hypothesize` carries the stamps of the inferences behind its ranking.** It
|
|
56
|
+
dropped all of them, so a ranking computed against this engine's default
|
|
57
|
+
evidence floor arrived without `evidence_severity_not_declared`, while the
|
|
58
|
+
verb's own docstring told the reader to check for that stamp.
|
|
59
|
+
- **An intervention on the target answers exactly.** `infer(t, do={t: v})`
|
|
60
|
+
returned the same posterior for `v = 0` and `v = 1` (0.984981 on the
|
|
61
|
+
specimen), because the forced value was set aside with the reading. It
|
|
62
|
+
returns `v` now, with method `intervention`, and files nothing.
|
|
63
|
+
- **Twelve published sentences that read as broken English.** Seven docstrings
|
|
64
|
+
and comments (`Until this returned two values`, `the ONLY rule until, and`)
|
|
65
|
+
and five lines of `evidence/` (`the recursive-examination framework
|
|
66
|
+
framework`) came out of the step that removes internal references. They now
|
|
67
|
+
read as sentences. No behaviour changes.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- **Releases are uploaded to the index by hand, and `.github/PUBLISH_FROM_CI` is
|
|
72
|
+
retired.** The CI publish job it enabled runs on the tag, after the upload the
|
|
73
|
+
release procedure makes first, so it never published a file. CI still builds
|
|
74
|
+
each release from its tag and attaches the files to the GitHub Release.
|
|
75
|
+
|
|
37
76
|
## [0.2.7] — 2026-09-25
|
|
38
77
|
|
|
39
78
|
### Added
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
alias: "james-sheen"
|
|
10
10
|
- name: "The Arbiter Project Authors"
|
|
11
11
|
license: Apache-2.0
|
|
12
|
-
version: "0.2.
|
|
12
|
+
version: "0.2.8"
|
|
13
13
|
date-released: "2026-09-25"
|
|
14
14
|
repository-code: "https://github.com/james-sheen/arbiter"
|
|
15
15
|
url: "https://github.com/james-sheen/arbiter"
|
|
@@ -1105,7 +1105,18 @@ this is a verb rather than a filter over `traverse`. On the shipped specimen,
|
|
|
1105
1105
|
asking about the supply with the feeder OBSERVED faulty gives 0.679054 and with
|
|
1106
1106
|
the feeder FORCED faulty gives 0.05 -- the same node in the same state, a factor
|
|
1107
1107
|
of thirteen apart. Seeing a thing fail is evidence about what feeds it; breaking
|
|
1108
|
-
it yourself is not.
|
|
1108
|
+
it yourself is not. Forcing the TARGET itself answers exactly: `do={t: v}`
|
|
1109
|
+
returns `v`, method `intervention`.
|
|
1110
|
+
|
|
1111
|
+
**The target's own reading is not evidence about the target.** `infer` asks
|
|
1112
|
+
whether everything ELSE implicates it, because conditioning on its own state
|
|
1113
|
+
would answer 1 or 0 by construction. So a supply in critical breach and the
|
|
1114
|
+
same supply healthy get one posterior between them -- correct for that
|
|
1115
|
+
question, and the answer says so: `target_reading_set_aside` is stamped whenever
|
|
1116
|
+
the target had a reading, and `checked.target_reading` names the state it would
|
|
1117
|
+
have set and the target's own worst severity. `hypothesize` carries the same
|
|
1118
|
+
row per candidate as `own_reading`, so a candidate the graph implicates can be
|
|
1119
|
+
read beside what its own meter already said.
|
|
1109
1120
|
|
|
1110
1121
|
### What counts as faulty evidence: `causal.evidence_severity`
|
|
1111
1122
|
|
|
@@ -1249,7 +1260,8 @@ which number to distrust.
|
|
|
1249
1260
|
They arrive in an `assumptions` list on the `simulation` and `plan`
|
|
1250
1261
|
sub-envelopes, and on each `plan` candidate where the candidates differ. An
|
|
1251
1262
|
EMPTY list means the engine made none of them, which is a different claim from
|
|
1252
|
-
the key being absent.
|
|
1263
|
+
the key being absent. The `inference` sub-envelope -- what `infer` and
|
|
1264
|
+
`hypothesize` return -- carries the list only when it has something in it.
|
|
1253
1265
|
|
|
1254
1266
|
| stamp | what it discloses |
|
|
1255
1267
|
|---|---|
|
|
@@ -1257,6 +1269,7 @@ the key being absent.
|
|
|
1257
1269
|
| `time_course_not_declared` | the time course crossed was not declared; this engine supplied a delay or a time constant, or both |
|
|
1258
1270
|
| `evidence_severity_not_declared` | `infer` read the last check against THIS engine's severity floor, because the model declared none. Declare `causal.evidence_severity:` to choose it |
|
|
1259
1271
|
| `evidence_severity_unusable` | the model DID declare `causal.evidence_severity:` and this engine could not use it, so the floor above was its own. Carried beside the stamp above, never instead of it; `model_describe` names the value that was refused |
|
|
1272
|
+
| `target_reading_set_aside` | the queried entity had a reading of its own and the posterior was computed without it -- the question answered is whether everything else implicates it. `checked.target_reading` says what the reading would have set, and the target's own worst severity |
|
|
1260
1273
|
| `steady_state_reached` | the horizon outlasted the transient, so the value reported is the settled one |
|
|
1261
1274
|
| `series_edges_composed_exactly` | two couplings in series were composed by the exact cascade response |
|
|
1262
1275
|
| `series_edges_compose_by_product` | two couplings in series were composed by multiplying response fractions, which is an approximation |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: arbiter-engine
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A detection engine that reports what it did not check.
|
|
5
5
|
Project-URL: Homepage, https://github.com/james-sheen/arbiter
|
|
6
6
|
Project-URL: Source, https://github.com/james-sheen/arbiter
|
|
@@ -2526,7 +2526,19 @@ def hypothesize(session: EngineSession, entity_id: str,
|
|
|
2526
2526
|
specimen: with both panels in the warning band the supply outranks the
|
|
2527
2527
|
feeder 0.0104 to 0.0018, and with both below critical the feeder ranks first
|
|
2528
2528
|
at 0.962. Same topology, same question, opposite answers — so read the
|
|
2529
|
-
`evidence_severity_not_declared` stamp before reading this ranking.
|
|
2529
|
+
`evidence_severity_not_declared` stamp before reading this ranking. Since
|
|
2530
|
+
the ranking carries it: every stamp an inference behind a candidate
|
|
2531
|
+
applied rides on `hypothesis.assumptions`. Before that the verb dropped
|
|
2532
|
+
them, and this paragraph told the reader to look for a stamp that was never
|
|
2533
|
+
there.
|
|
2534
|
+
|
|
2535
|
+
**A candidate's own reading is not part of its score.** Each posterior
|
|
2536
|
+
answers whether the REST of the graph implicates that candidate, and
|
|
2537
|
+
`own_reading` says what the candidate's own meter already said -- `None`
|
|
2538
|
+
when unread, which is the case `evidence_needed` is for. Measured: a feeder
|
|
2539
|
+
read clean at 300 A ranked first at 0.962 with its own current named as the
|
|
2540
|
+
evidence needed. The ranking is right about the graph; the row now shows
|
|
2541
|
+
the reading beside it.
|
|
2530
2542
|
"""
|
|
2531
2543
|
from arbiter_engine.inference.hypothesis import (
|
|
2532
2544
|
hypothesize as _hypothesize)
|
|
@@ -2586,6 +2598,18 @@ def infer(session: EngineSession, target: str,
|
|
|
2586
2598
|
Without `report_above` there is no finding, on the same rule as `project`
|
|
2587
2599
|
and `discover`: the posterior is computed and reported, and whether it is
|
|
2588
2600
|
alarming is not the engine's to decide.
|
|
2601
|
+
|
|
2602
|
+
THE TARGET'S OWN READING IS NOT EVIDENCE. The question answered is whether
|
|
2603
|
+
everything ELSE implicates the target -- conditioning on its own state would
|
|
2604
|
+
return 1 or 0 by construction. When the target had a reading, the answer is
|
|
2605
|
+
stamped `target_reading_set_aside` and `checked.target_reading` says what
|
|
2606
|
+
the reading would have set (`faulty` or `clean`) and the target's own worst
|
|
2607
|
+
severity at any level. A supply in critical breach and the same supply
|
|
2608
|
+
healthy get one posterior between them; that is correct for the question,
|
|
2609
|
+
and until a later change nothing on the answer said which question it was.
|
|
2610
|
+
|
|
2611
|
+
An intervention on the target itself answers exactly: `do={t: v}` returns
|
|
2612
|
+
`v`, method `intervention`, and files nothing.
|
|
2589
2613
|
"""
|
|
2590
2614
|
if session.model is None:
|
|
2591
2615
|
return unavailable_envelope("no domain model loaded")
|
|
@@ -6,7 +6,7 @@ not a warning and not a finding: it is the engine saying which of its own
|
|
|
6
6
|
choices the value in front of you depends on, so that a reader who disagrees
|
|
7
7
|
with the choice knows which number to distrust.
|
|
8
8
|
|
|
9
|
-
WHY THEY LIVE HERE. Until they lived as bare string literals at twenty
|
|
9
|
+
WHY THEY LIVE HERE. Until a later change they lived as bare string literals at twenty
|
|
10
10
|
sites across four modules, and nothing anywhere held the list. The cost was not
|
|
11
11
|
hypothetical. An outside comparison of this engine reproduced all three of its
|
|
12
12
|
ENUMERATED vocabularies exactly -- the fourteen decline reasons, the six gap
|
|
@@ -85,6 +85,23 @@ EVIDENCE_SEVERITY_NOT_DECLARED = "evidence_severity_not_declared"
|
|
|
85
85
|
#: duplicate what is there.
|
|
86
86
|
EVIDENCE_SEVERITY_UNUSABLE = "evidence_severity_unusable"
|
|
87
87
|
|
|
88
|
+
#: The queried entity had a reading of its own, and the posterior was computed
|
|
89
|
+
#: WITHOUT it. `infer` answers *does the rest of the graph implicate this
|
|
90
|
+
#: entity*, which is the informative question -- conditioning on the target's
|
|
91
|
+
#: own state would answer 1 or 0 by construction -- and the engine chose that
|
|
92
|
+
#: question on the caller's behalf. What the reading said is on the answer as
|
|
93
|
+
#: `checked.target_reading`: the state it would have set, and the target's own
|
|
94
|
+
#: worst severity at any level.
|
|
95
|
+
#:
|
|
96
|
+
#:, and it went unsaid for as long as the verb has existed. Measured on
|
|
97
|
+
#: the substation specimen with the feeder unread: the supply at 9.0 kV, below
|
|
98
|
+
#: its own critical floor, gets exactly the posterior it gets at a healthy
|
|
99
|
+
#: 11.0 kV, 0.670634 both times, because the one reading that would have
|
|
100
|
+
#: settled the question was the one left out. The other direction is worse. A feeder READ CLEAN is ranked
|
|
101
|
+
#: first by `hypothesize` at 0.962 with its own meter named as the evidence
|
|
102
|
+
#: needed -- the reading it had already taken and set aside.
|
|
103
|
+
TARGET_READING_SET_ASIDE = "target_reading_set_aside"
|
|
104
|
+
|
|
88
105
|
#: The horizon was long enough that the transient had finished, so the value
|
|
89
106
|
#: reported is the steady state rather than a point on the way to it.
|
|
90
107
|
STEADY_STATE_REACHED = "steady_state_reached"
|
|
@@ -239,6 +256,7 @@ ASSUMPTION_STAMPS: Tuple[str, ...] = (
|
|
|
239
256
|
TIME_COURSE_NOT_DECLARED,
|
|
240
257
|
EVIDENCE_SEVERITY_NOT_DECLARED,
|
|
241
258
|
EVIDENCE_SEVERITY_UNUSABLE,
|
|
259
|
+
TARGET_READING_SET_ASIDE,
|
|
242
260
|
STEADY_STATE_REACHED,
|
|
243
261
|
SERIES_EDGES_COMPOSED_EXACTLY,
|
|
244
262
|
SERIES_EDGES_COMPOSE_BY_PRODUCT,
|
|
@@ -75,7 +75,7 @@ domain:
|
|
|
75
75
|
#
|
|
76
76
|
# The role rule is single-value: `role: percentage` range-checks this
|
|
77
77
|
# reading against 0-100 and would behave identically if `level_pct` were
|
|
78
|
-
# deleted from the model. That was the ONLY rule until, and this
|
|
78
|
+
# deleted from the model. That was the ONLY rule until a later change, and this
|
|
79
79
|
# comment said `two independent readings that should agree` until
|
|
80
80
|
# 2026-08-16 -- the reading the use-case catalogue carried in eleven
|
|
81
81
|
# places, and the reason both were reported from outside on the same day.
|
|
@@ -46,6 +46,7 @@ from __future__ import annotations
|
|
|
46
46
|
|
|
47
47
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
48
48
|
|
|
49
|
+
from ..assumptions import ASSUMPTION_STAMPS
|
|
49
50
|
from ..subenvelope import Decline, SubEnvelope
|
|
50
51
|
from .causal import CausalGraph, causal_subgraph
|
|
51
52
|
from .runner import Query, run_inference
|
|
@@ -151,10 +152,18 @@ def hypothesize(session: Any, entity_id: str, *,
|
|
|
151
152
|
return SubEnvelope("inference", checked, not_checked=declines), []
|
|
152
153
|
|
|
153
154
|
ranked: List[Dict[str, Any]] = []
|
|
155
|
+
# THE STAMPS OF EVERY INFERENCE THIS RANKING RESTS ON. Each
|
|
156
|
+
# candidate is scored by `run_inference`, which stamps the defaults it
|
|
157
|
+
# applied; this verb used to drop them all, so a ranking computed against
|
|
158
|
+
# the engine's evidence floor carried no `evidence_severity_not_declared`
|
|
159
|
+
# while the verb's own docstring told the reader to check for it.
|
|
160
|
+
stamps: set = set()
|
|
154
161
|
for node, hops in candidates:
|
|
155
162
|
sub = run_inference(session, Query(target=node), report_above=None)
|
|
156
163
|
payload = sub.to_dict()
|
|
157
|
-
|
|
164
|
+
checked_here = payload.get("checked") or {}
|
|
165
|
+
posterior = checked_here.get("posterior")
|
|
166
|
+
stamps.update(payload.get("assumptions") or ())
|
|
158
167
|
entity_type = graph.entity_type.get(node, "")
|
|
159
168
|
properties = _readable_properties(session.model, entity_type)
|
|
160
169
|
ranked.append({
|
|
@@ -165,6 +174,13 @@ def hypothesize(session: Any, entity_id: str, *,
|
|
|
165
174
|
# The FIRST declared readable property, which is the model's own
|
|
166
175
|
# ordering rather than this verb's opinion about which matters.
|
|
167
176
|
"evidence_needed": (f"{node}.{properties[0]}" if properties else None),
|
|
177
|
+
# WHAT THAT READING ALREADY SAID, when it was taken. The
|
|
178
|
+
# posterior above leaves the candidate's own reading out, which is
|
|
179
|
+
# what makes it a ranking at all; without this row a feeder READ
|
|
180
|
+
# CLEAN came back first at 0.962 with its own meter as the evidence
|
|
181
|
+
# needed, sending an operator to take a reading already taken.
|
|
182
|
+
# `None` means unread -- the case `evidence_needed` is written for.
|
|
183
|
+
"own_reading": checked_here.get("target_reading"),
|
|
168
184
|
"test_action": _test_action(session.model, entity_type),
|
|
169
185
|
})
|
|
170
186
|
|
|
@@ -179,4 +195,9 @@ def hypothesize(session: Any, entity_id: str, *,
|
|
|
179
195
|
if r["posterior"] is not None and r["posterior"] >= report_above]
|
|
180
196
|
checked["reported"] = len(ranked)
|
|
181
197
|
|
|
182
|
-
|
|
198
|
+
# In the vocabulary's own order, so one set of findings always reports one
|
|
199
|
+
# list; a stamp outside the published tuple sorts last rather than vanishing.
|
|
200
|
+
order = {stamp: i for i, stamp in enumerate(ASSUMPTION_STAMPS)}
|
|
201
|
+
assumptions = tuple(sorted(stamps, key=lambda s: (order.get(s, len(order)), s)))
|
|
202
|
+
return (SubEnvelope("inference", checked, not_checked=declines,
|
|
203
|
+
assumptions=assumptions), ranked)
|
|
@@ -23,7 +23,8 @@ from typing import (Any, Dict, FrozenSet, List, Optional, Sequence, Set,
|
|
|
23
23
|
Tuple)
|
|
24
24
|
|
|
25
25
|
from ..assumptions import (EVIDENCE_SEVERITY_NOT_DECLARED,
|
|
26
|
-
EVIDENCE_SEVERITY_UNUSABLE
|
|
26
|
+
EVIDENCE_SEVERITY_UNUSABLE,
|
|
27
|
+
TARGET_READING_SET_ASIDE)
|
|
27
28
|
from ..subenvelope import Decline, SubEnvelope
|
|
28
29
|
from ..twin.gap import GAP_CONFIDENCE_THRESHOLDS as _GAP_WEIGHT
|
|
29
30
|
from ..twin.topology import GapType, TopologyGap, TopologyQuestion
|
|
@@ -79,7 +80,7 @@ def evidence_severities(model) -> Tuple[FrozenSet[str], bool, bool]:
|
|
|
79
80
|
see; `[critical, hihg]` therefore becomes the default rather than quietly
|
|
80
81
|
becoming `[critical]`.
|
|
81
82
|
|
|
82
|
-
`unusable` SEPARATES TRYING FROM NOT TRYING. Until this returned
|
|
83
|
+
`unusable` SEPARATES TRYING FROM NOT TRYING. Until a later change this returned
|
|
83
84
|
two values and an author who mistyped a severity got the same bare
|
|
84
85
|
`evidence_severity_not_declared` as one who declared nothing -- the reading
|
|
85
86
|
an outside review reproduced was *not declared*, therefore *my file did not
|
|
@@ -137,6 +138,40 @@ def evidence_from(session, graph: CausalGraph,
|
|
|
137
138
|
return observed, unobserved
|
|
138
139
|
|
|
139
140
|
|
|
141
|
+
#: Severity order for reporting the worst one, most urgent first. Ties in
|
|
142
|
+
#: `priority_score` (WARNING and MEDIUM share one) fall to declaration order, so
|
|
143
|
+
#: the same findings always report the same word.
|
|
144
|
+
_SEVERITY_ORDER: Tuple[Severity, ...] = tuple(Severity)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _own_severity(session, entity_id: str) -> Optional[str]:
|
|
148
|
+
"""The most urgent severity the last check gave `entity_id`, at ANY level.
|
|
149
|
+
|
|
150
|
+
Deliberately not filtered by the evidence floor. A panel carrying a warning
|
|
151
|
+
under an engine floor of `high` counted as CLEAN, and a reader looking at
|
|
152
|
+
the set-aside reading is owed both facts -- what the floor made of it and
|
|
153
|
+
what the check actually said -- or *clean* reads as *nothing was found*.
|
|
154
|
+
"""
|
|
155
|
+
result = getattr(session, "_last_result", None)
|
|
156
|
+
if result is None:
|
|
157
|
+
return None
|
|
158
|
+
worst: Optional[Severity] = None
|
|
159
|
+
for problem in list(getattr(result, "problems", ()) or ()) + \
|
|
160
|
+
list(getattr(result, "warnings", ()) or ()):
|
|
161
|
+
if str(getattr(problem, "entity_id", "")) != entity_id:
|
|
162
|
+
continue
|
|
163
|
+
raw = getattr(problem, "severity", None)
|
|
164
|
+
try:
|
|
165
|
+
severity = Severity(str(getattr(raw, "value", raw)).lower())
|
|
166
|
+
except ValueError:
|
|
167
|
+
continue
|
|
168
|
+
if worst is None or (
|
|
169
|
+
(severity.priority_score, _SEVERITY_ORDER.index(severity))
|
|
170
|
+
< (worst.priority_score, _SEVERITY_ORDER.index(worst))):
|
|
171
|
+
worst = severity
|
|
172
|
+
return None if worst is None else worst.value
|
|
173
|
+
|
|
174
|
+
|
|
140
175
|
def _surgery(graph: CausalGraph, do: Dict[str, int]) -> CausalGraph:
|
|
141
176
|
"""Cut the incoming edges of every intervened node. THIS is the difference
|
|
142
177
|
between `do(x)` and observing x, and the reason a hypothetical cannot be
|
|
@@ -220,6 +255,22 @@ def run_inference(session, query: Query,
|
|
|
220
255
|
evidence={"cycle": loop}))
|
|
221
256
|
return SubEnvelope("inference", checked, findings, declines, questions)
|
|
222
257
|
|
|
258
|
+
# AN INTERVENTION ON THE TARGET IS THE ANSWER. `do(x=v)` sets x,
|
|
259
|
+
# so P(x faulty | do(x=v)) is v, whatever the evidence says and however the
|
|
260
|
+
# graph is wired. Until this branch the intervened value went into the
|
|
261
|
+
# evidence and was then popped with the target's reading below, so the
|
|
262
|
+
# surgery cut x's parents and the elimination answered for an x nobody had
|
|
263
|
+
# set: measured on the specimen, `do={fdr-1: 0}` and `do={fdr-1: 1}` both
|
|
264
|
+
# returned 0.984981. Answered here, BEFORE the backdoor check, because an
|
|
265
|
+
# answer that reads no edge cannot be unidentifiable. Nothing is filed and
|
|
266
|
+
# nothing is reported: a value the caller forced is not a prediction about
|
|
267
|
+
# the world, and a finding would report the caller's own act back to them.
|
|
268
|
+
if query.target in query.do:
|
|
269
|
+
checked["answered"] = 1
|
|
270
|
+
checked["method"] = "intervention"
|
|
271
|
+
checked["posterior"] = float(query.do[query.target])
|
|
272
|
+
return SubEnvelope("inference", checked, findings, declines, questions)
|
|
273
|
+
|
|
223
274
|
working = _surgery(graph, query.do) if query.do else graph
|
|
224
275
|
latent = _open_backdoor_latent(working, query)
|
|
225
276
|
if latent is not None:
|
|
@@ -235,17 +286,34 @@ def run_inference(session, query: Query,
|
|
|
235
286
|
observed, unobserved = evidence_from(session, working, severities)
|
|
236
287
|
for node in query.do:
|
|
237
288
|
observed[node] = query.do[node]
|
|
238
|
-
|
|
289
|
+
# The target's own state is left out, because conditioning on it answers 1
|
|
290
|
+
# or 0 by construction. What is asked is whether EVERYTHING ELSE implicates
|
|
291
|
+
# it -- and since the answer says that is what was asked.
|
|
292
|
+
set_aside = observed.pop(query.target, None)
|
|
239
293
|
checked["evidence"] = len(observed)
|
|
240
294
|
checked["unobserved"] = len(unobserved)
|
|
241
295
|
# from here down the answer depends on WHICH severities counted
|
|
242
|
-
# as faulty, so every exit below carries the disclosure. The
|
|
296
|
+
# as faulty, so every exit below carries the disclosure. The returns
|
|
243
297
|
# above this line are refusals decided from the GRAPH alone -- a cycle, an
|
|
244
|
-
# open backdoor --
|
|
245
|
-
# choice that did not touch
|
|
298
|
+
# open backdoor -- or an intervention that fixes the answer, and read no
|
|
299
|
+
# evidence, so stamping them would name a choice that did not touch it.
|
|
246
300
|
stamps: Tuple[str, ...] = () if floor_declared else (
|
|
247
301
|
(EVIDENCE_SEVERITY_NOT_DECLARED,)
|
|
248
302
|
+ ((EVIDENCE_SEVERITY_UNUSABLE,) if floor_unusable else ()))
|
|
303
|
+
# AND WHICH READING WAS NOT USED. A target in breach answered
|
|
304
|
+
# exactly as a healthy one did, with nothing on the envelope saying its own
|
|
305
|
+
# reading had been excluded: measured, the supply at 9.0 kV and at 11.0 kV
|
|
306
|
+
# both 0.670634. Stamped whenever the target HAD a reading, clean as well
|
|
307
|
+
# as faulty -- a clean reading set aside misleads just as far, the other
|
|
308
|
+
# way. `severity` is the target's own worst finding at any level, beside
|
|
309
|
+
# the state the evidence floor made of it, because under the engine's floor
|
|
310
|
+
# a warning counts as clean and *clean* alone would read as *nothing found*.
|
|
311
|
+
target_reading: Optional[Dict[str, Any]] = None
|
|
312
|
+
if set_aside is not None:
|
|
313
|
+
target_reading = {"state": "faulty" if set_aside else "clean",
|
|
314
|
+
"severity": _own_severity(session, query.target)}
|
|
315
|
+
checked["target_reading"] = target_reading
|
|
316
|
+
stamps = stamps + (TARGET_READING_SET_ASIDE,)
|
|
249
317
|
|
|
250
318
|
relevant = _relevant_edges(working, query, observed)
|
|
251
319
|
defaulted = sorted(f"{s}->{t}" for (s, t) in relevant
|
|
@@ -313,14 +381,14 @@ def run_inference(session, query: Query,
|
|
|
313
381
|
elif posterior >= report_above:
|
|
314
382
|
findings.append(_posterior_finding(
|
|
315
383
|
session, working, query, posterior, observed, unobserved,
|
|
316
|
-
report_above))
|
|
384
|
+
report_above, target_reading))
|
|
317
385
|
|
|
318
386
|
return SubEnvelope("inference", checked, findings, declines, questions,
|
|
319
387
|
assumptions=stamps)
|
|
320
388
|
|
|
321
389
|
|
|
322
390
|
def _posterior_finding(session, graph, query, posterior, observed,
|
|
323
|
-
unobserved, report_above):
|
|
391
|
+
unobserved, report_above, target_reading=None):
|
|
324
392
|
from ..interfaces import Problem
|
|
325
393
|
entity = session.entities.get(query.target)
|
|
326
394
|
return Problem.from_entity(
|
|
@@ -335,6 +403,9 @@ def _posterior_finding(session, graph, query, posterior, observed,
|
|
|
335
403
|
"cpt_sources": graph.sources(),
|
|
336
404
|
"evidence_set": sorted(observed),
|
|
337
405
|
"unobserved": sorted(unobserved),
|
|
406
|
+
# a finding travels without its envelope, so the
|
|
407
|
+
# reading it did not use travels with it.
|
|
408
|
+
"target_reading": target_reading,
|
|
338
409
|
"root_prior": ROOT_PRIOR,
|
|
339
410
|
"root_prior_source": "default",
|
|
340
411
|
"do": dict(query.do)})
|
|
@@ -138,7 +138,7 @@ def build(entities: int, observations: int, breach_fraction: float):
|
|
|
138
138
|
"""A fresh session with `entities` units, a `breach_fraction` of them bad.
|
|
139
139
|
|
|
140
140
|
Returns the session and the two halves of its construction cost SEPARATELY.
|
|
141
|
-
They were one number until, and the number was unreadable: loading
|
|
141
|
+
They were one number until a later change, and the number was unreadable: loading
|
|
142
142
|
the model is flat in ENTITY count -- it loads a model, not entities -- while
|
|
143
143
|
the feed is linear, so a single `build` figure hides which half a consumer
|
|
144
144
|
pays again on the next cycle. That is the question the cost table gets
|
|
@@ -1744,7 +1744,7 @@ class TopologyTraverser:
|
|
|
1744
1744
|
builder seeded, which is how a walk that evaluated one invariant came
|
|
1745
1745
|
to report four.
|
|
1746
1746
|
|
|
1747
|
-
**BOUNDEDNESS only** — and, until, only HALF of BOUNDEDNESS.
|
|
1747
|
+
**BOUNDEDNESS only** — and, until a later change, only HALF of BOUNDEDNESS.
|
|
1748
1748
|
The body compared against `warning` and `critical` and never against
|
|
1749
1749
|
`lower_warning` / `lower_critical`, so a declared FLOOR was invisible
|
|
1750
1750
|
here while `UnifiedAxiomReasoner` reported it: a traversal over a
|
|
@@ -121,9 +121,9 @@ Detail is in the hypothesis log's Day-7/8/9 entries. A per-day Day-7 fault-watch
|
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
|
124
|
-
## Methodology —
|
|
124
|
+
## Methodology — recursive-examination 5-tier exercise framework
|
|
125
125
|
|
|
126
|
-
Alpha-1 work was structured by the recursive-examination
|
|
126
|
+
Alpha-1 work was structured by the recursive-examination (Recursive Examination as Engine) framework — a 5-tier session-level exercise discipline that generates L5 surprises by repeatedly stressing substrate rather than auditing it (auditing reveals known unknowns; exercising reveals unknown unknowns):
|
|
127
127
|
|
|
128
128
|
- **T0**: Data-flow probe (every session start; ~60s) — catches silent-fall-through before per-axis work.
|
|
129
129
|
- **T1**: Diagnostic-signature library match — 18 catalogued signatures save ~30-60 min per match.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## What is an L5 surprise?
|
|
10
10
|
|
|
11
|
-
L5 surprises are observations that the planned probes had not anticipated. The Alpha's
|
|
11
|
+
L5 surprises are observations that the planned probes had not anticipated. The Alpha's recursive-examination 5-tier exercise framework (T0 data-flow probe → T1 signature library → T2 adversarial cycle → T3 diagnostic-iteration loop → T4 cross-pattern leverage → T5 codification) defines its own surface — the questions each tier knows to ask. L5 surprises are observations that fall outside that surface: they emerge from exercising substrate, not auditing it, and they typically arise during T5 (session-end codification) when the operator notices a pattern that the framework's own probes couldn't see.
|
|
12
12
|
|
|
13
13
|
Why partners should care: L5 surprises are the substrate's claim to *real* coverage of cascade behavior in production-like AI/ML serving deployments. If the only findings were from planned probes, the substrate would be reporting back to its own designer. Surprises are the unplanned dividend — observations a partner couldn't have anticipated from the system's documentation alone.
|
|
14
14
|
|
|
@@ -134,7 +134,7 @@ For each L5 surprise (Days 1-11 = 16; Day-12 the second evaluation round RUN add
|
|
|
134
134
|
- **Anticipated by the probe design, before the load generator was built**: 0 of 16.
|
|
135
135
|
- **Anticipated after the triggering fault event**: 2 of 16 — the cumulative-counter self-clear and the MONOTONICITY axiom-family shift were predictable from the prior day's findings.
|
|
136
136
|
|
|
137
|
-
So the vast majority were genuinely open-world: the substrate produced findings that the planned probes (
|
|
137
|
+
So the vast majority were genuinely open-world: the substrate produced findings that the planned probes (recursive-examination T0-T5 + Spikes 1-5) did NOT anticipate.
|
|
138
138
|
|
|
139
139
|
**Detector anchor (replay) — the result that runs the other way.** Every figure above measures what the *designers* foresaw. None of them says anything about what the *detector* caught, and that number is unfavourable: **0 of the 16 Alpha-1 surprises were machine-surfaced at the time.** A human found all sixteen (the replay verdict, not published — see the provenance list at the end of this document).
|
|
140
140
|
|
|
@@ -216,7 +216,7 @@ request. They are not links; the records themselves can be supplied directly:
|
|
|
216
216
|
|
|
217
217
|
**Operator working notes, not documents** — pattern codifications held outside the repository. Listed
|
|
218
218
|
because they are where these findings were generalised, not as retrievable sources:
|
|
219
|
-
alpha-recursive-examination (T1 catalog +
|
|
219
|
+
alpha-recursive-examination (T1 catalog + recursive-examination framework); the methodology notes
|
|
220
220
|
(Pattern N 3-branch family + asymmetric-recovery sub-shape); the methodology notes
|
|
221
221
|
(Pattern N load-bearing); the methodology notes (Compression-B 12× yield).
|
|
222
222
|
|
|
@@ -75,7 +75,7 @@ domain:
|
|
|
75
75
|
#
|
|
76
76
|
# The role rule is single-value: `role: percentage` range-checks this
|
|
77
77
|
# reading against 0-100 and would behave identically if `level_pct` were
|
|
78
|
-
# deleted from the model. That was the ONLY rule until, and this
|
|
78
|
+
# deleted from the model. That was the ONLY rule until a later change, and this
|
|
79
79
|
# comment said `two independent readings that should agree` until
|
|
80
80
|
# 2026-08-16 -- the reading the use-case catalogue carried in eleven
|
|
81
81
|
# places, and the reason both were reported from outside on the same day.
|
|
@@ -380,7 +380,7 @@ def test_a_declaration_that_names_models_without_expecting_one_counts_nothing():
|
|
|
380
380
|
|
|
381
381
|
|
|
382
382
|
def test_the_kind_filter_is_now_a_live_path():
|
|
383
|
-
"""IT WAS DEFENCE UNTIL, AND THIS TEST SAID SO AND SAID WHY.
|
|
383
|
+
"""IT WAS DEFENCE UNTIL a later change, AND THIS TEST SAID SO AND SAID WHY.
|
|
384
384
|
|
|
385
385
|
The version here was named `..._is_defence_and_not_a_live_path`, reported
|
|
386
386
|
that no test claimed to exercise the filter, and gave the measurement
|