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
|
@@ -1,85 +1,20 @@
|
|
|
1
1
|
require "digest"
|
|
2
2
|
require "fileutils"
|
|
3
|
+
require_relative "../../cache_dir"
|
|
3
4
|
|
|
4
5
|
module Hecks
|
|
5
6
|
module Bluebook
|
|
6
7
|
module MetaValidator
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# lifecycle — checked at real dispatch time (the same admission/
|
|
10
|
-
# coercion/lifecycle-guard door every other command goes through),
|
|
11
|
-
# not merely declared and never exercised.
|
|
8
|
+
# Dispatches the language's own grammar table through a real runtime so
|
|
9
|
+
# `Keyword`/`Argument` status is a lifecycle, not just declared (ADR 0026).
|
|
12
10
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# Aggregate-local `KeywordSeed`/`ArgumentSeed` value objects (still
|
|
16
|
-
# hand-written `member` rows — now beside the concepts they spell)
|
|
17
|
-
# are what gets written ; this is what turns them into what gets
|
|
18
|
-
# read. `Judge`/`Reconstruction` already draw exactly this line
|
|
19
|
-
# everywhere else in the meta-domain (a chapter's own declarations
|
|
20
|
-
# versus what gets dispatched from them) — this runs the same
|
|
21
|
-
# distinction one level further out, for the language's own grammar
|
|
22
|
-
# table.
|
|
23
|
-
#
|
|
24
|
-
# ## A dedicated runtime
|
|
25
|
-
#
|
|
26
|
-
# Not `MetaValidator.fresh_runtime`. That one is reserved for
|
|
27
|
-
# `Judge`'s own bootstrap (dispatching a chapter's declarations into
|
|
28
|
-
# the meta-domain's grammar) — a different act from this one
|
|
29
|
-
# (dispatching the meta-domain's own grammar table data into a live
|
|
30
|
-
# "Bluebook" domain instance). Sharing the runtime would let one
|
|
31
|
-
# boot's own repository state leak into the other's.
|
|
32
|
-
#
|
|
33
|
-
# ## Usage
|
|
34
|
-
#
|
|
35
|
-
# MetaValidator.syntax_table # => { keywords: [...], arguments: [...] }
|
|
36
|
-
#
|
|
37
|
-
# each row a plain Hash, string values, `status` included — the
|
|
38
|
-
# exact shape `ParserTable`/`syntax_conformance_spec` already read
|
|
39
|
-
# off the old closed-set members, so neither consumer had to change
|
|
40
|
-
# what it does with a row, only where the row comes from.
|
|
11
|
+
# SyntaxBoot.call # => { keywords: [...], arguments: [...] }
|
|
41
12
|
module SyntaxBoot
|
|
42
13
|
module_function
|
|
43
14
|
|
|
44
|
-
# Memoized
|
|
45
|
-
#
|
|
46
|
-
# something three separate callers (ParserTable, syntax_
|
|
47
|
-
# conformance_spec, bin/reference) should each pay for on every
|
|
48
|
-
# call.
|
|
49
|
-
#
|
|
50
|
-
# Keyed by the grammar registry's own chapter set, not by a
|
|
51
|
-
# "ready" flag. `boot` reads exactly two things: the registry's
|
|
52
|
-
# "Bluebook" chapter (the core seed rows) and every chapter in the
|
|
53
|
-
# registry that `attaches_to` a core context (Paging's rows). So
|
|
54
|
-
# the table is a pure function of which chapter objects the
|
|
55
|
-
# registry holds — and that is the cache key: the same chapters,
|
|
56
|
-
# by identity, mean the same table; a chapter replaced (the
|
|
57
|
-
# fixpoint judge swapping a raw chapter for its assembled self)
|
|
58
|
-
# or added (`load_attached_grammar_into`) means a fresh boot.
|
|
59
|
-
#
|
|
60
|
-
# Why not the earlier `grammar_registry_ready?` guard. That guard
|
|
61
|
-
# was right about the hazard — a snapshot taken mid-build, before
|
|
62
|
-
# Paging attached, would be missing limit/offset/cursor/nulls
|
|
63
|
-
# forever — and wrong about the cost of its cure. It refused to
|
|
64
|
-
# cache anything until the whole grammar registry had finished
|
|
65
|
-
# building, calling that window "narrow" and recomputing in it
|
|
66
|
-
# "cheap". Measured (hecks_ai_training, a six-entity chess domain,
|
|
67
|
-
# 2026-08-22): every `word_gate_dispatch` landing in that window
|
|
68
|
-
# re-ran the full ~284-dispatch boot at ~0.76s each — 42 times per
|
|
69
|
-
# process, 32 of a 35-second `Hecks.boot`, 95% of which had
|
|
70
|
-
# nothing to do with the domain being booted. Keying on the
|
|
71
|
-
# chapter set closes the same hazard by construction (a snapshot
|
|
72
|
-
# can only be served while the chapters it was read from are
|
|
73
|
-
# still the chapters the registry holds) and lets the window's
|
|
74
|
-
# own repeated, identical calls share one boot. A registry reset
|
|
75
|
-
# (fixpoint_spec's own `@grammar_registry = nil`) yields new
|
|
76
|
-
# chapter objects, so it invalidates this the same way it always
|
|
77
|
-
# invalidated `grammar_registry_ready?`.
|
|
15
|
+
# Memoized per grammar-registry chapter set (identity, not a "ready"
|
|
16
|
+
# flag), and cross-process on disk, since a full boot is real work.
|
|
78
17
|
#
|
|
79
|
-
# `equal?`, not `==`, on the chapters — identity is the fact being
|
|
80
|
-
# tracked. Holding the chapter objects themselves (not their ids)
|
|
81
|
-
# in the key also means a collected chapter can never hand its id
|
|
82
|
-
# to a newcomer behind this cache's back.
|
|
83
18
|
# @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
|
|
84
19
|
# and `:arguments`, each an array of plain, string-valued row
|
|
85
20
|
# hashes (`status` included)
|
|
@@ -98,15 +33,8 @@ module Hecks
|
|
|
98
33
|
result
|
|
99
34
|
end
|
|
100
35
|
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
# @param cached [Array<Array(String, Object)>] the `[name, chapter]`
|
|
105
|
-
# pairs `call` last cached against
|
|
106
|
-
# @param current [Array<Array(String, Object)>] the registry's
|
|
107
|
-
# current `[name, chapter]` pairs
|
|
108
|
-
# @return [Boolean] whether `cached` and `current` name the same
|
|
109
|
-
# chapters, by identity, in the same order
|
|
36
|
+
# `equal?`, not `==` — chapter identity, not value equality, is the
|
|
37
|
+
# fact this cache key tracks.
|
|
110
38
|
def same_chapters?(cached, current)
|
|
111
39
|
cached.size == current.size &&
|
|
112
40
|
cached.zip(current).all? do |(cached_name, cached_chapter), (name, chapter)|
|
|
@@ -114,73 +42,17 @@ module Hecks
|
|
|
114
42
|
end
|
|
115
43
|
end
|
|
116
44
|
|
|
117
|
-
# Cross-process persistence for the same
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
# scratch even when the grammar source hasn't changed at all since
|
|
124
|
-
# the last process that built it.
|
|
125
|
-
#
|
|
126
|
-
# Not a fix for the two-builds-per-process shape — investigated and
|
|
127
|
-
# confirmed genuine, not waste (see this module's own header
|
|
128
|
-
# history: the previous "wait for the whole registry" design cost
|
|
129
|
-
# 42 rebuilds/32s per process precisely because real callers need a
|
|
130
|
-
# correct table mid-bootstrap, before Paging attaches). Both builds
|
|
131
|
-
# still happen once each per process; this only makes each of them
|
|
132
|
-
# a cheap disk read instead of a real ~1s dispatch, once some
|
|
133
|
-
# earlier process has already paid for that exact chapter-set +
|
|
134
|
-
# grammar-content combination.
|
|
135
|
-
#
|
|
136
|
-
# Keyed the same way `same_chapters?` is, translated across process
|
|
137
|
-
# boundaries — chapter *object identity* (what the in-memory cache
|
|
138
|
-
# keys on) means nothing to a different process; chapter *names*,
|
|
139
|
-
# in the same order, do. Combined with a content hash of every
|
|
140
|
-
# grammar file `boot` can read from (`seed_chapters` walks every
|
|
141
|
-
# bluebook the registry holds, so this must cover the core chapters
|
|
142
|
-
# and every attached one, not just "Bluebook" + "Paging") — a
|
|
143
|
-
# source edit anywhere in that set correctly misses the old cache
|
|
144
|
-
# entry rather than silently serving a stale table.
|
|
145
|
-
#
|
|
146
|
-
# Fails toward a real boot, never toward a wrong table — same
|
|
147
|
-
# loud-not-silent discipline this codebase already holds CI to
|
|
148
|
-
# (`postgres_io_relevant_changed`'s own header). A missing file, a
|
|
149
|
-
# corrupt Marshal blob, a permission error, an unwritable `tmp/` —
|
|
150
|
-
# every one of these degrades to "no disk cache today", never to a
|
|
151
|
-
# crash or a served-but-wrong table. `tmp/` is already gitignored
|
|
152
|
-
# for exactly this kind of local, disposable-but-useful-while-it-
|
|
153
|
-
# lasts artifact (`Storehouse::LOG_ROOT`'s own header names the
|
|
154
|
-
# same convention).
|
|
155
|
-
#
|
|
156
|
-
# **Atomic write, not a lock** — `qa_sweep --all` spawns up to 4
|
|
157
|
-
# children at once, any of which could reach a cold cache
|
|
158
|
-
# simultaneously and each compute the identical real boot result
|
|
159
|
-
# for the identical key. Writing to a PID-suffixed temp file and
|
|
160
|
-
# `File.rename`ing it into place (a single atomic syscall on the
|
|
161
|
-
# same filesystem) means a concurrent second writer's rename just
|
|
162
|
-
# overwrites the first with byte-identical content — never a torn
|
|
163
|
-
# or partially-written file a concurrent reader could observe.
|
|
164
|
-
#
|
|
165
|
-
# `HECKS_SYNTAX_BOOT_CACHE=off` — an escape hatch needing no code
|
|
166
|
-
# change, the same shape `Storehouse::BOOT_ROOT`'s own
|
|
167
|
-
# `HECKS_STOREHOUSE_ROOT` override uses, for the day this needs to
|
|
168
|
-
# be ruled out while debugging something else entirely.
|
|
169
|
-
CACHE_DIR = File.expand_path("../../../../tmp/hecks_syntax_boot_cache", __dir__).freeze
|
|
45
|
+
# Cross-process persistence for the same build `call` already memoizes
|
|
46
|
+
# in-process, keyed by chapter name (not identity, which means nothing
|
|
47
|
+
# across processes) plus a content hash of every grammar file `boot`
|
|
48
|
+
# can read from — so a source edit anywhere in that set misses the
|
|
49
|
+
# cache rather than silently serving a stale table.
|
|
50
|
+
def cache_dir = Hecks::CacheDir.path("hecks_syntax_boot_cache")
|
|
170
51
|
|
|
171
|
-
# Reports whether the cross-process disk cache is turned on.
|
|
172
|
-
#
|
|
173
|
-
# @return [Boolean] whether the cross-process disk cache is turned
|
|
174
|
-
# on (`HECKS_SYNTAX_BOOT_CACHE=off` turns it off)
|
|
175
52
|
def disk_cache_enabled? = ENV["HECKS_SYNTAX_BOOT_CACHE"] != "off"
|
|
176
53
|
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
# @param chapters [Array<Array(String, Object)>] the `[name,
|
|
180
|
-
# chapter]` pairs to key the cache entry on
|
|
181
|
-
# @return [Hash{Symbol => Array<Hash{Symbol => String}>}, nil] the
|
|
182
|
-
# cached syntax table, or `nil` if the cache is disabled, no entry
|
|
183
|
-
# exists yet, or the entry could not be read
|
|
54
|
+
# Fails toward a real boot, never toward a wrong table: a missing
|
|
55
|
+
# file, a corrupt blob, or a permission error just misses the cache.
|
|
184
56
|
def read_disk_cache(chapters)
|
|
185
57
|
return nil unless disk_cache_enabled?
|
|
186
58
|
|
|
@@ -192,18 +64,14 @@ module Hecks
|
|
|
192
64
|
nil
|
|
193
65
|
end
|
|
194
66
|
|
|
195
|
-
# Writes
|
|
196
|
-
#
|
|
197
|
-
#
|
|
198
|
-
# chapter]` pairs to key the cache entry on
|
|
199
|
-
# @param result [Hash{Symbol => Array<Hash{Symbol => String}>}] the
|
|
200
|
-
# syntax table to persist
|
|
201
|
-
# @return [void]
|
|
67
|
+
# Writes to a PID-suffixed temp file and renames it into place, so a
|
|
68
|
+
# concurrent writer's rename can only overwrite with identical
|
|
69
|
+
# content, never leave a torn file for a concurrent reader.
|
|
202
70
|
def write_disk_cache(chapters, result)
|
|
203
71
|
return unless disk_cache_enabled?
|
|
204
72
|
|
|
205
73
|
path = disk_cache_path(chapters)
|
|
206
|
-
FileUtils.mkdir_p(
|
|
74
|
+
FileUtils.mkdir_p(cache_dir)
|
|
207
75
|
tmp_path = "#{path}.#{Process.pid}.tmp"
|
|
208
76
|
File.binwrite(tmp_path, Marshal.dump(result))
|
|
209
77
|
File.rename(tmp_path, path)
|
|
@@ -211,38 +79,18 @@ module Hecks
|
|
|
211
79
|
nil
|
|
212
80
|
end
|
|
213
81
|
|
|
214
|
-
# Builds the disk cache file path for `chapters`.
|
|
215
|
-
#
|
|
216
|
-
# @param chapters [Array<Array(String, Object)>] the `[name,
|
|
217
|
-
# chapter]` pairs to key the cache entry on
|
|
218
|
-
# @return [String] the disk cache file path for `chapters`
|
|
219
82
|
def disk_cache_path(chapters)
|
|
220
|
-
File.join(
|
|
83
|
+
File.join(cache_dir, "#{disk_cache_key(chapters)}.marshal")
|
|
221
84
|
end
|
|
222
85
|
|
|
223
|
-
# Builds the cache key for `chapters`.
|
|
224
|
-
#
|
|
225
|
-
# @param chapters [Array<Array(String, Object)>] the `[name,
|
|
226
|
-
# chapter]` pairs to key the cache entry on
|
|
227
|
-
# @return [String] a SHA-256 digest of the chapter names and the
|
|
228
|
-
# current grammar source
|
|
229
86
|
def disk_cache_key(chapters)
|
|
230
87
|
names = chapters.map { |name, _chapter| name }
|
|
231
88
|
Digest::SHA256.hexdigest("#{names.join(',')}:#{grammar_content_digest}")
|
|
232
89
|
end
|
|
233
90
|
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
# most often), because World/Hecksagon/any future attached chapter
|
|
238
|
-
# are equally eligible to carry their own `KeywordSeed`/
|
|
239
|
-
# `ArgumentSeed` value object. Coarser than strictly necessary (any
|
|
240
|
-
# one file changing invalidates every cached key, not just the
|
|
241
|
-
# chapter it belongs to) — deliberately, since under-covering this
|
|
242
|
-
# set is a correctness bug (a stale table survives a real grammar
|
|
243
|
-
# edit) and over-covering it is only ever a wasted cache miss.
|
|
244
|
-
# @return [String] a SHA-256 digest of every grammar file's own
|
|
245
|
-
# current content, sorted for a stable digest
|
|
91
|
+
# Covers every chapter's grammar files, not just the core ones —
|
|
92
|
+
# coarser than strictly necessary, but under-covering this set would
|
|
93
|
+
# let a stale table survive a real grammar edit.
|
|
246
94
|
def grammar_content_digest
|
|
247
95
|
files = (MetaValidator::GRAMMAR_FILES + MetaValidator::WORLD_GRAMMAR + MetaValidator::HECKSAGON_GRAMMAR +
|
|
248
96
|
Dir.glob(File.join(MetaValidator::ATTACHED_GRAMMAR_DIR, "*.bluebook"))).sort
|
|
@@ -251,21 +99,11 @@ module Hecks
|
|
|
251
99
|
|
|
252
100
|
# Dispatches every seed row into a fresh "Bluebook" instance and
|
|
253
101
|
# reads the result back.
|
|
254
|
-
#
|
|
255
|
-
# @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
|
|
256
|
-
# and `:arguments`, each an array of plain, string-valued row
|
|
257
|
-
# hashes (`status` included)
|
|
258
102
|
def boot
|
|
259
103
|
bluebook = MetaValidator.grammar_registry.bluebook("Bluebook")
|
|
260
|
-
# `
|
|
261
|
-
#
|
|
262
|
-
#
|
|
263
|
-
# ran `registry.add_bluebook`) and its adapter ports already
|
|
264
|
-
# loaded ; a standalone registry would need both wired by hand.
|
|
265
|
-
# `fresh_runtime` resets `@repositories` on the same registry —
|
|
266
|
-
# the identical isolation `Judge.new` already relies on for
|
|
267
|
-
# every real domain it judges, proven safe by every dispatch
|
|
268
|
-
# this session has ever made.
|
|
104
|
+
# `fresh_runtime`, not a new `Runtime::Registry` — the grammar
|
|
105
|
+
# registry already has "Bluebook" registered and its adapter
|
|
106
|
+
# ports already loaded.
|
|
269
107
|
runtime = MetaValidator.fresh_runtime
|
|
270
108
|
|
|
271
109
|
declare_syntax(runtime, bluebook)
|
|
@@ -275,56 +113,26 @@ module Hecks
|
|
|
275
113
|
read_back(runtime, bluebook)
|
|
276
114
|
end
|
|
277
115
|
|
|
278
|
-
#
|
|
279
|
-
#
|
|
280
|
-
#
|
|
281
|
-
# An Integer stays an Integer — `position` is `Position`-typed
|
|
282
|
-
# (`attribute :value, Integer`), so stringifying it fails the type
|
|
283
|
-
# gate rather than feeding it, the same reading `Judge#v` gives.
|
|
284
|
-
#
|
|
285
|
-
# @param text [String, Integer] the scalar to wrap
|
|
286
|
-
# @return [Hash{Symbol => String, Integer}] `{value: text}`,
|
|
287
|
-
# stringified unless `text` is already an Integer
|
|
116
|
+
# An Integer stays an Integer — `position` is `Position`-typed, so
|
|
117
|
+
# stringifying it would fail the type gate rather than feed it.
|
|
288
118
|
def v(text)
|
|
289
119
|
return { value: text } if text.is_a?(Integer)
|
|
290
120
|
|
|
291
121
|
{ value: text.to_s }
|
|
292
122
|
end
|
|
293
123
|
|
|
294
|
-
#
|
|
295
|
-
#
|
|
296
|
-
#
|
|
297
|
-
# Absent stays absent. A seed row's own optional columns ("was",
|
|
298
|
-
# "at", "named", ...) are empty strings, not nil — `Literal`/CSV-
|
|
299
|
-
# shaped grammar data has no `nil` to write — so this is the one
|
|
300
|
-
# place that decides "" means "not given" for the purpose of an
|
|
301
|
-
# `optional: true` command argument, the same reading `Judge#v`
|
|
302
|
-
# makes for the meta-domain's own dispatches.
|
|
303
|
-
#
|
|
304
|
-
# @param text [String, nil] the seed row's own column value
|
|
305
|
-
# @return [Hash{Symbol => String}, nil] `v(text)`, or `nil` when
|
|
306
|
-
# `text` is `nil` or empty
|
|
124
|
+
# A seed row's own optional columns are "", not nil (CSV-shaped
|
|
125
|
+
# grammar data has no nil to write) — this is where "" is read as
|
|
126
|
+
# "not given".
|
|
307
127
|
def optional(text)
|
|
308
128
|
return nil if text.nil? || text.to_s.empty?
|
|
309
129
|
|
|
310
130
|
v(text)
|
|
311
131
|
end
|
|
312
132
|
|
|
313
|
-
#
|
|
314
|
-
#
|
|
315
|
-
#
|
|
316
|
-
# `Policy.Declare`, ...). This fresh runtime holds no chapter
|
|
317
|
-
# record of its own yet (nothing else here needs one), so one is
|
|
318
|
-
# declared first, named after the real chapter, purely to satisfy
|
|
319
|
-
# the reference — its own vision/classification are never read
|
|
320
|
-
# by anything this boot does.
|
|
321
|
-
#
|
|
322
|
-
# @param runtime [Runtime::Dispatcher] the fresh runtime to
|
|
323
|
-
# dispatch into
|
|
324
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
325
|
-
# "Bluebook" chapter, read for its `hecks_name` and `"Syntax"`
|
|
326
|
-
# aggregate
|
|
327
|
-
# @return [void]
|
|
133
|
+
# This fresh runtime holds no chapter record of its own, so one is
|
|
134
|
+
# declared first, purely to satisfy `Syntax.Declare`'s `reference_to
|
|
135
|
+
# Bluebook` — its vision/classification are never read afterward.
|
|
328
136
|
def declare_syntax(runtime, bluebook)
|
|
329
137
|
syntax = bluebook.aggregate("Syntax")
|
|
330
138
|
runtime.dispatch("Bluebook::Bluebook.Declare",
|
|
@@ -336,21 +144,10 @@ module Hecks
|
|
|
336
144
|
with: { bluebook: bluebook.hecks_name, name: v(syntax.hecks_name) })
|
|
337
145
|
end
|
|
338
146
|
|
|
339
|
-
# `to: "Syntax"`
|
|
340
|
-
#
|
|
341
|
-
#
|
|
342
|
-
#
|
|
343
|
-
# `ValueObject.Member`/`ProcessManager.Handler`) already left behind
|
|
344
|
-
# for `to:`/`with:` — would carry the receiver in the payload,
|
|
345
|
-
# making `Syntax.Keyword`'s own `command.creates?` (true: it
|
|
346
|
-
# declares no `reference_to`) look like a fresh identity to mint,
|
|
347
|
-
# colliding with the very "Syntax" row `declare_syntax` just opened.
|
|
348
|
-
#
|
|
349
|
-
# @param runtime [Runtime::Dispatcher] the fresh runtime to
|
|
350
|
-
# dispatch into
|
|
351
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
352
|
-
# "Bluebook" chapter, read for its `KeywordSeed` rows
|
|
353
|
-
# @return [void]
|
|
147
|
+
# `to: "Syntax"` appends onto the record `declare_syntax` already
|
|
148
|
+
# opened; putting the receiver in the payload instead would make
|
|
149
|
+
# `Syntax.Keyword` look like a fresh identity to mint, colliding
|
|
150
|
+
# with that row.
|
|
354
151
|
def admit_keywords(runtime, bluebook)
|
|
355
152
|
all_rows(bluebook, "KeywordSeed").each_with_index do |row, index|
|
|
356
153
|
runtime.dispatch("Bluebook::Syntax.Keyword", to: "Syntax",
|
|
@@ -368,14 +165,7 @@ module Hecks
|
|
|
368
165
|
end
|
|
369
166
|
end
|
|
370
167
|
|
|
371
|
-
#
|
|
372
|
-
# `to: "Syntax"` append shape `admit_keywords` uses one type over.
|
|
373
|
-
#
|
|
374
|
-
# @param runtime [Runtime::Dispatcher] the fresh runtime to
|
|
375
|
-
# dispatch into
|
|
376
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
377
|
-
# "Bluebook" chapter, read for its `ArgumentSeed` rows
|
|
378
|
-
# @return [void]
|
|
168
|
+
# Same `to: "Syntax"` append shape `admit_keywords` uses, one type over.
|
|
379
169
|
def admit_arguments(runtime, bluebook)
|
|
380
170
|
all_rows(bluebook, "ArgumentSeed").each_with_index do |row, index|
|
|
381
171
|
runtime.dispatch("Bluebook::Syntax.Argument", to: "Syntax",
|
|
@@ -395,49 +185,18 @@ module Hecks
|
|
|
395
185
|
end
|
|
396
186
|
end
|
|
397
187
|
|
|
398
|
-
#
|
|
399
|
-
#
|
|
400
|
-
# filename, or context catalog is maintained here. This finds the core
|
|
401
|
-
# Bluebook concepts, the sibling artifact languages (World, Hecksagon,
|
|
402
|
-
# Port, Adapter, Translation), and attached sub-languages alike.
|
|
403
|
-
# Concatenated into one sequence because `position` is minted from the
|
|
404
|
-
# walk index and must not collide across concepts.
|
|
405
|
-
#
|
|
406
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
407
|
-
# "Bluebook" chapter, read first, before every other loaded
|
|
408
|
-
# chapter
|
|
409
|
-
# @param name [String] the local value-object name to collect rows
|
|
410
|
-
# of, such as `"KeywordSeed"`
|
|
411
|
-
# @return [Array<Hash{Symbol => String}>] every matching row, across
|
|
412
|
-
# every loaded chapter, in chapter order
|
|
188
|
+
# Concatenated into one sequence because `position` is minted from
|
|
189
|
+
# the walk index and must not collide across concepts.
|
|
413
190
|
def all_rows(bluebook, name)
|
|
414
191
|
seed_chapters(bluebook).flat_map { |chapter| rows(chapter, name) }
|
|
415
192
|
end
|
|
416
193
|
|
|
417
|
-
#
|
|
418
|
-
#
|
|
419
|
-
# object twice without relying on object identity across fixpoint
|
|
420
|
-
# assembly.
|
|
421
|
-
#
|
|
422
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
423
|
-
# "Bluebook" chapter
|
|
424
|
-
# @return [Array<Bluebook::Chapter>] `bluebook` first, then every
|
|
425
|
-
# other chapter the grammar registry holds
|
|
194
|
+
# `bluebook` first, then registry insertion order, so the core
|
|
195
|
+
# chapter is never read twice.
|
|
426
196
|
def seed_chapters(bluebook)
|
|
427
197
|
[bluebook] + MetaValidator.grammar_registry.bluebooks.values.reject { |chapter| chapter.name == bluebook.name }
|
|
428
198
|
end
|
|
429
199
|
|
|
430
|
-
# The seed rows themselves — plain hashes, string values, read from
|
|
431
|
-
# every aggregate that owns a same-named local value object. Repeating
|
|
432
|
-
# the value-object shape is deliberate: each concept remains readable
|
|
433
|
-
# by itself, while this discovery is the only grouping mechanism.
|
|
434
|
-
#
|
|
435
|
-
# @param bluebook [Bluebook::Chapter] the chapter to search
|
|
436
|
-
# @param name [String] the local value-object name to collect rows
|
|
437
|
-
# of, such as `"KeywordSeed"`
|
|
438
|
-
# @return [Array<Hash{Symbol => String}>] one hash per member row,
|
|
439
|
-
# `[]` if no aggregate in `bluebook` owns a value object named
|
|
440
|
-
# `name`
|
|
441
200
|
def rows(bluebook, name)
|
|
442
201
|
bluebook.aggregates.flat_map do |aggregate|
|
|
443
202
|
value_object = aggregate.value_objects.find { |vo| vo.hecks_name == name }
|
|
@@ -447,18 +206,8 @@ module Hecks
|
|
|
447
206
|
end
|
|
448
207
|
end
|
|
449
208
|
|
|
450
|
-
# Reads the dispatched result back into the same shape
|
|
451
|
-
#
|
|
452
|
-
# `status` included — so `ParserTable`/`syntax_conformance_spec`
|
|
453
|
-
# need not know or care that a real dispatch happened in between.
|
|
454
|
-
#
|
|
455
|
-
# @param runtime [Runtime::Dispatcher] the runtime `boot` dispatched
|
|
456
|
-
# every seed row into
|
|
457
|
-
# @param bluebook [Bluebook::Chapter] the language's own assembled
|
|
458
|
-
# "Bluebook" chapter, read for its `"Syntax"` aggregate
|
|
459
|
-
# @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
|
|
460
|
-
# and `:arguments`, each an array of plain, string-valued row
|
|
461
|
-
# hashes (`status` included)
|
|
209
|
+
# Reads the dispatched result back into the same plain-hash shape
|
|
210
|
+
# `rows` hands the seed data in as.
|
|
462
211
|
def read_back(runtime, bluebook)
|
|
463
212
|
syntax = bluebook.aggregate("Syntax")
|
|
464
213
|
repository = runtime.registry.repository("Bluebook", syntax)
|
|
@@ -470,23 +219,13 @@ module Hecks
|
|
|
470
219
|
}
|
|
471
220
|
end
|
|
472
221
|
|
|
473
|
-
# Flattens one dispatched record into a plain, string-valued row.
|
|
474
|
-
#
|
|
475
|
-
# @param row [Object] one dispatched keyword or argument record,
|
|
476
|
-
# answering `to_h`
|
|
477
|
-
# @return [Hash{Symbol => String}] `row`'s own fields, each value
|
|
478
|
-
# unwrapped and stringified
|
|
479
222
|
def stringify(row)
|
|
480
223
|
row.to_h.transform_values do |cell|
|
|
481
224
|
scalar(cell).to_s
|
|
482
225
|
end
|
|
483
226
|
end
|
|
484
227
|
|
|
485
|
-
# Unwraps
|
|
486
|
-
#
|
|
487
|
-
# @param cell [Object] one field's stored value
|
|
488
|
-
# @return [Object] `cell`'s sole wrapped value, if `cell` is a
|
|
489
|
-
# to_h-able non-String; `cell` unchanged otherwise
|
|
228
|
+
# Unwraps a value-object-wrapped field back to its bare scalar.
|
|
490
229
|
def scalar(cell)
|
|
491
230
|
return cell.to_h.values.first if cell.respond_to?(:to_h) && !cell.is_a?(String)
|
|
492
231
|
|
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
module MetaValidator
|
|
4
|
-
# Offers a built translation (a `translations/*.bluebook` edge
|
|
5
|
-
#
|
|
6
|
-
# there is no separate `.translation` extension) to the language
|
|
7
|
-
# that describes translations.
|
|
8
|
-
#
|
|
9
|
-
# A sibling of a bluebook again, the same shape PortJudge/
|
|
10
|
-
# AdapterJudge already are — its own file, its own door, judged
|
|
11
|
-
# through its own self-hosted language (translation.bluebook)
|
|
12
|
-
# rather than left as plain Ruby structs nothing checks. Walks the
|
|
13
|
-
# whole built translation in one pass — the top-level Declare/
|
|
14
|
-
# Retire commands, then every nested aggregate's own Declare plus
|
|
15
|
-
# one Add* command per rule it carries — the same "one judge, every
|
|
16
|
-
# nested record" shape WorldJudge already gives Wiring. Field names
|
|
17
|
-
# throughout read lib/hecks/bluebook/translation.rb's own real
|
|
18
|
-
# struct/class definitions directly, not the DSL builder's own
|
|
19
|
-
# local parameter names (`move(old_path, to:)`'s `old_path` reads
|
|
20
|
-
# back as the struct's own `from`). Whole-project table-
|
|
21
|
-
# unification survey, item #13's remaining builders.
|
|
4
|
+
# Offers a built translation (a `translations/*.bluebook` edge) to the language that
|
|
5
|
+
# describes translations. Field names follow the `Translation` structs, not the DSL builder.
|
|
22
6
|
class TranslationJudge
|
|
23
7
|
attr_reader :refusals
|
|
24
8
|
|
|
@@ -36,18 +20,8 @@ module Hecks
|
|
|
36
20
|
|
|
37
21
|
def args(pairs) = pairs.compact
|
|
38
22
|
|
|
39
|
-
# `
|
|
40
|
-
#
|
|
41
|
-
# Those three each judge a single aggregate per build (Port/Adapter)
|
|
42
|
-
# or a Hash keyed by verb (World's own settings, deduped by
|
|
43
|
-
# construction), so a duplicate-identity Declare can never reach
|
|
44
|
-
# their own runtime. `TranslationBuilder#aggregate` appends every
|
|
45
|
-
# block to a plain Array (`@aggregates << builder.build`) with no
|
|
46
|
-
# dedup — two `aggregate "Account" do ... end` blocks in the same
|
|
47
|
-
# translation are syntactically legal and reach here for real.
|
|
48
|
-
# Left unrescued, the second Declare's `AlreadyExists` would crash
|
|
49
|
-
# straight through `call_translation` instead of becoming a clean
|
|
50
|
-
# refusal — confirmed via direct dispatch.
|
|
23
|
+
# Rescues `AlreadyExists` too: `TranslationBuilder#aggregate` does not dedup, so two
|
|
24
|
+
# same-named aggregate blocks reach here and must become a refusal, not a crash.
|
|
51
25
|
def offer(label)
|
|
52
26
|
yield
|
|
53
27
|
rescue Runtime::GivenNotMet, Runtime::InvariantViolation, Runtime::TypeMismatch,
|
|
@@ -66,14 +40,7 @@ module Hecks
|
|
|
66
40
|
send_to("Translation::Translation.Declare", t.domain,
|
|
67
41
|
with: { domain: v(t.domain), from: v(t.from), to: v(t.to) })
|
|
68
42
|
|
|
69
|
-
# `id
|
|
70
|
-
# to])` — Translation's own identity is composite
|
|
71
|
-
# (`identified_by :domain, :from, :to`), the same reason
|
|
72
|
-
# `Wiring.Set`'s own self-reference dispatch (world.bluebook,
|
|
73
|
-
# `WorldJudge#judge_wiring`) needs a computed `id:` rather than
|
|
74
|
-
# a bare field value — a single-field identity (TranslationAggregate's
|
|
75
|
-
# own `name`) is the one case where the bare value itself is the
|
|
76
|
-
# id, confirmed live via direct dispatch testing, not assumed.
|
|
43
|
+
# Translation's identity is composite, so `id:` must be computed, not a bare field.
|
|
77
44
|
translation_id = Naming.identity([t.domain, t.from, t.to])
|
|
78
45
|
Array(t.retired).each do |name|
|
|
79
46
|
send_to("Translation::Translation.Retire", t.domain, to: translation_id,
|
|
@@ -83,11 +50,8 @@ module Hecks
|
|
|
83
50
|
Array(t.aggregates).each { |aggregate| judge_aggregate(t, aggregate) }
|
|
84
51
|
end
|
|
85
52
|
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
# different fields), so each is its own private method below; only
|
|
89
|
-
# Declare-before-any-Add is order-sensitive, and that order is
|
|
90
|
-
# preserved here.
|
|
53
|
+
# Declares the aggregate, then adds each rule collection. Only Declare-before-Add is
|
|
54
|
+
# order-sensitive.
|
|
91
55
|
def judge_aggregate(translation, aggregate)
|
|
92
56
|
name = aggregate.name
|
|
93
57
|
declare_aggregate(translation, aggregate, name)
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
module MetaValidator
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# A world is a sibling of a bluebook — the same domain runs in many of
|
|
7
|
-
# them — so it is judged through its own door, against its own language
|
|
8
|
-
# file, and its settings normalise the same way a mutation's fields do:
|
|
9
|
-
# an open map becomes one Wiring per verb and one Setting row per value.
|
|
4
|
+
# Judges a built .world against the language that describes worlds,
|
|
5
|
+
# normalizing its settings into one Wiring per verb, one Setting per value.
|
|
10
6
|
class WorldJudge
|
|
11
7
|
attr_reader :refusals
|
|
12
8
|
|
|
13
|
-
# @param world [Bluebook::World] the built world to judge
|
|
14
9
|
def initialize(world)
|
|
15
10
|
@world = world
|
|
16
11
|
@refusals = []
|
|
@@ -54,18 +49,11 @@ module Hecks
|
|
|
54
49
|
end
|
|
55
50
|
|
|
56
51
|
def judge_wiring(domain, verb, values)
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
# (a creating command) ignores this `id:` entirely and computes its own
|
|
60
|
-
# from `world`/`verb`, so a locally minted "#{domain}.#{verb}" named a
|
|
61
|
-
# record `Wiring.Set` could never find : the id passed here has to be
|
|
62
|
-
# the same derivation, not a second guess at what it must be.
|
|
52
|
+
# Must match Wiring's own `identified_by do world; verb.value end`
|
|
53
|
+
# derivation exactly, or a later `Wiring.Set` could never find it.
|
|
63
54
|
id = Naming.identity([domain, verb])
|
|
64
|
-
# `world_ref` is the
|
|
65
|
-
#
|
|
66
|
-
# beside it is an ordinary text attribute that happens to hold the same
|
|
67
|
-
# string, and stays a value object. The two look alike and are not —
|
|
68
|
-
# which is exactly why the judge asks the type rather than the name.
|
|
55
|
+
# `world_ref` is the type-checked reference; the plain `world`
|
|
56
|
+
# attribute alongside it just happens to hold the same string.
|
|
69
57
|
send_to("World::Wiring.Declare", id, world_ref: v(domain),
|
|
70
58
|
world: v(domain), verb: v(verb), adapter: v(Hash(values)[:adapter]))
|
|
71
59
|
|