hecks 2.8.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +50 -7
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +32 -100
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +149 -136
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +48 -38
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +16 -50
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +49 -67
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +39 -661
- data/lib/hecks/bluebook/hexagon.rb +18 -33
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +87 -352
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +122 -596
- data/lib/hecks/bluebook/pattern_subset.rb +49 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +27 -51
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +9 -99
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +5 -23
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +4 -6
- data/lib/hecks/cli/mcp.rb +5 -6
- data/lib/hecks/cli/model_check.rb +24 -88
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +223 -64
- data/lib/hecks/cli/project_diagrams.rb +4 -10
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +15 -61
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +7 -19
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -6
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +216 -73
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +14 -34
- data/lib/hecks/doors/handle.rb +206 -0
- data/lib/hecks/doors/json_door.rb +132 -0
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
- data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
- data/lib/hecks/doors/ruby_door.rb +77 -0
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +5 -72
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +23 -51
- data/lib/hecks/forms/app.rb +21 -76
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +31 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +19 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +47 -108
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +12 -44
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +40 -207
- data/lib/hecks/projections/deploy/lambda.rb +191 -708
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +3 -59
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +48 -147
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +22 -584
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +16 -43
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +13 -32
- data/lib/hecks/projections/reference.rb +4 -18
- data/lib/hecks/projections/rust_vocabulary.rb +13 -251
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +154 -400
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +5 -8
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +15 -9
- data/lib/hecks/release/runner/npm_publisher.rb +9 -53
- data/lib/hecks/release/runner/preflight.rb +29 -20
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +31 -23
- data/lib/hecks/release/runner.rb +60 -38
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +15 -39
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +50 -104
- data/lib/hecks/runtime/dispatcher.rb +134 -243
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +14 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +109 -194
- data/lib/hecks/runtime/outbox.rb +39 -262
- data/lib/hecks/runtime/policy_interpreter.rb +43 -202
- data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
- data/lib/hecks/runtime/query_interpreter.rb +122 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +28 -87
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +213 -227
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +156 -247
- data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +162 -760
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +15 -84
- data/lib/hecks/runtime.rb +35 -69
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +155 -582
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +52 -90
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +478 -12
- data/lib/hecks/facade/cli_door.rb +0 -178
- data/lib/hecks/facade/cli_runner.rb +0 -271
- data/lib/hecks/facade/handle.rb +0 -293
- data/lib/hecks/facade/json_door.rb +0 -247
- data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
- data/lib/hecks/facade/surface/chapter.rb +0 -116
- data/lib/hecks/facade/surface.rb +0 -61
- data/lib/hecks/mcp_door_scope.rb +0 -176
|
@@ -3,45 +3,8 @@ require "digest"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Runtime
|
|
6
|
-
# The storage-shape projection of a bluebook:
|
|
7
|
-
#
|
|
8
|
-
# their attributes (with full value-object/entity structure and
|
|
9
|
-
# cardinality), references, the lifecycle field, and the identity
|
|
10
|
-
# paths. Everything behavioral — commands, invariants, queries,
|
|
11
|
-
# policies, lifecycle transitions, defaults, descriptions, comments,
|
|
12
|
-
# the declared routing `version:` — is excluded, so editing behavior
|
|
13
|
-
# never bumps an era and editing shape always does.
|
|
14
|
-
#
|
|
15
|
-
# ## Constraints left out on purpose
|
|
16
|
-
#
|
|
17
|
-
# Three attribute facts on the wire are constraints on persisted
|
|
18
|
-
# values, not behavior, and are still excluded — each decided, not
|
|
19
|
-
# overlooked:
|
|
20
|
-
#
|
|
21
|
-
# `optional` — required-ness is enforced at dispatch; stored rows
|
|
22
|
-
# are never re-validated on read, so flipping it
|
|
23
|
-
# strands nothing already written. Excluded.
|
|
24
|
-
# `pattern` — same argument: a fact about what may be written
|
|
25
|
-
# next, not about what was stored. Excluded.
|
|
26
|
-
# `admits` — the sharpest of the three: narrowing a closed set
|
|
27
|
-
# can strand stored rows outside it, and the wire
|
|
28
|
-
# carries only the set's name, so a set whose members
|
|
29
|
-
# changed under a stable name is invisible even to a
|
|
30
|
-
# projection that included the fact (the same lesson
|
|
31
|
-
# recursive value-object drift taught). Excluded, and
|
|
32
|
-
# named as a gap: constraint tightening has no
|
|
33
|
-
# translation-rule vocabulary to acknowledge it yet,
|
|
34
|
-
# so including it would mint era bumps nothing can
|
|
35
|
-
# explain. When the translation language grows a
|
|
36
|
-
# constraint-acknowledgment rule, `admits` (by member
|
|
37
|
-
# list, not by name) is first in line, and that
|
|
38
|
-
# change bumps `FORM_VERSION`.
|
|
39
|
-
#
|
|
40
|
-
# ## Structural comparison over the dump form
|
|
41
|
-
#
|
|
42
|
-
# Projection runs over the canonical dump form (`to_h`, JSON
|
|
43
|
-
# round-tripped), so a verdict depends only on the IR — never on live
|
|
44
|
-
# object graphs. Structural comparison only, never a hash comparison.
|
|
6
|
+
# The storage-shape projection of a bluebook: only the IR parts that decide how persisted
|
|
7
|
+
# data looks, so behavior edits never bump an era and shape edits always do.
|
|
45
8
|
module StorageShape
|
|
46
9
|
module_function
|
|
47
10
|
|
|
@@ -67,10 +30,7 @@ module Hecks
|
|
|
67
30
|
# @return [Boolean] true when both project to an equal structure
|
|
68
31
|
def same?(held, current) = project(held) == project(current)
|
|
69
32
|
|
|
70
|
-
# The canonical serialization
|
|
71
|
-
# — the one moment identity is computed. Nothing ever recomputes a
|
|
72
|
-
# stored era name to verify it, so this form can evolve freely.
|
|
73
|
-
#
|
|
33
|
+
# The canonical serialization hashed at mint time; stored era names are never recomputed.
|
|
74
34
|
# @param bluebook [Bluebook::Chapter] the bluebook to serialize
|
|
75
35
|
# @return [String] compact JSON text of `project(bluebook)`
|
|
76
36
|
def canonical(bluebook) = JSON.generate(project(bluebook))
|
|
@@ -89,12 +49,8 @@ module Hecks
|
|
|
89
49
|
# @return [String] the first `LABEL_LENGTH` hex characters of `mint_hash(bluebook)`
|
|
90
50
|
def mint_label(bluebook) = mint_hash(bluebook)[0, LABEL_LENGTH]
|
|
91
51
|
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# if each name records which form minted it, so v1-named and
|
|
95
|
-
# v2-named eras coexist legibly. Stored beside every minted hash
|
|
96
|
-
# (names.tsv fourth field / hecks_eras.canon_form); bump this in
|
|
97
|
-
# the same change that alters project/canonical output.
|
|
52
|
+
# Version of the canonical form, stored beside each minted hash; bump it with any
|
|
53
|
+
# change to project/canonical output.
|
|
98
54
|
FORM_VERSION = 1
|
|
99
55
|
|
|
100
56
|
# Projects one dumped aggregate down to its identity, lifecycle field and attributes.
|
|
@@ -108,11 +64,7 @@ module Hecks
|
|
|
108
64
|
def project_aggregate(aggregate)
|
|
109
65
|
{
|
|
110
66
|
"name" => aggregate["name"],
|
|
111
|
-
#
|
|
112
|
-
# order is semantic (the paths join in order to form the id).
|
|
113
|
-
# No "id" fallback: an aggregate that declares nothing has [],
|
|
114
|
-
# and that is a real declared state, distinct from an aggregate
|
|
115
|
-
# identified by a field named "id".
|
|
67
|
+
# Declaration order is semantic (paths join in order to form the id); no "id" fallback.
|
|
116
68
|
"identity" => Array(aggregate["identified_by"]).map(&:to_s),
|
|
117
69
|
"lifecycle_field" => aggregate.dig("lifecycle", "field"),
|
|
118
70
|
"attributes" => (aggregate["attributes"] || [])
|
|
@@ -121,12 +73,13 @@ module Hecks
|
|
|
121
73
|
}
|
|
122
74
|
end
|
|
123
75
|
|
|
76
|
+
# `optional`, `pattern` and `admits` are left out: they constrain future writes, not
|
|
77
|
+
# stored rows. Including `admits` needs a translation rule to acknowledge it first.
|
|
78
|
+
#
|
|
124
79
|
# Projects one dumped attribute to its name, cardinality and full type signature.
|
|
125
80
|
#
|
|
126
|
-
# @param aggregate [Hash{String => Object}] the dumped aggregate that owns the attribute
|
|
127
|
-
#
|
|
128
|
-
# @param attribute [Hash{String => Object}] the dumped attribute, read for `"name"`,
|
|
129
|
-
# `"list"` and `"type"`
|
|
81
|
+
# @param aggregate [Hash{String => Object}] the dumped aggregate that owns the attribute
|
|
82
|
+
# @param attribute [Hash{String => Object}] the dumped attribute
|
|
130
83
|
# @param seen [Array<String>] type names already being expanded, which stops a
|
|
131
84
|
# self-referencing type from recursing forever
|
|
132
85
|
# @return [Hash{String => Object}] `"name"` (String), `"list"` (Boolean) and `"type"`
|
|
@@ -139,11 +92,8 @@ module Hecks
|
|
|
139
92
|
}
|
|
140
93
|
end
|
|
141
94
|
|
|
142
|
-
# A
|
|
143
|
-
#
|
|
144
|
-
# attributes with the same declared type name but different
|
|
145
|
-
# internals are never mistaken for unchanged.
|
|
146
|
-
#
|
|
95
|
+
# A primitive's type name, or for a value object or entity the name plus its members'
|
|
96
|
+
# signatures, so same-named types with different internals never look unchanged.
|
|
147
97
|
# @param aggregate [Hash{String => Object}] the dumped aggregate whose value objects and
|
|
148
98
|
# entities are searched for `type_name`
|
|
149
99
|
# @param type_name [String] the attribute's declared type name
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "date"
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require_relative "audit/approval_digest"
|
|
5
|
+
require_relative "../../../../../version"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Translation
|
|
9
|
+
# The committed form of an edge's approval: `translations/<edge>.approval`, a JSON file beside
|
|
10
|
+
# the edge that a reviewer sees in the same diff.
|
|
11
|
+
#
|
|
12
|
+
# It binds to the edge's content digest and not to the journal's tip, so a production journal
|
|
13
|
+
# that keeps writing between the commit and the deploy does not void it. An edge with a compute
|
|
14
|
+
# or rekey rule also carries the rehearsal a person ran against real data, since the audit's
|
|
15
|
+
# samples are that edge's only other verification.
|
|
16
|
+
module ApprovalFile
|
|
17
|
+
EXTENSION = ".approval".freeze
|
|
18
|
+
|
|
19
|
+
# The keys of a rehearsal block; every one is required when the block is required.
|
|
20
|
+
#
|
|
21
|
+
# `host_version` is the Hecks release the rehearsal ran on, and the gate checks it: a
|
|
22
|
+
# rehearsal counts only on a host whose release shares its `major.minor` (see
|
|
23
|
+
# `host_compatible?`).
|
|
24
|
+
REHEARSAL_KEYS = %w[snapshot host_version result at].freeze
|
|
25
|
+
|
|
26
|
+
# How a `host_version` reads: `major.minor`, an optional patch, an optional pre-release or
|
|
27
|
+
# build suffix. Only the first two numbers take part in the comparison.
|
|
28
|
+
HOST_LINE = /\A(\d+)\.(\d+)(?:\.\d+)?(?:[-+][0-9A-Za-z.+-]+)?\z/
|
|
29
|
+
|
|
30
|
+
# The release the running host reports: the Hecks release this code was built for. The Rust
|
|
31
|
+
# host embeds the same string from `rust/host/HECKS_RELEASE`, and a spec fails when the two
|
|
32
|
+
# drift.
|
|
33
|
+
HOST_RELEASE = Hecks::VERSION
|
|
34
|
+
|
|
35
|
+
# An ISO 8601 time: `2026-09-28T12:30:00Z`, with optional fraction and `+HH:MM` offset. The
|
|
36
|
+
# host's approval.rs accepts the same shape.
|
|
37
|
+
TIMESTAMP = /\A(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})\z/
|
|
38
|
+
|
|
39
|
+
extend Audit::ApprovalDigest
|
|
40
|
+
|
|
41
|
+
module_function
|
|
42
|
+
|
|
43
|
+
# Names an edge by the labels it joins; labels are hex, so the dash cannot be part of one.
|
|
44
|
+
#
|
|
45
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
46
|
+
# @return [String] `<from>-<to>`
|
|
47
|
+
def edge_name(edge) = "#{edge.from}-#{edge.to}"
|
|
48
|
+
|
|
49
|
+
# Where an edge's approval lives.
|
|
50
|
+
#
|
|
51
|
+
# @param directory [String] the domain's bluebook directory
|
|
52
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
53
|
+
# @return [String] `<directory>/translations/<edge>.approval`
|
|
54
|
+
def path_for(directory, edge) = File.join(directory, "translations", "#{edge_name(edge)}#{EXTENSION}")
|
|
55
|
+
|
|
56
|
+
# Whether the edge carries a rule whose only verification is a human's review of samples.
|
|
57
|
+
#
|
|
58
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
59
|
+
# @return [Boolean] true when any aggregate declares a compute or a rekey
|
|
60
|
+
def needs_rehearsal?(edge)
|
|
61
|
+
edge.aggregates.any? { |declared| !declared.computes.empty? || !declared.rekeys.empty? }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Whether a rehearsal block records a run that passed, with every field named.
|
|
65
|
+
#
|
|
66
|
+
# @param rehearsal [Hash, nil] the block, string-keyed as it reads from JSON
|
|
67
|
+
# @return [Boolean] true when all of `REHEARSAL_KEYS` are non-empty Strings and `result` is
|
|
68
|
+
# `pass`
|
|
69
|
+
def rehearsed?(rehearsal)
|
|
70
|
+
return false unless rehearsal.is_a?(Hash)
|
|
71
|
+
|
|
72
|
+
REHEARSAL_KEYS.all? { |key| named?(rehearsal[key]) } && rehearsal["result"] == "pass"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The `major.minor` a version names.
|
|
76
|
+
#
|
|
77
|
+
# @param version [Object] a `host_version` as it reads from JSON
|
|
78
|
+
# @return [Array<Integer>, nil] `[major, minor]`, or nil when it is not a version
|
|
79
|
+
def release_line(version)
|
|
80
|
+
match = HOST_LINE.match(version) if version.is_a?(String)
|
|
81
|
+
match && [match[1].to_i, match[2].to_i]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Whether a rehearsal ran on a host compatible with the running one.
|
|
85
|
+
#
|
|
86
|
+
# The rule is the smallest sound one: equal `major.minor`. A patch release does not change
|
|
87
|
+
# what a mint does, so a rehearsal survives it; a minor or major release may, so a rehearsal
|
|
88
|
+
# from an older host (or a newer one, which proves nothing about this one) does not.
|
|
89
|
+
#
|
|
90
|
+
# @param rehearsal [Hash] a rehearsal block, string-keyed
|
|
91
|
+
# @param host_version [String] the running host's release
|
|
92
|
+
# @return [Boolean] true when both versions parse and share `major.minor`
|
|
93
|
+
def host_compatible?(rehearsal, host_version = HOST_RELEASE)
|
|
94
|
+
line = release_line(rehearsal["host_version"])
|
|
95
|
+
!line.nil? && line == release_line(host_version)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# The refusal for a rehearsal that ran on another host line; rust/host words it the same.
|
|
99
|
+
#
|
|
100
|
+
# @param rehearsal [Hash] a rehearsal block, string-keyed
|
|
101
|
+
# @param host_version [String] the running host's release
|
|
102
|
+
# @return [String] names both versions
|
|
103
|
+
def host_refusal(rehearsal, host_version = HOST_RELEASE)
|
|
104
|
+
line = release_line(host_version)&.join(".")
|
|
105
|
+
"the rehearsal ran on Hecks #{rehearsal['host_version']}, but this host is Hecks #{host_version}; " \
|
|
106
|
+
"a rehearsal counts only on a host of the same major.minor (#{line}.x) — " \
|
|
107
|
+
"re-run the rehearsal on this host and approve again"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Whether a value is a String with something in it; a number or nil names nothing.
|
|
111
|
+
#
|
|
112
|
+
# @param value [Object] a field as it reads from JSON
|
|
113
|
+
# @return [Boolean] true for a String that is not blank
|
|
114
|
+
def named?(value) = value.is_a?(String) && !value.strip.empty?
|
|
115
|
+
|
|
116
|
+
# Whether a value is an ISO 8601 time that exists on the calendar.
|
|
117
|
+
#
|
|
118
|
+
# @param value [Object] a field as it reads from JSON
|
|
119
|
+
# @return [Boolean] true for a String of the `TIMESTAMP` shape with a real date and clock time
|
|
120
|
+
def timestamp?(value)
|
|
121
|
+
return false unless value.is_a?(String) && (match = TIMESTAMP.match(value))
|
|
122
|
+
|
|
123
|
+
year, month, day, hour, minute, second = match.captures.map(&:to_i)
|
|
124
|
+
Date.valid_date?(year, month, day) && hour < 24 && minute < 60 && second < 60
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Whether an approval names who approved it and when, the two things a reviewer signs.
|
|
128
|
+
#
|
|
129
|
+
# @param approval [Hash] the file, string-keyed as it reads from JSON
|
|
130
|
+
# @return [Boolean] true when `approved_by` is a non-empty String and `approved_at` a time
|
|
131
|
+
def attributed?(approval)
|
|
132
|
+
named?(approval["approved_by"]) && timestamp?(approval["approved_at"])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Builds the JSON document of one approval.
|
|
136
|
+
#
|
|
137
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
138
|
+
# @param approved_by [String] who approved it, from their git identity
|
|
139
|
+
# @param approved_at [String] when, as an ISO 8601 UTC time
|
|
140
|
+
# @param rehearsal [Hash{String => String}, nil] the block; required for a compute or rekey
|
|
141
|
+
# @return [Hash{String => Object}] `edge`, `edge_digest`, `approved_by`, `approved_at`, and
|
|
142
|
+
# `rehearsal` when one was given
|
|
143
|
+
# @raise [ArgumentError] if `approved_by` is blank or `approved_at` is not a time, or if the
|
|
144
|
+
# edge needs a rehearsal and none that passed was given
|
|
145
|
+
def build(edge:, approved_by:, approved_at:, rehearsal: nil)
|
|
146
|
+
unless attributed?("approved_by" => approved_by, "approved_at" => approved_at)
|
|
147
|
+
raise ArgumentError, "an approval names who approved it (approved_by, your git identity) " \
|
|
148
|
+
"and when (approved_at, an ISO 8601 time)"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
if needs_rehearsal?(edge) && !rehearsed?(rehearsal)
|
|
152
|
+
raise ArgumentError, "an edge with a compute or rekey rule is approved on a rehearsal that passed: " \
|
|
153
|
+
"name the snapshot, the host version, the result (pass) and when it ran"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
document = { "edge" => edge_name(edge), "edge_digest" => edge_digest(edge),
|
|
157
|
+
"approved_by" => approved_by, "approved_at" => approved_at }
|
|
158
|
+
document["rehearsal"] = rehearsal.slice(*REHEARSAL_KEYS) if rehearsal
|
|
159
|
+
document
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Writes an edge's approval file, replacing an earlier approval of the same edge.
|
|
163
|
+
#
|
|
164
|
+
# @param directory [String] the domain's bluebook directory
|
|
165
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
166
|
+
# @param document [Hash{String => Object}] what `build` answered
|
|
167
|
+
# @return [String] the path written
|
|
168
|
+
def write!(directory, edge, document)
|
|
169
|
+
path = path_for(directory, edge)
|
|
170
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
171
|
+
File.write(path, "#{JSON.pretty_generate(document)}\n")
|
|
172
|
+
path
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Reads every committed approval of a domain.
|
|
176
|
+
#
|
|
177
|
+
# @param directory [String] the domain's bluebook directory
|
|
178
|
+
# @return [Array<Hash{String => Object}>] each parsed file; one that is not JSON is skipped,
|
|
179
|
+
# since a file that cannot be read approves nothing
|
|
180
|
+
def read_all(directory)
|
|
181
|
+
Dir[File.join(directory, "translations", "*#{EXTENSION}")].filter_map do |path|
|
|
182
|
+
parsed = JSON.parse(File.read(path))
|
|
183
|
+
parsed if parsed.is_a?(Hash)
|
|
184
|
+
rescue JSON::ParserError
|
|
185
|
+
nil
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# The committed approval that lets an edge mint, if there is one.
|
|
190
|
+
#
|
|
191
|
+
# @param directory [String, nil] the domain's bluebook directory
|
|
192
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
193
|
+
# @param host_version [String] the running host's release
|
|
194
|
+
# @return [Hash{String => Object}, nil] an approval whose digest is the edge's, that names
|
|
195
|
+
# who approved it and when, and whose rehearsal passed on a compatible host when the edge
|
|
196
|
+
# needs one; nil when none applies
|
|
197
|
+
def applicable(directory, edge, host_version: HOST_RELEASE)
|
|
198
|
+
return unless directory
|
|
199
|
+
|
|
200
|
+
digest = edge_digest(edge)
|
|
201
|
+
read_all(directory).find do |approval|
|
|
202
|
+
approval["edge_digest"] == digest && attributed?(approval) &&
|
|
203
|
+
(!needs_rehearsal?(edge) ||
|
|
204
|
+
(rehearsed?(approval["rehearsal"]) && host_compatible?(approval["rehearsal"], host_version)))
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Why a committed approval that covers the edge was still not applied, when the only thing
|
|
209
|
+
# wrong is the host it was rehearsed on.
|
|
210
|
+
#
|
|
211
|
+
# @param directory [String, nil] the domain's bluebook directory
|
|
212
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
213
|
+
# @param host_version [String] the running host's release
|
|
214
|
+
# @return [String, nil] `host_refusal`'s text, or nil when no such approval exists
|
|
215
|
+
def host_mismatch(directory, edge, host_version: HOST_RELEASE)
|
|
216
|
+
return unless directory && needs_rehearsal?(edge)
|
|
217
|
+
|
|
218
|
+
digest = edge_digest(edge)
|
|
219
|
+
stale = read_all(directory).find do |approval|
|
|
220
|
+
approval["edge_digest"] == digest && attributed?(approval) && rehearsed?(approval["rehearsal"]) &&
|
|
221
|
+
!host_compatible?(approval["rehearsal"], host_version)
|
|
222
|
+
end
|
|
223
|
+
host_refusal(stale["rehearsal"], host_version) if stale
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
@@ -4,23 +4,8 @@ require_relative "../../../../../../projector/exporter"
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Translation
|
|
6
6
|
module Audit
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# For the five portable rule kinds the mint verifies the edge
|
|
10
|
-
# mechanically (Layer 2 is the cross-execution equivalence gate).
|
|
11
|
-
# A compute has no mechanical verification — the Layer-3 sample a
|
|
12
|
-
# human reads is the only one there is — so a compute edge cannot
|
|
13
|
-
# mint until someone has run `bin/translation_audit … --approve`.
|
|
14
|
-
#
|
|
15
|
-
# The approval binds to what was actually reviewed, on both axes:
|
|
16
|
-
# a content digest of the parsed edge (change the edge's meaning
|
|
17
|
-
# and the approval lapses; a comment does not), and the journal's
|
|
18
|
-
# high-water ordinal at review time, recorded in the target
|
|
19
|
-
# database — a token in the repo could not bind to the data, and
|
|
20
|
-
# samples reviewed against staging or against production-as-of-T
|
|
21
|
-
# say nothing about a database that has moved on. Mint stays
|
|
22
|
-
# non-interactive and its lock stays short; the human decision
|
|
23
|
-
# happens in the audit tool, where the samples are.
|
|
7
|
+
# The human gate: a compute edge cannot mint until `hecks audit_translation --approve`
|
|
8
|
+
# binds an approval to the edge's content digest and the journal's ordinal at review.
|
|
24
9
|
module ApprovalDigest
|
|
25
10
|
# Fingerprints a parsed translation edge, so an approval lapses when the edge's
|
|
26
11
|
# meaning changes but not when only a comment does.
|
|
@@ -6,12 +6,8 @@ require_relative "../../../../../../bluebook/model_check"
|
|
|
6
6
|
module Hecks
|
|
7
7
|
module Translation
|
|
8
8
|
module Audit
|
|
9
|
-
# Layer 1
|
|
10
|
-
#
|
|
11
|
-
# This is also where a new, stricter invariant that old records
|
|
12
|
-
# violate surfaces — there is no "grandfather old records"
|
|
13
|
-
# construct, and the remedy is relaxing the invariant or explicit
|
|
14
|
-
# remediation, never a translation rule.
|
|
9
|
+
# Layer 1: every translated state must pass the new era's types, invariants and lifecycle.
|
|
10
|
+
# Old records that violate a stricter invariant surface here; no translation rule fixes them.
|
|
15
11
|
module LayerOne
|
|
16
12
|
# Hydrates every translated state as a current-era instance and records each one
|
|
17
13
|
# the era's types, invariants or lifecycle refuse.
|
|
@@ -28,14 +24,7 @@ module Hecks
|
|
|
28
24
|
next unless lifecycle
|
|
29
25
|
|
|
30
26
|
held = instance[lifecycle.field]
|
|
31
|
-
# `Lifecycle#states`
|
|
32
|
-
# legitimately declared just as a `from:` (a terminal
|
|
33
|
-
# transition's source, never anyone's target) is real and
|
|
34
|
-
# reachable but invisible to it. `ModelCheck.full_states`
|
|
35
|
-
# is the full declared set (default, every target, and
|
|
36
|
-
# every from) that `fuzzing/properties.rb`'s own replay
|
|
37
|
-
# check already uses for this identical question — see its
|
|
38
|
-
# comment on this same hole.
|
|
27
|
+
# `Lifecycle#states` omits states declared only as a `from:`; `full_states` has them.
|
|
39
28
|
allowed = Bluebook::ModelCheck.full_states(lifecycle)
|
|
40
29
|
unless held.nil? || allowed.include?(held.to_s)
|
|
41
30
|
violations << "#{aggregate.name}##{id}: #{lifecycle.field} is #{held.inspect}, " \
|
|
@@ -4,48 +4,27 @@ require_relative "../../lineage"
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Translation
|
|
6
6
|
module Audit
|
|
7
|
-
# Layer 2
|
|
8
|
-
# leftover source keys, and id-set conservation across the edge.
|
|
7
|
+
# Layer 2: from the edge alone, per-rule value preservation and id-set conservation.
|
|
9
8
|
module LayerTwo
|
|
10
9
|
# Checks one aggregate's records across the edge for id conservation and, where a
|
|
11
10
|
# per-record comparison is possible, agreement with the reference transform.
|
|
12
11
|
#
|
|
13
|
-
#
|
|
14
|
-
# against the reference transform in full — never rule by rule in
|
|
15
|
-
# isolation, because rules interact (a rename whose value a later
|
|
16
|
-
# move partially consumes preserves exactly what the transform
|
|
17
|
-
# says it preserves, no more). This makes every mint a run of the
|
|
18
|
-
# cross-execution equivalence gate for the five portable rule
|
|
19
|
-
# kinds: the compiled SQL produced `after`; the port's entry-JSON
|
|
20
|
-
# transform produces `expected`; they must agree byte-for-byte on
|
|
21
|
-
# every path a compute doesn't own. Compute paths are exempt — the
|
|
22
|
-
# SQL is their only implementation, and the Layer-3 sample is
|
|
23
|
-
# their only review. A rekeyed aggregate is exempt from this whole
|
|
24
|
-
# per-record check, for the same reason and one more: there is no
|
|
25
|
-
# old-id → new-id correspondence to look `after` up by once the id
|
|
26
|
-
# itself is what changed.
|
|
12
|
+
# Compute paths and rekeyed aggregates are exempt from the comparison.
|
|
27
13
|
#
|
|
28
14
|
# @param violations [Array<String>] collector this method appends messages to
|
|
29
15
|
# @param aggregate [Bluebook::Aggregate] the current era's IR for the aggregate
|
|
30
|
-
# @param declared [Bluebook::TranslationAggregate, nil]
|
|
31
|
-
# aggregate; nil limits the check to id conservation
|
|
16
|
+
# @param declared [Bluebook::TranslationAggregate, nil] nil limits the check to ids
|
|
32
17
|
# @param before [Hash{String => Hash}] source state per record id, as parsed JSON
|
|
33
18
|
# @param after [Hash{String => Hash}] translated state per record id, as parsed JSON
|
|
34
19
|
# @return [void]
|
|
35
|
-
# @raise [Runtime::WiringError] if the reference transform cannot translate
|
|
36
|
-
# state: a convert meets an unmapped value, or a move nests under a non-Hash
|
|
20
|
+
# @raise [Runtime::WiringError] if the reference transform cannot translate `before`
|
|
37
21
|
def layer_two!(violations, aggregate, declared, before, after)
|
|
38
22
|
rekeyed = declared && !declared.rekeys.empty?
|
|
39
23
|
|
|
40
24
|
check_id_conservation!(violations, aggregate, before, after, rekeyed: rekeyed)
|
|
41
25
|
|
|
42
26
|
return unless declared
|
|
43
|
-
#
|
|
44
|
-
# in Ruby (the rekey's SQL is its only implementation, same as
|
|
45
|
-
# compute's) — exempt from the per-record equivalence gate for
|
|
46
|
-
# the same reason compute paths already are, extended to the
|
|
47
|
-
# whole record since an old-id lookup into `after` can never
|
|
48
|
-
# succeed once the id itself has changed.
|
|
27
|
+
# A rekey's SQL is its only implementation and `after` cannot be looked up by old id.
|
|
49
28
|
return if rekeyed
|
|
50
29
|
|
|
51
30
|
check_value_preservation!(violations, aggregate, declared, before, after)
|
|
@@ -53,12 +32,6 @@ module Hecks
|
|
|
53
32
|
|
|
54
33
|
# Records a violation when the edge loses, gains or collides record ids.
|
|
55
34
|
#
|
|
56
|
-
# Record-count / id-set conservation — one of the two properties
|
|
57
|
-
# this module's own header names, and independent of the other
|
|
58
|
-
# (per-rule value preservation, below): it needs only `before`,
|
|
59
|
-
# `after`, and whether the edge rekeyed, never the declared rules
|
|
60
|
-
# themselves.
|
|
61
|
-
#
|
|
62
35
|
# @param violations [Array<String>] collector this method appends at most one message to
|
|
63
36
|
# @param aggregate [Bluebook::Aggregate] the aggregate, named in the message
|
|
64
37
|
# @param before [Hash{String => Hash}] source state per record id
|
|
@@ -67,13 +40,7 @@ module Hecks
|
|
|
67
40
|
# counts instead of id sets
|
|
68
41
|
# @return [void]
|
|
69
42
|
def check_id_conservation!(violations, aggregate, before, after, rekeyed:)
|
|
70
|
-
# A rekey
|
|
71
|
-
# point) — set-equality would flag every honest rekey as data
|
|
72
|
-
# loss. What must still hold is record count: a botched rekey
|
|
73
|
-
# colliding two distinct old ids onto one new id, or dropping one
|
|
74
|
-
# (its SQL returning NULL), shows up as the count going down —
|
|
75
|
-
# caught here without needing to track the old→new mapping
|
|
76
|
-
# itself.
|
|
43
|
+
# A rekey changes the id set, so compare counts: a collision or a NULL id lowers it.
|
|
77
44
|
if rekeyed
|
|
78
45
|
unless before.keys.size == after.keys.size
|
|
79
46
|
violations << "#{aggregate.name}: the record count changed across a rekeying edge " \
|
|
@@ -88,15 +55,14 @@ module Hecks
|
|
|
88
55
|
end
|
|
89
56
|
end
|
|
90
57
|
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
# that second guard); this method assumes both are false.
|
|
58
|
+
# Records a violation for each record whose translated state diverges from the reference.
|
|
59
|
+
# Assumes the edge is declared and does not rekey.
|
|
60
|
+
#
|
|
95
61
|
# @param violations [Array<String>] mutated in place with one message per divergent id
|
|
96
62
|
# @param aggregate [Bluebook::Aggregate] the aggregate being audited
|
|
97
63
|
# @param declared [Bluebook::Translation] the declared translation to check against
|
|
98
|
-
# @param before [Hash{String => Hash}]
|
|
99
|
-
# @param after [Hash{String => Hash}]
|
|
64
|
+
# @param before [Hash{String => Hash}] source records, keyed by id
|
|
65
|
+
# @param after [Hash{String => Hash}] translated records, keyed by id
|
|
100
66
|
# @return [void]
|
|
101
67
|
def check_value_preservation!(violations, aggregate, declared, before, after)
|
|
102
68
|
rules = Ports::Persistence::Lineage.from_declared(declared, aggregate.name)
|
|
@@ -124,19 +90,8 @@ module Hecks
|
|
|
124
90
|
|
|
125
91
|
# Removes the paths a compute owns from a normalized state, in place.
|
|
126
92
|
#
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
# ("price_cents") is itself the compute's entire value — dropping
|
|
130
|
-
# the whole top-level key is correct, there's nothing else there
|
|
131
|
-
# to check. A dotted path ("price.cents") only owns that one
|
|
132
|
-
# member of the value object it reaches into; every sibling
|
|
133
|
-
# member (e.g. "price.currency") is untouched by the compute and
|
|
134
|
-
# must stay subject to the equivalence check below. Blanket-
|
|
135
|
-
# dropping the whole top-level key for a dotted compute would
|
|
136
|
-
# exempt the entire attribute — silent data loss elsewhere in the
|
|
137
|
-
# same value object (a migration that nulls or drops a sibling
|
|
138
|
-
# field) would produce zero violations, defeating the one gate
|
|
139
|
-
# whose entire purpose is to catch exactly that.
|
|
93
|
+
# A dotted path removes only its own member, never the whole top-level key, so sibling
|
|
94
|
+
# members stay under the equivalence check and silent loss there is still caught.
|
|
140
95
|
#
|
|
141
96
|
# @param state [Hash{String => Object}] a normalized state; mutated
|
|
142
97
|
# @param paths [Array<String>] bare (`"price_cents"`) or dotted (`"price.cents"`)
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Translation
|
|
3
3
|
module Audit
|
|
4
|
-
# New-era attributes that nothing feeds:
|
|
5
|
-
#
|
|
6
|
-
# A report, not a violation — the remedy is a `default:` on the
|
|
7
|
-
# attribute, and the loud refusal for a required one comes from
|
|
8
|
-
# Layer 1 the moment an invariant reads it.
|
|
4
|
+
# New-era attributes that nothing feeds: no translated state, rule or default supplies them.
|
|
5
|
+
# A report, not a violation; a required one is refused by Layer 1 once an invariant reads it.
|
|
9
6
|
module UnfedReport
|
|
10
7
|
# Lists the current era's attributes that no rule, default or translated record feeds.
|
|
11
8
|
#
|
|
12
|
-
# `fed` build-up plus one ordered guard chain per attribute
|
|
13
|
-
# (already fed, has a default, actually present in some record, no
|
|
14
|
-
# records to check at all) answering a single question — "is
|
|
15
|
-
# anything, ever, going to feed this field" — where each `next`
|
|
16
|
-
# rules out one way the answer is "not unfed after all" before the
|
|
17
|
-
# next is even worth asking. Splitting the guards out would just
|
|
18
|
-
# turn each into a same-shaped one-line predicate call.
|
|
19
|
-
#
|
|
20
9
|
# @param aggregate [Bluebook::Aggregate] the current era's IR for the aggregate
|
|
21
10
|
# @param declared [Bluebook::TranslationAggregate, nil] this edge's rules; the
|
|
22
11
|
# destinations of its renames, moves, converts and computes count as fed
|
|
@@ -57,10 +46,7 @@ module Hecks
|
|
|
57
46
|
path.to_s.split(".").reduce(state) do |node, segment|
|
|
58
47
|
break nil unless node.is_a?(Hash)
|
|
59
48
|
|
|
60
|
-
# `key
|
|
61
|
-
# `false` genuinely held at this path must not fall through
|
|
62
|
-
# to the other spelling (usually absent) and read as `nil`,
|
|
63
|
-
# which would wrongly mark a `false`-valued attribute "unfed".
|
|
49
|
+
# `key?`, not `||`: a held `false` must not fall through and read as nil (unfed).
|
|
64
50
|
node.key?(segment) ? node[segment] : node[segment.to_sym]
|
|
65
51
|
end
|
|
66
52
|
end
|
|
@@ -7,13 +7,8 @@ require_relative "audit/approval_digest"
|
|
|
7
7
|
|
|
8
8
|
module Hecks
|
|
9
9
|
module Translation
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
# rules), audit/layer_two.rb (the edge against the reference
|
|
13
|
-
# transform), audit/unfed_report.rb (what nothing feeds), and
|
|
14
|
-
# audit/approval_digest.rb (the human gate's binding). Layer 3 — the
|
|
15
|
-
# before/after sample a human approves, intent not being derivable —
|
|
16
|
-
# is assembled right here in `check`.
|
|
10
|
+
# Derives the audit's assertions per layer (audit/layer_one, layer_two, unfed_report,
|
|
11
|
+
# approval_digest); Layer 3, the human-approved sample, is assembled in `check`.
|
|
17
12
|
module Audit
|
|
18
13
|
Verdict = Struct.new(:violations, :dropped, :unfed, :samples, keyword_init: true) do
|
|
19
14
|
# Reports whether the mechanical layers found nothing to refuse.
|
|
@@ -38,14 +33,12 @@ module Hecks
|
|
|
38
33
|
# @param aggregate [Bluebook::Aggregate] the current era's IR for the aggregate
|
|
39
34
|
# @param declared [Bluebook::TranslationAggregate, nil] this edge's rules for the
|
|
40
35
|
# aggregate; nil when the edge declares none
|
|
41
|
-
# @param before [Hash{String => Hash}]
|
|
42
|
-
#
|
|
43
|
-
# @
|
|
44
|
-
#
|
|
45
|
-
# (declared drop paths as Strings), `unfed` (attribute names nothing feeds) and
|
|
46
|
-
# `samples` (the Layer 3 before/after pairs)
|
|
36
|
+
# @param before [Hash{String => Hash}] source state per record id, as parsed JSON
|
|
37
|
+
# @param after [Hash{String => Hash}] translated state per record id, as parsed JSON
|
|
38
|
+
# @return [Translation::Audit::Verdict] Layer 1 and 2 `violations`, `dropped` paths,
|
|
39
|
+
# `unfed` attribute names and Layer 3 `samples`
|
|
47
40
|
# @raise [Runtime::WiringError] if Layer 2's reference transform cannot translate a
|
|
48
|
-
# `before` state
|
|
41
|
+
# `before` state
|
|
49
42
|
def check(aggregate:, declared:, before:, after:)
|
|
50
43
|
violations = []
|
|
51
44
|
|
|
@@ -74,19 +67,9 @@ module Hecks
|
|
|
74
67
|
before.keys.sort.first(SAMPLE_SIZE).map { |id| { id: id, before: before[id], after: after[id] } }
|
|
75
68
|
end
|
|
76
69
|
|
|
77
|
-
# Samples both sides of a rekeying edge separately
|
|
78
|
-
#
|
|
79
|
-
# A rekey changes the id itself, so `before`'s and `after`'s
|
|
80
|
-
# keyspaces share nothing — pairing by matching id (the ordinary
|
|
81
|
-
# path above) would show every `after` as nil, telling a human
|
|
82
|
-
# nothing. Nothing in-process can compute the old→new
|
|
83
|
-
# correspondence either (the rekey's SQL is its only
|
|
84
|
-
# implementation, same as compute's own). Shown side by side
|
|
85
|
-
# instead, each labelled by its own id: real records going in,
|
|
86
|
-
# real records coming out — not claimed to correspond one-to-one,
|
|
87
|
-
# but enough for the human this rule's only verification depends
|
|
88
|
-
# on to actually see real shapes and values, not a wall of null.
|
|
70
|
+
# Samples both sides of a rekeying edge separately, each labelled by its own id.
|
|
89
71
|
#
|
|
72
|
+
# A rekey changes the id, so pairing by id would show every `after` as nil.
|
|
90
73
|
# @param before [Hash{String => Hash}] source state per old record id
|
|
91
74
|
# @param after [Hash{String => Hash}] translated state per new record id
|
|
92
75
|
# @return [Array<Hash{Symbol => Object}>] up to `SAMPLE_SIZE` Hashes whose `:id` ends in
|