flux-sim-engine 0.2.0__tar.gz → 0.2.1__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.
- {flux_sim_engine-0.2.0/flux_sim_engine.egg-info → flux_sim_engine-0.2.1}/PKG-INFO +7 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/README.md +4 -2
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/__init__.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_links.py +1 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/VENDOR-NOTES.md +3 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vocabulary.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/describe.py +3 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/evidence/report.py +8 -9
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/governance/gate.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/apply.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1/flux_sim_engine.egg-info}/PKG-INFO +7 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_sim_engine.egg-info/SOURCES.txt +1 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/pyproject.toml +11 -10
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_architecture.py +3 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_community_files.py +24 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_first_run_script.py +2 -2
- flux_sim_engine-0.2.1/tests/test_public_wording.py +82 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_register_lint.py +3 -3
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_spec_modules.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_spec_shim.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_startup_budget.py +1 -1
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/LICENSE +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/NOTICE +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/NOTICE +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/bundle.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/enforce.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-enforcement-0.5.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-manifest-0.5.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-0.2.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-0.3.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-0.4.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-0.4.1.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-0.5.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-schema-latest.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-ui-hints-0.4.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-ui-hints-0.4.1.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/schema/flux-ui-hints-0.5.0.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/validate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/vectors/enforcement-vectors.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/vendor/fluid/fluid-schema-0.7.3.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/vendor/fluid/fluid-schema-0.7.4.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/vendor/fluid/fluid-schema-0.7.5.json +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/_scoring/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/accuracy_record.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/policy.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/records.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/accuracy/store.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/accuracy.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/agentic.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/calibration.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/claims.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/digests.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/emit.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/expressions.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/fidelity.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/lineage.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/stages.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/api/verdict.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/calibrate/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/calibrate/declared.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/calibrate/provenance.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/__main__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/_documents.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/_hints.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/_init.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/cli/_progress.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/merkle.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/slice.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/statistic.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/store.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/boundary/vault.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/compiler.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/gate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/predicate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/record.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/concordance/verifier.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/artifact.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/canonical.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/clock.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/digest.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/fixedpoint.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/lrm.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/rng.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/seedtree.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/core/trace.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/engine.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/evidence/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/evidence/pack.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/ast.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/attrs.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/check.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/compile.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/lexer.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/parser.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/expr/types.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/generator/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/generator/families.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/generator/paths.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/generator/rows.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/generator/statistics.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/governance/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/governance/audit.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/governance/skills.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/governance/sovereignty.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/lineage/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/lineage/emitter.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/py.typed +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/campaign.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/cast.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/detector.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/experiment.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/journey.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/jurisdiction.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/payloads.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/signals.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/runtime/temperature.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/attest.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/conform.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/contract.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/emit.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/mapping.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/resolve.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/seam/sinks.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/spec/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/spec/bundle.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/spec/enforce.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/spec/validate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/layout.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/pipeline.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/plan.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/replay.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/run.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/ship.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/validate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/stages/verify.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/detector.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/journey.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/module.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/payment-recovery.fluid.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/persona.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/signal.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/simulation.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/taxonomy.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/treatment.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/starter/bundle/world.flux.yml +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/verticals/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/verticals/telco.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/__init__.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/derived.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/errors.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/families.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/population.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/tracing.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/world/values.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_sim_engine.egg-info/dependency_links.txt +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_sim_engine.egg-info/entry_points.txt +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_sim_engine.egg-info/requires.txt +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_sim_engine.egg-info/top_level.txt +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/setup.cfg +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_artifact_envelope.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_check_proof_material.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_cli.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_cli_envelope_contract.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_describe.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_distribution_name.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_flux_examples_gate.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_third_party_licenses.py +0 -0
- {flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/tests/test_workflow_pins.py +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flux-sim-engine
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: FLUX Simulation Engine: the runtime for FLUX bundles -- deterministic, governed simulation under a referenced FLUID contract.
|
|
5
5
|
Author: Agentics Transformation Ltd
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Documentation, https://agenticstiger.github.io/flux/engine/
|
|
7
8
|
Project-URL: Repository, https://github.com/Agenticstiger/flux-engine
|
|
9
|
+
Project-URL: Issues, https://github.com/Agenticstiger/flux-engine/issues
|
|
8
10
|
Keywords: FLUX,FLUID,simulation,synthetic data,data contracts
|
|
9
11
|
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -45,11 +47,13 @@ Dynamic: license-file
|
|
|
45
47
|
|
|
46
48
|
Describe your customers and what they do in YAML, and this engine turns that into synthetic rows that follow a [FLUID](https://open-data-protocol.github.io/fluid/) data contract: the same rows every time, with a report that says plainly what the run does not show.
|
|
47
49
|
|
|
50
|
+
Documentation: <https://agenticstiger.github.io/flux/engine/>
|
|
51
|
+
|
|
48
52
|
## Try it
|
|
49
53
|
|
|
50
|
-
You need [uv](https://docs.astral.sh/uv/).
|
|
54
|
+
You need [uv](https://docs.astral.sh/uv/).
|
|
51
55
|
|
|
52
|
-
<!-- skip: next "the package
|
|
56
|
+
<!-- skip: next "installs the published package, so it cannot test this checkout; the First run workflow runs these same commands from a built wheel" -->
|
|
53
57
|
```bash
|
|
54
58
|
uvx --from flux-sim-engine fluxsim init demo && cd demo && uvx --from flux-sim-engine fluxsim run . --verify --ship -o out
|
|
55
59
|
```
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Describe your customers and what they do in YAML, and this engine turns that into synthetic rows that follow a [FLUID](https://open-data-protocol.github.io/fluid/) data contract: the same rows every time, with a report that says plainly what the run does not show.
|
|
4
4
|
|
|
5
|
+
Documentation: <https://agenticstiger.github.io/flux/engine/>
|
|
6
|
+
|
|
5
7
|
## Try it
|
|
6
8
|
|
|
7
|
-
You need [uv](https://docs.astral.sh/uv/).
|
|
9
|
+
You need [uv](https://docs.astral.sh/uv/).
|
|
8
10
|
|
|
9
|
-
<!-- skip: next "the package
|
|
11
|
+
<!-- skip: next "installs the published package, so it cannot test this checkout; the First run workflow runs these same commands from a built wheel" -->
|
|
10
12
|
```bash
|
|
11
13
|
uvx --from flux-sim-engine fluxsim init demo && cd demo && uvx --from flux-sim-engine fluxsim run . --verify --ship -o out
|
|
12
14
|
```
|
|
@@ -17,6 +17,6 @@ from importlib import metadata as _metadata
|
|
|
17
17
|
try:
|
|
18
18
|
__version__ = _metadata.version("flux-sim-engine")
|
|
19
19
|
except _metadata.PackageNotFoundError: # pragma: no cover - editable/dev tree, no metadata yet
|
|
20
|
-
__version__ = "0.2.
|
|
20
|
+
__version__ = "0.2.1"
|
|
21
21
|
|
|
22
22
|
__all__ = ["__version__"]
|
|
@@ -22,9 +22,7 @@ The base is the address these docs are published at. They are written in this
|
|
|
22
22
|
repository and join the FLUX specification's site as its ``engine/`` folder. That
|
|
23
23
|
site is built with VuePress at ``base: '/flux/'``, which its config locks because
|
|
24
24
|
every published schema ``$id`` depends on it, so ``docs/engine/reference/errors/FLX-nnnn.md``
|
|
25
|
-
there is served as ``/flux/engine/reference/errors/FLX-nnnn.html``.
|
|
26
|
-
are in the site they are not reachable: printing the address early is deliberate,
|
|
27
|
-
because the address is what has to stay stable.
|
|
25
|
+
there is served as ``/flux/engine/reference/errors/FLX-nnnn.html``.
|
|
28
26
|
|
|
29
27
|
**These addresses are public.** Every released version prints them, and a printed
|
|
30
28
|
address cannot be recalled. Moving a page means leaving something behind at the
|
{flux_sim_engine-0.2.0 → flux_sim_engine-0.2.1}/flux_engine/_vendor/flux_spec/VENDOR-NOTES.md
RENAMED
|
@@ -12,9 +12,9 @@ Retrieved via `git show <commit>:<path>` rather than the working tree,
|
|
|
12
12
|
because the FLUX checkout had uncommitted, in-flight changes at copy time
|
|
13
13
|
(a `feat/flux-spec-package` branch already mid-refactor into a `flux_spec/`
|
|
14
14
|
package with `scripts/*.py` becoming compatibility shims — exactly the
|
|
15
|
-
public-distribution work
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
public-distribution work planned for a later increment). Pinning to the
|
|
16
|
+
last commit keeps this vendor copy reproducible and independent of that
|
|
17
|
+
unmerged, unstable work.
|
|
18
18
|
|
|
19
19
|
Files copied, each verified byte-identical to the pinned blob before any
|
|
20
20
|
edit was applied:
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
A fixed set of words is held back from every public-facing surface this
|
|
8
8
|
project ships -- ``README.md``, repository-root Markdown, ``docs/``
|
|
9
|
-
outside
|
|
9
|
+
outside ``docs/spec/``, every ``fluxsim --help``
|
|
10
10
|
string, the docstrings and error-catalog explanations under
|
|
11
11
|
``flux_engine/``, and the generated ``EVIDENCE.md``. Public prose uses
|
|
12
12
|
"sign-off", "credibility" and "fidelity check" instead.
|
|
@@ -29,9 +29,9 @@ from flux_engine.spec import SOURCE
|
|
|
29
29
|
__all__ = ["installed_spec_version", "self_describe"]
|
|
30
30
|
|
|
31
31
|
#: The FLUX spec version the **vendored** validator/enforcement copy in
|
|
32
|
-
#: ``flux_engine._vendor.flux_spec`` implements (RFC-04 + RFC-09, v0.5.0
|
|
33
|
-
#:
|
|
34
|
-
#:
|
|
32
|
+
#: ``flux_engine._vendor.flux_spec`` implements (RFC-04 + RFC-09, v0.5.0).
|
|
33
|
+
#: It is the answer only while the vendored fallback is what this
|
|
34
|
+
#: installation runs on -- see :func:`installed_spec_version`.
|
|
35
35
|
VENDORED_SPEC_VERSION = "0.5.0"
|
|
36
36
|
|
|
37
37
|
#: The pre-0.2 spelling of :data:`VENDORED_SPEC_VERSION`, kept so a caller
|
|
@@ -58,12 +58,11 @@ __all__ = [
|
|
|
58
58
|
|
|
59
59
|
FLX_8030 = register(
|
|
60
60
|
"FLX-8030",
|
|
61
|
-
"generated evidence prose contains reserved
|
|
61
|
+
"generated evidence prose contains a reserved word",
|
|
62
62
|
"EVIDENCE.md is rendered from a fixed template, but a caller-supplied "
|
|
63
63
|
"value (a bundle name, a conformance summary) can still introduce a "
|
|
64
|
-
"word this project reserves
|
|
65
|
-
"
|
|
66
|
-
"written with the word inside it.",
|
|
64
|
+
"word this project reserves (the list is in flux_engine/_vocabulary.py). "
|
|
65
|
+
"The report is refused rather than written with the word inside it.",
|
|
67
66
|
)
|
|
68
67
|
|
|
69
68
|
#: The five sections of ``EVIDENCE.md``, in the fixed order they always
|
|
@@ -78,12 +77,12 @@ EVIDENCE_SECTIONS: Tuple[str, ...] = (
|
|
|
78
77
|
)
|
|
79
78
|
|
|
80
79
|
#: v0.1 names exactly one authored dial in the mandatory "What Was Not
|
|
81
|
-
#: Proven" section -- the one the
|
|
80
|
+
#: Proven" section -- the one the design names. A later
|
|
82
81
|
#: increment with a real calibration loop grows this list; nothing here
|
|
83
82
|
#: shrinks it silently.
|
|
84
83
|
DEFAULT_AUTHORED_DIALS: Tuple[str, ...] = ("temperature.campaignResponse",)
|
|
85
84
|
|
|
86
|
-
#: The
|
|
85
|
+
#: The reserved-word list. Re-exported from
|
|
87
86
|
#: :mod:`flux_engine._vocabulary`, which is the single definition shared
|
|
88
87
|
#: with ``scripts/register_lint.py``: the list used to be hand-copied into
|
|
89
88
|
#: both gates plus three test modules, with nothing asserting they were
|
|
@@ -92,7 +91,7 @@ _BANNED_WORDS: Tuple[str, ...] = BANNED_WORDS
|
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
def find_banned_words(text: str) -> Tuple[str, ...]:
|
|
95
|
-
"""Return every reserved
|
|
94
|
+
"""Return every reserved word found in *text*, lower-cased, sorted, deduplicated.
|
|
96
95
|
|
|
97
96
|
Thin wrapper over :func:`flux_engine._vocabulary.find_banned_words`,
|
|
98
97
|
kept because this module is where the runtime refusal lives: unlike
|
|
@@ -106,7 +105,7 @@ def find_banned_words(text: str) -> Tuple[str, ...]:
|
|
|
106
105
|
|
|
107
106
|
|
|
108
107
|
def require_no_banned_words(text: str, *, label: str = "EVIDENCE.md") -> None:
|
|
109
|
-
"""Raise ``FLX-8030`` when *text* contains a reserved
|
|
108
|
+
"""Raise ``FLX-8030`` when *text* contains a reserved word."""
|
|
110
109
|
hits = find_banned_words(text)
|
|
111
110
|
if hits:
|
|
112
111
|
raise FluxError(FLX_8030, f"{label} contains reserved vocabulary: {', '.join(hits)}")
|
|
@@ -173,7 +172,7 @@ def render_evidence_report(
|
|
|
173
172
|
"""Render ``EVIDENCE.md``'s five fixed sections for one bundle.
|
|
174
173
|
|
|
175
174
|
Raises ``FLX-8030`` if the rendered text contains a reserved
|
|
176
|
-
|
|
175
|
+
word -- most likely introduced through a caller-supplied
|
|
177
176
|
string such as *bundle_name* or *conformance_summary*.
|
|
178
177
|
"""
|
|
179
178
|
sections = [
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
"""The sole authorized boundary onto the FLUX enforcement contract (RFC-04).
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The architecture makes ``AIGate.call`` "the only path to a
|
|
8
8
|
``ModelPort``... first statement ``flux_spec.enforce.decide``". This
|
|
9
9
|
module is that boundary today: the import-linter contract "only
|
|
10
10
|
governance.gate may import spec.enforce" (pyproject.toml) keeps every
|
|
@@ -10,7 +10,7 @@ refuses (``FLX-2101``) when the bundle's freshly recomputed ``inputDigest``
|
|
|
10
10
|
no longer matches the one the plan recorded -- the bundle moved since
|
|
11
11
|
`fluxsim plan` ran. Both are checked *before* a single row is written.
|
|
12
12
|
|
|
13
|
-
Every artifact KERNEL-SPEC
|
|
13
|
+
Every artifact KERNEL-SPEC names lands under the run
|
|
14
14
|
directory: ``population.ndjson`` (cohort/market/trait), ``events.ndjson``
|
|
15
15
|
(signal/detect/transition/deliver/suppress/assign), ``suppressions.ndjson``,
|
|
16
16
|
``decisions.ndjson`` + its meta sidecar, one ``emits/<exposeId>.ndjson``
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flux-sim-engine
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: FLUX Simulation Engine: the runtime for FLUX bundles -- deterministic, governed simulation under a referenced FLUID contract.
|
|
5
5
|
Author: Agentics Transformation Ltd
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Documentation, https://agenticstiger.github.io/flux/engine/
|
|
7
8
|
Project-URL: Repository, https://github.com/Agenticstiger/flux-engine
|
|
9
|
+
Project-URL: Issues, https://github.com/Agenticstiger/flux-engine/issues
|
|
8
10
|
Keywords: FLUX,FLUID,simulation,synthetic data,data contracts
|
|
9
11
|
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -45,11 +47,13 @@ Dynamic: license-file
|
|
|
45
47
|
|
|
46
48
|
Describe your customers and what they do in YAML, and this engine turns that into synthetic rows that follow a [FLUID](https://open-data-protocol.github.io/fluid/) data contract: the same rows every time, with a report that says plainly what the run does not show.
|
|
47
49
|
|
|
50
|
+
Documentation: <https://agenticstiger.github.io/flux/engine/>
|
|
51
|
+
|
|
48
52
|
## Try it
|
|
49
53
|
|
|
50
|
-
You need [uv](https://docs.astral.sh/uv/).
|
|
54
|
+
You need [uv](https://docs.astral.sh/uv/).
|
|
51
55
|
|
|
52
|
-
<!-- skip: next "the package
|
|
56
|
+
<!-- skip: next "installs the published package, so it cannot test this checkout; the First run workflow runs these same commands from a built wheel" -->
|
|
53
57
|
```bash
|
|
54
58
|
uvx --from flux-sim-engine fluxsim init demo && cd demo && uvx --from flux-sim-engine fluxsim run . --verify --ship -o out
|
|
55
59
|
```
|
|
@@ -332,6 +332,7 @@ tests/test_describe.py
|
|
|
332
332
|
tests/test_distribution_name.py
|
|
333
333
|
tests/test_first_run_script.py
|
|
334
334
|
tests/test_flux_examples_gate.py
|
|
335
|
+
tests/test_public_wording.py
|
|
335
336
|
tests/test_register_lint.py
|
|
336
337
|
tests/test_spec_modules.py
|
|
337
338
|
tests/test_spec_shim.py
|
|
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "flux-sim-engine"
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.1"
|
|
12
12
|
description = "FLUX Simulation Engine: the runtime for FLUX bundles -- deterministic, governed simulation under a referenced FLUID contract."
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.11"
|
|
@@ -30,8 +30,8 @@ classifiers = [
|
|
|
30
30
|
# no calibration, synthesis or statistics library is among them, because no
|
|
31
31
|
# engine code imports one.
|
|
32
32
|
dependencies = [
|
|
33
|
-
# PCG64 bit source for the deterministic seed tree (core/seedtree.py
|
|
34
|
-
#
|
|
33
|
+
# PCG64 bit source for the deterministic seed tree (core/seedtree.py):
|
|
34
|
+
# `SeedSequence.spawn`/path-addressed derivation is the standard
|
|
35
35
|
# pattern (borrow-before-build receipt: numpy docs; also how Synthea's
|
|
36
36
|
# per-person RNG and the `neworder` microsimulation framework seed their
|
|
37
37
|
# entities). Ceiling <3 because numpy 2.x's C-API churn is still
|
|
@@ -57,8 +57,8 @@ dependencies = [
|
|
|
57
57
|
# a FLUX bundle and its FLUX engine agree on one digest, not two.
|
|
58
58
|
"rfc8785>=0.1",
|
|
59
59
|
# CNCF CloudEvents 1.0 envelope for signal/detection/emit event records
|
|
60
|
-
# (runtime
|
|
61
|
-
#
|
|
60
|
+
# (runtime/) and the ship-gate failure signal (concordance/gate.py).
|
|
61
|
+
# Borrowed-not-built per /borrow-before-build: the alternative was
|
|
62
62
|
# hand-rolling an event envelope, which is exactly the kind of
|
|
63
63
|
# stringly-typed wire format the project's own standing rules forbid.
|
|
64
64
|
# Ceiling <3 pins to the 1.x/2.x line the rest of the FLUID stack (the
|
|
@@ -145,7 +145,9 @@ dev = [
|
|
|
145
145
|
fluxsim = "flux_engine.cli:main"
|
|
146
146
|
|
|
147
147
|
[project.urls]
|
|
148
|
+
Documentation = "https://agenticstiger.github.io/flux/engine/"
|
|
148
149
|
Repository = "https://github.com/Agenticstiger/flux-engine"
|
|
150
|
+
Issues = "https://github.com/Agenticstiger/flux-engine/issues"
|
|
149
151
|
|
|
150
152
|
[tool.setuptools]
|
|
151
153
|
package-dir = {"" = "."}
|
|
@@ -307,11 +309,10 @@ ignore_imports = [
|
|
|
307
309
|
"flux_engine._vendor.flux_spec.enforce -> rfc8785",
|
|
308
310
|
"flux_engine._vendor.flux_spec.validate -> rfc8785",
|
|
309
311
|
]
|
|
310
|
-
#
|
|
311
|
-
#
|
|
312
|
-
#
|
|
313
|
-
#
|
|
314
|
-
# "error" in the case where the edge does NOT exist.
|
|
312
|
+
# "warn" (rather than the default "error") keeps this contract green when an
|
|
313
|
+
# ignored edge above matches nothing, for example if the vendored copy stops
|
|
314
|
+
# importing rfc8785. It only differs from "error" in the case where an edge
|
|
315
|
+
# does NOT exist.
|
|
315
316
|
unmatched_ignore_imports_alerting = "warn"
|
|
316
317
|
allow_indirect_imports = false
|
|
317
318
|
as_packages = true
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
"""Architecture gates: the import-linter contracts, plus a kernel AST scan.
|
|
6
6
|
|
|
7
7
|
Two independent checks of the same "kernel packages stay deterministic"
|
|
8
|
-
property
|
|
8
|
+
property:
|
|
9
9
|
|
|
10
10
|
1. The import-linter contracts in pyproject.toml (run as a subprocess --
|
|
11
11
|
the same `lint-imports` entry point `make ci-local` and CI use).
|
|
12
12
|
2. An AST scan asserting the kernel packages (core, world, runtime, expr,
|
|
13
13
|
seam) never call the wall clock, a UUID generator, or the stdlib
|
|
14
|
-
`random` module -- the "six deliberately broken kernels" idea
|
|
15
|
-
|
|
14
|
+
`random` module -- the "six deliberately broken kernels" idea
|
|
15
|
+
names exactly these as the ways a kernel silently loses
|
|
16
16
|
determinism (wall clock, uuid4 ids, ...). import-linter's forbidden
|
|
17
17
|
contract already bans importing the `random`/`uuid`/`time`/`os`/
|
|
18
18
|
`socket` *modules* from the kernel; this test is an independent,
|
|
@@ -23,6 +23,8 @@ from pathlib import Path
|
|
|
23
23
|
import pytest
|
|
24
24
|
import yaml
|
|
25
25
|
|
|
26
|
+
from flux_engine._links import DOCS_URL, ISSUES_URL
|
|
27
|
+
|
|
26
28
|
ROOT = Path(__file__).resolve().parent.parent
|
|
27
29
|
|
|
28
30
|
# Placeholder domains documentation is allowed to use in examples.
|
|
@@ -84,6 +86,28 @@ def test_citation_file_carries_the_required_keys() -> None:
|
|
|
84
86
|
assert data["authors"] and all(author.get("name") for author in data["authors"])
|
|
85
87
|
|
|
86
88
|
|
|
89
|
+
@pytest.mark.unit
|
|
90
|
+
def test_citation_file_names_this_release() -> None:
|
|
91
|
+
data = yaml.safe_load(_read("CITATION.cff"))
|
|
92
|
+
project = tomllib.loads(_read("pyproject.toml"))["project"]
|
|
93
|
+
assert data["version"] == project["version"], "move CITATION.cff with pyproject.toml"
|
|
94
|
+
assert data["license"] == project["license"]
|
|
95
|
+
heading = re.search(
|
|
96
|
+
rf"^## {re.escape(project['version'])} - (\d{{4}}-\d{{2}}-\d{{2}})$",
|
|
97
|
+
_read("CHANGELOG.md"),
|
|
98
|
+
re.MULTILINE,
|
|
99
|
+
)
|
|
100
|
+
assert heading, "CHANGELOG.md has no dated section for this version"
|
|
101
|
+
assert str(data["date-released"]) == heading.group(1)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pytest.mark.unit
|
|
105
|
+
def test_project_urls_name_the_published_docs_and_the_issue_tracker() -> None:
|
|
106
|
+
urls = tomllib.loads(_read("pyproject.toml"))["project"]["urls"]
|
|
107
|
+
assert urls["Documentation"] == DOCS_URL
|
|
108
|
+
assert urls["Issues"] == ISSUES_URL
|
|
109
|
+
|
|
110
|
+
|
|
87
111
|
@pytest.mark.unit
|
|
88
112
|
def test_code_of_conduct_is_the_covenant_with_every_placeholder_filled() -> None:
|
|
89
113
|
text = _read("CODE_OF_CONDUCT.md")
|
|
@@ -203,8 +203,8 @@ def test_main_says_what_to_install_when_uvx_is_missing(
|
|
|
203
203
|
def test_the_workflow_runs_the_make_target_and_keeps_macos_off_the_pull_request_path() -> None:
|
|
204
204
|
text = WORKFLOW.read_text(encoding="utf-8")
|
|
205
205
|
assert "run: make first-run" in text
|
|
206
|
-
# macOS
|
|
207
|
-
#
|
|
206
|
+
# macOS may only appear in the expression that is selected for the weekly
|
|
207
|
+
# and manual runs.
|
|
208
208
|
assert text.count("macos-latest") == 1
|
|
209
209
|
expression = text[text.index("include: >-") :]
|
|
210
210
|
assert expression.index("schedule") < expression.index("macos-latest")
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Copyright 2026 Agentics Transformation Limited
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""The repository's prose carries nothing that was only meant for the people building it.
|
|
6
|
+
|
|
7
|
+
A banner saying the repository is private, wording about a freeze on some
|
|
8
|
+
vocabulary, a job title, and a reference to a plan nobody outside the project can
|
|
9
|
+
read were all true or useful once, and they are wrong or confusing in a public
|
|
10
|
+
repository. Each pattern below is a leak this repository has had. A pattern here
|
|
11
|
+
turns the next one into a failing test instead of the next audit.
|
|
12
|
+
|
|
13
|
+
The files checked are the ones git tracks, plus any new file git does not ignore,
|
|
14
|
+
so a developer's virtual environment or build output is never read. A phrase
|
|
15
|
+
wrapped across two lines is still found, because the patterns run over the whole
|
|
16
|
+
text and let any white space separate the words.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
import subprocess
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Dict, Iterator, List
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
27
|
+
|
|
28
|
+
pytestmark = pytest.mark.unit
|
|
29
|
+
|
|
30
|
+
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
31
|
+
_SUFFIXES = frozenset({".md", ".py", ".toml", ".yml", ".yaml", ".cff"})
|
|
32
|
+
|
|
33
|
+
#: What each pattern catches. Keys read as the finding in a failure message.
|
|
34
|
+
LEAKS: Dict[str, "re.Pattern[str]"] = {
|
|
35
|
+
"a banner saying the repository is private": re.compile(
|
|
36
|
+
r"(?i)private\s+repo(?:sitory)?\s+only"
|
|
37
|
+
),
|
|
38
|
+
"wording about a freeze on vocabulary": re.compile(r"(?i)freeze\s+list|lifts?\s+the\s+freeze"),
|
|
39
|
+
"a job title in prose": re.compile(r"\bCEO\b"),
|
|
40
|
+
"a reference to a plan nobody outside the project can read": re.compile(
|
|
41
|
+
r"(?i)\b(?:approved|build)\s+plan\b"
|
|
42
|
+
),
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _text_files() -> Iterator[Path]:
|
|
47
|
+
try:
|
|
48
|
+
listing = subprocess.run(
|
|
49
|
+
["git", "ls-files", "-z", "--cached", "--others", "--exclude-standard"],
|
|
50
|
+
cwd=REPO_ROOT,
|
|
51
|
+
capture_output=True,
|
|
52
|
+
check=True,
|
|
53
|
+
).stdout.decode("utf-8")
|
|
54
|
+
except (OSError, subprocess.CalledProcessError):
|
|
55
|
+
pytest.skip("not a git checkout, so there is no list of files to check")
|
|
56
|
+
for name in sorted(filter(None, listing.split("\0"))):
|
|
57
|
+
path = REPO_ROOT / name
|
|
58
|
+
# This file names every pattern, so it would match itself.
|
|
59
|
+
if path.suffix in _SUFFIXES and path.is_file() and path != Path(__file__).resolve():
|
|
60
|
+
yield path
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_there_is_prose_to_check() -> None:
|
|
64
|
+
assert sum(1 for _ in _text_files()) > 100
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.parametrize("finding", sorted(LEAKS))
|
|
68
|
+
def test_the_prose_has_no_leak_of(finding: str) -> None:
|
|
69
|
+
pattern = LEAKS[finding]
|
|
70
|
+
hits: List[str] = []
|
|
71
|
+
for path in _text_files():
|
|
72
|
+
text = path.read_text(encoding="utf-8")
|
|
73
|
+
for match in pattern.finditer(text):
|
|
74
|
+
line = text.count("\n", 0, match.start()) + 1
|
|
75
|
+
hits.append(f"{path.relative_to(REPO_ROOT).as_posix()}:{line}: {match.group(0)!r}")
|
|
76
|
+
assert hits == [], f"{finding}:\n" + "\n".join(hits)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_a_phrase_wrapped_across_two_lines_is_found() -> None:
|
|
80
|
+
pattern = LEAKS["a reference to a plan nobody outside the project can read"]
|
|
81
|
+
assert pattern.search("The build\nplan requires a frozen grammar")
|
|
82
|
+
assert not pattern.search("The plan is built in the plan stage")
|
|
@@ -19,7 +19,7 @@ assert every consumer reads it rather than a copy.
|
|
|
19
19
|
``docs/``, so ``GOLDEN-CHANGELOG.md`` carried a banned word past a green
|
|
20
20
|
run of the lint. The scan now covers every Markdown file at the
|
|
21
21
|
repository root; the negative controls below prove it fires there, still
|
|
22
|
-
fires under ``docs/``, and still exempts the
|
|
22
|
+
fires under ``docs/``, and still exempts the
|
|
23
23
|
``docs/spec`` tree.
|
|
24
24
|
"""
|
|
25
25
|
|
|
@@ -101,7 +101,7 @@ def _fake_repo(root: Path) -> None:
|
|
|
101
101
|
docs.mkdir()
|
|
102
102
|
(docs / "public.md").write_text("this proves the docs scan still works\n")
|
|
103
103
|
(docs / "spec").mkdir()
|
|
104
|
-
(docs / "spec" / "x.md").write_text("this proves
|
|
104
|
+
(docs / "spec" / "x.md").write_text("this proves spec docs are exempt\n")
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
def test_scan_docs_covers_repository_root_markdown(tmp_path: Path, monkeypatch) -> None:
|
|
@@ -112,7 +112,7 @@ def test_scan_docs_covers_repository_root_markdown(tmp_path: Path, monkeypatch)
|
|
|
112
112
|
|
|
113
113
|
assert any(hit.startswith("GOLDEN-CHANGELOG.md:") for hit in hits), hits
|
|
114
114
|
assert any(hit.startswith("docs/public.md:") for hit in hits), hits
|
|
115
|
-
# The
|
|
115
|
+
# The specification tree stays exempt, and a non-Markdown file
|
|
116
116
|
# at the root is not swept in by the widening.
|
|
117
117
|
assert not any("docs/spec" in hit for hit in hits), hits
|
|
118
118
|
assert not any("NOTES.txt" in hit for hit in hits), hits
|
|
@@ -8,7 +8,7 @@ test_spec_shim.py already exercises flux_engine.spec.enforce end to end
|
|
|
8
8
|
(all 34 conformance vectors). These tests do the equivalent minimal smoke
|
|
9
9
|
check for the other two re-exported modules -- validate.py's offline
|
|
10
10
|
reference-validator surface and bundle.py's evidence-bundle surface --
|
|
11
|
-
without needing a full FLUX bundle fixture, which is out of scope
|
|
11
|
+
without needing a full FLUX bundle fixture, which is out of scope here.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
@@ -153,7 +153,7 @@ def test_all_34_vectors_pass_through_the_shim() -> None:
|
|
|
153
153
|
def test_a_fail_open_gate_fails_the_conformance_vectors() -> None:
|
|
154
154
|
"""A deliberately fail-open gate (always allows) must FAIL the vectors.
|
|
155
155
|
|
|
156
|
-
Regression guard
|
|
156
|
+
Regression guard in the spirit of the "six deliberately broken
|
|
157
157
|
kernels" idea, applied here to the enforcement gate: a gate that
|
|
158
158
|
always allows would pass no vector expecting a denial, proving the
|
|
159
159
|
vectors are a real oracle and not a rubber stamp that passes anything.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"""Startup budget gate: `import flux_engine.cli` must not pull numpy.
|
|
6
6
|
|
|
7
7
|
Mirrors forge-cli's tests/perf/test_startup_budget.py idea, scoped to
|
|
8
|
-
|
|
8
|
+
the CLI module itself: it must stay numpy-free on
|
|
9
9
|
import so `fluxsim --help` (and every other cold invocation) stays fast --
|
|
10
10
|
the CLI's command bodies do their heavy imports lazily, inside the
|
|
11
11
|
function that needs them, never at module scope.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|