hecks 2.7.0 → 2.9.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 +11 -0
- 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 +18 -99
- 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 +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- 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 +15 -37
- 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/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 +54 -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 +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -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 +38 -26
- 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 +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- 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 +17 -65
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- 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 +12 -87
- 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 +26 -189
- 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 +11 -42
- 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 +19 -106
- 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 +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- 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 +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
- data/lib/hecks/bluebook/model_check.rb +102 -600
- data/lib/hecks/bluebook/pattern_subset.rb +11 -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 +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- 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 +84 -0
- data/lib/hecks/cli/document.rb +86 -0
- data/lib/hecks/cli/ir.rb +45 -0
- data/lib/hecks/cli/mcp.rb +31 -0
- data/lib/hecks/cli/mcp_door.rb +366 -0
- data/lib/hecks/cli/model_check.rb +203 -0
- data/lib/hecks/cli/project_cli.rb +90 -0
- data/lib/hecks/cli/project_diagrams.rb +36 -0
- data/lib/hecks/cli/run.rb +173 -0
- data/lib/hecks/cli/smoke_test.rb +45 -0
- data/lib/hecks/cli/stores.rb +53 -0
- data/lib/hecks/cli.rb +160 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- 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 +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- 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 +30 -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/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- 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 +15 -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 +12 -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 +98 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -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_door_scope.rb +95 -0
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- 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 +62 -65
- 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 +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- 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 +18 -75
- 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 +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- 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 +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
- 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.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 +23 -103
- 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/projections/bootstrap_table.rb +11 -43
- 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 +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +151 -679
- 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/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 +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- 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 +20 -582
- 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 +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +9 -16
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- 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 +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +46 -138
- 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/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 +93 -0
- data/lib/hecks/release/runner/commands.rb +66 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +43 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +75 -0
- data/lib/hecks/release/runner/preflight.rb +104 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +80 -0
- data/lib/hecks/release/runner.rb +215 -0
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- 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 +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +125 -307
- 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 +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +65 -220
- 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 +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +139 -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 +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +103 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- 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 +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +146 -567
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- 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/vocabulary.rb +5 -0
- data/lib/hecks.rb +32 -82
- 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
- metadata +30 -59
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
|
@@ -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
|
|
@@ -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 `bin/translation_audit --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
|
|
@@ -5,17 +5,8 @@ require_relative "../storage_shape"
|
|
|
5
5
|
|
|
6
6
|
module Hecks
|
|
7
7
|
module Translation
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# (comments, whitespace, behavior) re-freeze safely; a shape change
|
|
11
|
-
# would retroactively redefine what era N *meant* for data already
|
|
12
|
-
# written under it, and refuses hard — there is no --accept past
|
|
13
|
-
# this guard.
|
|
14
|
-
#
|
|
15
|
-
# This does not violate minted-once. That prohibition exists so
|
|
16
|
-
# boot-time recognition never depends on canonicalization stability;
|
|
17
|
-
# this is operator-initiated repair, where a false negative is a
|
|
18
|
-
# loud refusal, never a silent misread.
|
|
8
|
+
# Decides whether an edited era text changed the era's shape or only its text.
|
|
9
|
+
# A shape change refuses hard; no --accept flag gets past it.
|
|
19
10
|
module Reattest
|
|
20
11
|
module_function
|
|
21
12
|
|
|
@@ -25,14 +16,12 @@ module Hecks
|
|
|
25
16
|
# @param domain [String] the domain's name, used in refusal messages
|
|
26
17
|
# @param ordinal [Integer] the era's ordinal, used in refusal messages
|
|
27
18
|
# @param text [String] the held era's bluebook source as it now stands
|
|
28
|
-
# @param stored_hash [String, nil] the era's minted shape hash (SHA-256 hex); nil
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# `Runtime::StorageShape.project` result as parsed JSON; nil for a store without one
|
|
19
|
+
# @param stored_hash [String, nil] the era's minted shape hash (SHA-256 hex); nil if unnamed
|
|
20
|
+
# @param stored_projection [Hash{String => Object}, nil] the stored
|
|
21
|
+
# `Runtime::StorageShape.project` result as parsed JSON; nil when absent
|
|
32
22
|
# @return [Symbol] `:cosmetic` when the shape is unchanged, `:unnamed` when neither a
|
|
33
|
-
# projection nor a hash is stored
|
|
34
|
-
# @raise [Runtime::WiringError] if `text` does not load
|
|
35
|
-
# a shape other than the stored one
|
|
23
|
+
# projection nor a hash is stored
|
|
24
|
+
# @raise [Runtime::WiringError] if `text` does not load, or projects to another shape
|
|
36
25
|
def shape_guard!(domain:, ordinal:, text:, stored_hash:, stored_projection: nil)
|
|
37
26
|
bluebook = shadow(text)
|
|
38
27
|
unless bluebook
|
|
@@ -41,13 +30,8 @@ module Hecks
|
|
|
41
30
|
"bluebook — a held era text is bootable source; restore a loadable text"
|
|
42
31
|
end
|
|
43
32
|
|
|
44
|
-
# The stored projection is
|
|
45
|
-
#
|
|
46
|
-
# this guard never depends on canonicalization stability, and a
|
|
47
|
-
# future canonical-form version cannot make cosmetic edits to
|
|
48
|
-
# old-form eras false-refuse as shape changes. The hash path
|
|
49
|
-
# survives only as a fallback for stores that predate stored
|
|
50
|
-
# projections.
|
|
33
|
+
# The stored projection is compared first: it is version-free, so a new canonical form
|
|
34
|
+
# cannot make a cosmetic edit look like a shape change. The hash is the fallback.
|
|
51
35
|
if stored_projection
|
|
52
36
|
edited = JSON.parse(JSON.generate(Runtime::StorageShape.project(bluebook)))
|
|
53
37
|
return :cosmetic if edited == stored_projection
|