hecks 0.2.0 → 0.3.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 +5 -5
- data/lib/hecks/adapters/driven/claude_code.adapter +3 -0
- data/lib/hecks/adapters/driven/claude_code.rb +127 -0
- data/lib/hecks/adapters/driven/d1.adapter +12 -0
- data/lib/hecks/adapters/driven/d1.rb +403 -0
- data/lib/hecks/adapters/driven/folder.adapter +3 -0
- data/lib/hecks/adapters/driven/folder.rb +199 -0
- data/lib/hecks/adapters/driven/google_authentication.adapter +3 -0
- data/lib/hecks/adapters/driven/google_authentication.rb +100 -0
- data/lib/hecks/adapters/driven/governance_authorization.adapter +3 -0
- data/lib/hecks/adapters/driven/governance_authorization.rb +62 -0
- data/lib/hecks/adapters/driven/heki/journal.rb +51 -0
- data/lib/hecks/adapters/driven/heki/saga_store.rb +0 -0
- data/lib/hecks/adapters/driven/heki/snapshot.rb +38 -0
- data/lib/hecks/adapters/driven/heki.adapter +4 -0
- data/lib/hecks/adapters/driven/heki.rb +148 -0
- data/lib/hecks/adapters/driven/identity_registry.adapter +3 -0
- data/lib/hecks/adapters/driven/identity_registry.rb +26 -0
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +51 -0
- data/lib/hecks/adapters/driven/lambda/client.rb +63 -0
- data/lib/hecks/adapters/driven/lambda.adapter +4 -0
- data/lib/hecks/adapters/driven/lambda.rb +131 -0
- data/lib/hecks/adapters/driven/memory.adapter +3 -0
- data/lib/hecks/adapters/driven/memory.rb +103 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +3 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +28 -0
- data/lib/hecks/adapters/driven/postgres/codec.rb +80 -0
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +168 -0
- data/lib/hecks/adapters/driven/postgres.adapter +5 -0
- data/lib/hecks/adapters/driven/postgres.rb +391 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +171 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/field_cache.rb +190 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/head_compiler.rb +429 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +166 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +286 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/resumable_backfill.rb +168 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/tail_merge.rb +163 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/transform_installer.rb +114 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage.rb +137 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +89 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +82 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +132 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +74 -0
- data/lib/hecks/adapters/driven/postgres_era.adapter +6 -0
- data/lib/hecks/adapters/driven/postgres_era.rb +671 -0
- data/lib/hecks/adapters/driven/prism.adapter +3 -0
- data/lib/hecks/adapters/driven/prism.rb +80 -0
- data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
- data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
- data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
- data/lib/hecks/adapters/driven/sqlite/codec.rb +63 -0
- data/lib/hecks/adapters/driven/sqlite/projection.rb +105 -0
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +180 -0
- data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
- data/lib/hecks/adapters/driven/sqlite.rb +285 -0
- data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
- data/lib/hecks/adapters/driven/system_clock.rb +14 -0
- data/lib/hecks/adapters/driven.rb +36 -0
- data/lib/hecks/adapters.rb +6 -0
- data/lib/hecks/behaviors/dsl.rb +96 -0
- data/lib/hecks/behaviors/expectations.rb +280 -0
- data/lib/hecks/behaviors/ir.rb +31 -0
- data/lib/hecks/behaviors/rspec.rb +42 -0
- data/lib/hecks/behaviors/runner.rb +96 -0
- data/lib/hecks/behaviors.rb +25 -0
- data/lib/hecks/bluebook/aggregate.rb +108 -0
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
- data/lib/hecks/bluebook/assembly/build.rb +48 -0
- data/lib/hecks/bluebook/assembly/contract.rb +112 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +409 -0
- data/lib/hecks/bluebook/assembly/marks.rb +227 -0
- data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
- data/lib/hecks/bluebook/assembly.rb +78 -0
- data/lib/hecks/bluebook/attribute.rb +96 -0
- data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
- data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
- data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
- data/lib/hecks/bluebook/behaviour/command.rb +116 -0
- data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
- data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
- data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +51 -0
- data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
- data/lib/hecks/bluebook/behaviour/process_manager.rb +38 -0
- data/lib/hecks/bluebook/behaviour/query.rb +10 -0
- data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
- data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
- data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
- data/lib/hecks/bluebook/chapter.rb +68 -0
- data/lib/hecks/bluebook/command.rb +124 -0
- data/lib/hecks/bluebook/domain_port.rb +102 -0
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +906 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +327 -0
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1018 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +626 -0
- data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
- data/lib/hecks/bluebook/dsl/entity_builder.rb +305 -0
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
- data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
- data/lib/hecks/bluebook/dsl/policy_builder.rb +120 -0
- data/lib/hecks/bluebook/dsl/port_builder.rb +30 -0
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +207 -0
- data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
- data/lib/hecks/bluebook/dsl/rule_reference.rb +172 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
- data/lib/hecks/bluebook/dsl/word_gate.rb +221 -0
- data/lib/hecks/bluebook/dsl/world_builder.rb +77 -0
- data/lib/hecks/bluebook/dsl.rb +45 -0
- data/lib/hecks/bluebook/entity.rb +103 -0
- data/lib/hecks/bluebook/expression/canonical_form.rb +55 -0
- data/lib/hecks/bluebook/expression/evaluator.rb +261 -0
- data/lib/hecks/bluebook/expression/projection.json +170 -0
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
- data/lib/hecks/bluebook/expression/resolver.rb +630 -0
- data/lib/hecks/bluebook/expression.rb +13 -0
- data/lib/hecks/bluebook/hexagon.rb +60 -0
- data/lib/hecks/bluebook/lifecycle.rb +42 -0
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
- data/lib/hecks/bluebook/meta_validator/judge.rb +559 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +47 -0
- data/lib/hecks/bluebook/meta_validator/readings.rb +350 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +312 -0
- data/lib/hecks/bluebook/meta_validator/shapes.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
- data/lib/hecks/bluebook/meta_validator.rb +452 -0
- data/lib/hecks/bluebook/model_check.rb +318 -0
- data/lib/hecks/bluebook/pattern_subset.rb +120 -0
- data/lib/hecks/bluebook/policy.rb +41 -0
- data/lib/hecks/bluebook/process_manager.rb +86 -0
- data/lib/hecks/bluebook/project_discovery.rb +30 -0
- data/lib/hecks/bluebook/project_loader.rb +40 -0
- data/lib/hecks/bluebook/project_register.rb +82 -0
- data/lib/hecks/bluebook/query.rb +61 -0
- data/lib/hecks/bluebook/read_model.rb +109 -0
- data/lib/hecks/bluebook/reference.rb +74 -0
- data/lib/hecks/bluebook/smoke_test.rb +166 -0
- data/lib/hecks/bluebook/synthesizer.rb +95 -0
- data/lib/hecks/bluebook/translation.rb +92 -0
- data/lib/hecks/bluebook/value_object.rb +58 -0
- data/lib/hecks/bluebook.rb +74 -0
- data/lib/hecks/codemod.rb +342 -0
- data/lib/hecks/construct.rb +71 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
- data/lib/hecks/deploy/oidc.json +18 -0
- data/lib/hecks/doc/reference.rb +389 -0
- data/lib/hecks/embryonaut_bluebook.rb +75 -0
- data/lib/hecks/facade/cli_door.rb +116 -0
- data/lib/hecks/facade/cli_runner.rb +190 -0
- data/lib/hecks/facade/command_request.rb +105 -0
- data/lib/hecks/facade/handle.rb +173 -0
- data/lib/hecks/facade/json_door.rb +154 -0
- data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
- data/lib/hecks/facade/surface/chapter.rb +107 -0
- data/lib/hecks/facade/surface.rb +48 -0
- data/lib/hecks/facade.rb +44 -0
- data/lib/hecks/forms/app.rb +300 -0
- data/lib/hecks/forms/command_form_renderer.rb +113 -0
- data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
- data/lib/hecks/forms/field_renderer.rb +170 -0
- data/lib/hecks/forms/field_shape.rb +232 -0
- data/lib/hecks/forms/html.rb +53 -0
- data/lib/hecks/forms/index_renderer.rb +35 -0
- data/lib/hecks/forms/page.rb +157 -0
- data/lib/hecks/forms/params.rb +132 -0
- data/lib/hecks/forms/query_form_renderer.rb +114 -0
- data/lib/hecks/forms/record_renderer.rb +115 -0
- data/lib/hecks/forms/record_table.rb +63 -0
- data/lib/hecks/forms/reference_options.rb +30 -0
- data/lib/hecks/forms/value_object_shape.rb +46 -0
- data/lib/hecks/forms.rb +54 -0
- data/lib/hecks/fqn.rb +94 -0
- data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
- data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
- data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
- data/lib/hecks/framework/bluebook/governance.bluebook +130 -0
- data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
- data/lib/hecks/framework/oidc.json +39 -0
- data/lib/hecks/framework.rb +90 -0
- data/lib/hecks/freezer.rb +67 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +92 -0
- data/lib/hecks/fuzzing/properties.rb +1146 -0
- data/lib/hecks/fuzzing/replay.rb +635 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +54 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +185 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +130 -0
- data/lib/hecks/fuzzing/value_generator.rb +177 -0
- data/lib/hecks/fuzzing.rb +12 -0
- data/lib/hecks/grammar/evolve.rb +291 -0
- data/lib/hecks/grammar/expression.bluebook +417 -0
- data/lib/hecks/grammar/expression_operators.json +1152 -0
- data/lib/hecks/grammar/grammar.hecksagon +20 -0
- data/lib/hecks/grammar/oidc.json +69 -0
- data/lib/hecks/grammar/translation.bluebook +203 -0
- data/lib/hecks/grammar.rb +178 -0
- data/lib/hecks/ir.rb +126 -0
- data/lib/hecks/language/adapter.bluebook +116 -0
- data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
- data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
- data/lib/hecks/language/bluebook/command.bluebook +437 -0
- data/lib/hecks/language/bluebook/entity.bluebook +316 -0
- data/lib/hecks/language/bluebook/policy.bluebook +172 -0
- data/lib/hecks/language/bluebook/process_manager.bluebook +264 -0
- data/lib/hecks/language/bluebook/projection.bluebook +267 -0
- data/lib/hecks/language/bluebook/query.bluebook +245 -0
- data/lib/hecks/language/bluebook/shape.bluebook +292 -0
- data/lib/hecks/language/bluebook/syntax.bluebook +447 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +364 -0
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
- data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
- data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
- data/lib/hecks/language/oidc.json +313 -0
- data/lib/hecks/language/port.bluebook +92 -0
- data/lib/hecks/language/translation/translation.bluebook +110 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
- data/lib/hecks/language/world/wiring.bluebook +62 -0
- data/lib/hecks/language/world/world.bluebook +84 -0
- data/lib/hecks/literal.rb +125 -0
- data/lib/hecks/naming.rb +121 -0
- data/lib/hecks/ports/access_control.port +4 -0
- data/lib/hecks/ports/access_control.rb +62 -0
- data/lib/hecks/ports/agent/answers.rb +104 -0
- data/lib/hecks/ports/agent.port +4 -0
- data/lib/hecks/ports/agent.rb +167 -0
- data/lib/hecks/ports/authentication.port +4 -0
- data/lib/hecks/ports/authentication.rb +50 -0
- data/lib/hecks/ports/authorization.port +4 -0
- data/lib/hecks/ports/authorization.rb +59 -0
- data/lib/hecks/ports/clock.port +4 -0
- data/lib/hecks/ports/clock.rb +62 -0
- data/lib/hecks/ports/extraction.port +4 -0
- data/lib/hecks/ports/extraction.rb +37 -0
- data/lib/hecks/ports/identity_assignment.port +4 -0
- data/lib/hecks/ports/identity_assignment.rb +45 -0
- data/lib/hecks/ports/identity_generation.port +4 -0
- data/lib/hecks/ports/identity_generation.rb +49 -0
- data/lib/hecks/ports/identity_resolution.port +4 -0
- data/lib/hecks/ports/identity_resolution.rb +40 -0
- data/lib/hecks/ports/loading.port +4 -0
- data/lib/hecks/ports/loading.rb +13 -0
- data/lib/hecks/ports/persistence/append_only.rb +102 -0
- data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
- data/lib/hecks/ports/persistence/execution.rb +18 -0
- data/lib/hecks/ports/persistence/lineage.rb +277 -0
- data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
- data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
- data/lib/hecks/ports/persistence.port +4 -0
- data/lib/hecks/ports/persistence.rb +39 -0
- data/lib/hecks/ports/projection.port +4 -0
- data/lib/hecks/ports/projection.rb +76 -0
- data/lib/hecks/ports/query/in_memory.rb +60 -0
- data/lib/hecks/ports/query/ordering.rb +41 -0
- data/lib/hecks/ports/query.rb +36 -0
- data/lib/hecks/ports.rb +27 -0
- data/lib/hecks/projections/diagrams.rb +413 -0
- data/lib/hecks/projections/ir.rb +18 -0
- data/lib/hecks/projections/model/deviations.rb +98 -0
- data/lib/hecks/projections/model.rb +145 -0
- data/lib/hecks/projections/oidc.rb +110 -0
- data/lib/hecks/projections/parser_table.rb +159 -0
- data/lib/hecks/projections/reference.rb +38 -0
- data/lib/hecks/projections/shape.rb +31 -0
- data/lib/hecks/projections/statements.rb +110 -0
- data/lib/hecks/projections/vocabulary.rb +100 -0
- data/lib/hecks/projections.rb +32 -0
- data/lib/hecks/projector/cli_projector.rb +437 -0
- data/lib/hecks/projector/docs_projector.rb +321 -0
- data/lib/hecks/projector/exporter.rb +141 -0
- data/lib/hecks/projector/ir_projector.rb +18 -0
- data/lib/hecks/projector/narrate_projector.rb +243 -0
- data/lib/hecks/projector/target.rb +97 -0
- data/lib/hecks/projector.rb +186 -0
- data/lib/hecks/query_ir.rb +392 -0
- data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
- data/lib/hecks/query_specification/common/comparators.rb +25 -0
- data/lib/hecks/query_specification/common/comparison.rb +174 -0
- data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
- data/lib/hecks/query_specification/common/dsl.rb +58 -0
- data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
- data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
- data/lib/hecks/query_specification/common/null_policy.rb +80 -0
- data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
- data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
- data/lib/hecks/query_specification/common/options.rb +32 -0
- data/lib/hecks/query_specification/common/order_by.rb +9 -0
- data/lib/hecks/query_specification/common/specification.rb +10 -0
- data/lib/hecks/query_specification/common/where_clause.rb +9 -0
- data/lib/hecks/query_specification/field_path.rb +89 -0
- data/lib/hecks/query_specification/hop_path.rb +130 -0
- data/lib/hecks/query_specification/read_model/specification.rb +18 -0
- data/lib/hecks/query_specification.rb +14 -0
- data/lib/hecks/rendering.rb +48 -0
- data/lib/hecks/router/namespace_installer.rb +157 -0
- data/lib/hecks/router.rb +70 -0
- data/lib/hecks/runtime/caller.rb +50 -0
- data/lib/hecks/runtime/capability_graph.rb +44 -0
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +124 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +248 -0
- data/lib/hecks/runtime/command_interpreter.rb +413 -0
- data/lib/hecks/runtime/command_rules/admissibility.rb +307 -0
- data/lib/hecks/runtime/command_rules/arithmetic.rb +254 -0
- data/lib/hecks/runtime/command_rules/authorization.rb +64 -0
- data/lib/hecks/runtime/command_rules/emission.rb +34 -0
- data/lib/hecks/runtime/command_rules/references.rb +181 -0
- data/lib/hecks/runtime/command_rules.rb +28 -0
- data/lib/hecks/runtime/dependency_planning.rb +231 -0
- data/lib/hecks/runtime/dispatcher.rb +286 -0
- data/lib/hecks/runtime/entity_element.rb +253 -0
- data/lib/hecks/runtime/entity_interpreter.rb +228 -0
- data/lib/hecks/runtime/era_check.rb +136 -0
- data/lib/hecks/runtime/era_guard/shape_diff.rb +128 -0
- data/lib/hecks/runtime/era_guard.rb +193 -0
- data/lib/hecks/runtime/era_tamper.rb +61 -0
- data/lib/hecks/runtime/errors.rb +100 -0
- data/lib/hecks/runtime/event.rb +51 -0
- data/lib/hecks/runtime/identity.rb +128 -0
- data/lib/hecks/runtime/instance.rb +120 -0
- data/lib/hecks/runtime/interpreting.rb +69 -0
- data/lib/hecks/runtime/loader.rb +143 -0
- data/lib/hecks/runtime/policy_interpreter.rb +366 -0
- data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
- data/lib/hecks/runtime/query_interpreter.rb +254 -0
- data/lib/hecks/runtime/reaction_invocation.rb +245 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +266 -0
- data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
- data/lib/hecks/runtime/reference_hop.rb +99 -0
- data/lib/hecks/runtime/refusal_wording.rb +124 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +70 -0
- data/lib/hecks/runtime/registry/verification.rb +158 -0
- data/lib/hecks/runtime/registry.rb +218 -0
- data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
- data/lib/hecks/runtime/routing.rb +96 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
- data/lib/hecks/runtime/saga_interpreter.rb +301 -0
- data/lib/hecks/runtime/storage_shape.rb +120 -0
- data/lib/hecks/runtime/tenant_check.rb +84 -0
- data/lib/hecks/runtime/tenant_scope.rb +55 -0
- data/lib/hecks/runtime/value/admission.rb +112 -0
- data/lib/hecks/runtime/value/coercion.rb +500 -0
- data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
- data/lib/hecks/runtime/value.rb +125 -0
- data/lib/hecks/runtime.rb +95 -0
- data/lib/hecks/translation/audit/approval_digest.rb +31 -0
- data/lib/hecks/translation/audit/layer_one.rb +37 -0
- data/lib/hecks/translation/audit/layer_two.rb +77 -0
- data/lib/hecks/translation/audit/unfed_report.rb +42 -0
- data/lib/hecks/translation/audit.rb +70 -0
- data/lib/hecks/translation/reattest.rb +72 -0
- data/lib/hecks/translation/rule_compiler.rb +120 -0
- data/lib/hecks/translation/scaffold/differ.rb +183 -0
- data/lib/hecks/translation/scaffold/renderer.rb +41 -0
- data/lib/hecks/translation/scaffold/writer.rb +28 -0
- data/lib/hecks/translation/scaffold.rb +30 -0
- data/lib/hecks/translation.rb +11 -0
- data/lib/hecks/version.rb +16 -0
- data/lib/hecks/vocabulary.rb +213 -0
- data/lib/hecks.rb +118 -6
- metadata +401 -222
- data/bin/hecks +0 -7
- data/bin/hecks-package +0 -65
- data/bin/hecks_console +0 -12
- data/bin/hecks_serverless +0 -6
- data/lib/cli/build.rb +0 -14
- data/lib/cli/command_runner.rb +0 -28
- data/lib/cli/console.rb +0 -10
- data/lib/cli/generate.rb +0 -37
- data/lib/cli/hecks-cli.rb +0 -27
- data/lib/cli/test.rb +0 -57
- data/lib/console/commands.rb +0 -8
- data/lib/console/hecks-console.rb +0 -1
- data/lib/packager/README.md +0 -0
- data/lib/packager/app_runner.rb +0 -21
- data/lib/packager/args.rb +0 -26
- data/lib/packager/compatibility/fixnum.rb +0 -6
- data/lib/packager/hecks.rb +0 -39
- data/lib/packager/query_runner.rb +0 -21
- data/lib/packager/resources/Dockerfile +0 -11
- data/lib/packager/resources/app_binary +0 -7
- data/lib/packager/resources/bundle_config +0 -3
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
- data/lib/serverless/Domain +0 -32
- data/lib/serverless/cli.rb +0 -75
- data/lib/serverless/resources/command_name.js +0 -5
- data/lib/serverless/resources/environment.js +0 -7
- data/lib/serverless/resources/handler.js.tt +0 -28
- data/lib/serverless/resources/run_binary.js +0 -22
- data/lib/serverless/resources/serverless.yml +0 -20
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module MetaValidator
|
|
4
|
+
# The leaf shapes of a reconstructed bluebook, and the encodings that go with
|
|
5
|
+
# them.
|
|
6
|
+
#
|
|
7
|
+
# Reconstruction walks the tree; this rebuilds the small hashes at its tips —
|
|
8
|
+
# an attribute, a rule, a where-clause, a transition — and undoes the two
|
|
9
|
+
# things the walk encodes on the way in: an attribute's type offered as the ID
|
|
10
|
+
# of whatever it names, and an append flattened to one row per binding.
|
|
11
|
+
#
|
|
12
|
+
# Separate from the traversal because they are different concerns, and because
|
|
13
|
+
# the two together were 211 code lines against a 200 limit.
|
|
14
|
+
module Shapes
|
|
15
|
+
# The type came in as the id of what it names, so it goes back out as the
|
|
16
|
+
# name — or, for another aggregate's head, as the encoding the IR spells.
|
|
17
|
+
def attribute(field, aggregate_id)
|
|
18
|
+
type = text(field[:type]).to_s
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
name: text(field[:name])&.to_sym,
|
|
22
|
+
type: owned_type(type, aggregate_id) || reference_type(type),
|
|
23
|
+
list: text(field[:list]).to_s == "true",
|
|
24
|
+
default: decode_literal(text(field[:default])),
|
|
25
|
+
# Read back the same way `list` is — both are booleans about the
|
|
26
|
+
# attribute, held as text, and dropping either would rebuild a
|
|
27
|
+
# bluebook that no longer says what it said.
|
|
28
|
+
optional: text(field[:optional]).to_s == "true",
|
|
29
|
+
pattern: presence(text(field[:pattern])),
|
|
30
|
+
# THE ROUND TRIP IS THE ONLY WAY IN. The grammar registry keeps the
|
|
31
|
+
# ASSEMBLED graph — the language as its own judge read it back — so a
|
|
32
|
+
# fact dropped here is a fact no downstream projection ever sees, no
|
|
33
|
+
# matter how plainly the .bluebook file declares it.
|
|
34
|
+
admits: presence(text(field[:admits])),
|
|
35
|
+
relationship: presence(text(field[:relationship]))
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A TYPE THIS AGGREGATE OWNS, offered as its id and read back as its name.
|
|
40
|
+
# Prefixed with the owner and the identity join, because that IS the value
|
|
41
|
+
# object's identity — the aggregate it belongs to, then its name.
|
|
42
|
+
def owned_type(type, aggregate_id)
|
|
43
|
+
prefix = Naming.identity([aggregate_id, ""])
|
|
44
|
+
return nil unless type.start_with?(prefix)
|
|
45
|
+
|
|
46
|
+
type.delete_prefix(prefix)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# ONE PART OF AN IDENTITY, read back as the path it went in as. The inverse
|
|
50
|
+
# of `Marks#identity_path`, and named the same so the two directions read
|
|
51
|
+
# as one table.
|
|
52
|
+
def identity_path(part) = text(part[:value]).to_s
|
|
53
|
+
|
|
54
|
+
# An argument, a parameter, a piece's attribute — the three places an
|
|
55
|
+
# attribute is written that carry no owner id to strip.
|
|
56
|
+
#
|
|
57
|
+
# A REFERENCE among them came in as the head's ID, because that is what
|
|
58
|
+
# Command/Entity/Query.Reference offer, so it goes back out as the
|
|
59
|
+
# encoding the IR spells. A qualified name is the tell : an ordinary
|
|
60
|
+
# type names something declared beside it (`Money`, `AccountNumber`) and
|
|
61
|
+
# never carries a chapter, while a head's id always does.
|
|
62
|
+
def shape_field(field)
|
|
63
|
+
type = text(field[:type]).to_s
|
|
64
|
+
|
|
65
|
+
{
|
|
66
|
+
name: text(field[:name])&.to_sym,
|
|
67
|
+
# A QUALIFIED name is the tell : an ordinary type names something
|
|
68
|
+
# declared beside it (`Money`, `AccountNumber`) and carries no join at
|
|
69
|
+
# all, where a head's id always does (chapter + name, joined the way
|
|
70
|
+
# every derived id is).
|
|
71
|
+
type: type.include?(Naming::IDENTITY_JOIN) ? reference_type(type) : text(field[:type]),
|
|
72
|
+
list: text(field[:list]).to_s == "true",
|
|
73
|
+
default: decode_literal(text(field[:default])),
|
|
74
|
+
optional: text(field[:optional]).to_s == "true",
|
|
75
|
+
pattern: presence(text(field[:pattern])),
|
|
76
|
+
admits: presence(text(field[:admits])),
|
|
77
|
+
relationship: presence(text(field[:relationship]))
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# An ABSENT pattern is nil, not "". The language holds every field as
|
|
82
|
+
# text, so a field nobody set comes back as the empty string — and ""
|
|
83
|
+
# is a real regex (it matches everything), so keeping it would turn
|
|
84
|
+
# "no pattern" into "a pattern that always passes" and quietly cost the
|
|
85
|
+
# IR its round trip.
|
|
86
|
+
def presence(text)
|
|
87
|
+
value = text.to_s
|
|
88
|
+
value.empty? ? nil : value
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# A literal, read back from the self-describing form Readings#encode_literal
|
|
92
|
+
# wrote — the same reader Assembly::Marks uses, because it is the same
|
|
93
|
+
# spelling. The forms are exactly the five the Primitive vocabulary admits —
|
|
94
|
+
# String, Integer, Float, TrueClass, FalseClass — plus a symbol, and an
|
|
95
|
+
# object literal, which is what `to: { value: "good" }` is: a value object's
|
|
96
|
+
# fields written inline.
|
|
97
|
+
def decode_literal(text) = Literal.read(text)
|
|
98
|
+
|
|
99
|
+
def rule(row) = { description: text(row[:description]), canonical: text(row[:canonical]) }
|
|
100
|
+
|
|
101
|
+
# S12, ADR 0025 — `projects :name, from: :"reference.remote_field"`,
|
|
102
|
+
# read back the same three plain identifiers `rule` above reads
|
|
103
|
+
# description/canonical as.
|
|
104
|
+
def projected_field(row)
|
|
105
|
+
{ name: text(row[:name]), reference: text(row[:reference]), remote_field: text(row[:remote_field]) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# `provenance from: {...}` rides the same literal encoding `default:`
|
|
109
|
+
# does — an object literal, self-describing via Hecks::Literal — one
|
|
110
|
+
# level up: a whole keyword's argument rather than an attribute's
|
|
111
|
+
# `default:`.
|
|
112
|
+
def provenance(row) = decode_literal(text(row[:provenance]))
|
|
113
|
+
|
|
114
|
+
# `command "Debit", from: "open"` — the SAME literal encoding
|
|
115
|
+
# `provenance`/`default:` already ride (S10, ADR 0025), one
|
|
116
|
+
# state or an array of them, or nil for a command with no
|
|
117
|
+
# lifecycle guard.
|
|
118
|
+
def from(row) = decode_literal(text(row[:from]))
|
|
119
|
+
|
|
120
|
+
# THE OPTION ROWS, GATHERED BACK into the shapes `extra_options_to_h` spells.
|
|
121
|
+
#
|
|
122
|
+
# One row per part, so a compound option is several rows and a repeated one is
|
|
123
|
+
# several groups told apart by `at`. Grouping by option name and then by `at`
|
|
124
|
+
# rebuilds both without either knowing which options exist — the whole point
|
|
125
|
+
# of holding them as an open map.
|
|
126
|
+
def options_of(row)
|
|
127
|
+
Array(row[:options])
|
|
128
|
+
.group_by { |part| text(part[:option]) }
|
|
129
|
+
.to_h { |option, parts| [option.to_sym, gathered(parts)] }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def gathered(parts)
|
|
133
|
+
repeated, single = parts.partition { |part| !text(part[:at]).to_s.empty? }
|
|
134
|
+
return single.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } if repeated.empty?
|
|
135
|
+
|
|
136
|
+
repeated.group_by { |part| text(part[:at]) }
|
|
137
|
+
.values
|
|
138
|
+
.map { |group| group.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# The IR keeps a where's field as a STRING, not a symbol — it is read back
|
|
142
|
+
# out, never called. The value stays RAW TEXT here on purpose : this
|
|
143
|
+
# feeds the declaration hash Assembly::Marks#where_clause decodes
|
|
144
|
+
# from (via `read`), and decoding twice is worse than once — a
|
|
145
|
+
# kwarg reference (":ceiling") decoded here into the Symbol :ceiling
|
|
146
|
+
# would have its colon stripped by `read`'s own `.to_s` and come
|
|
147
|
+
# back out as the plain string "ceiling", indistinguishable from a
|
|
148
|
+
# literal of the same name. One decode, at the one place that builds
|
|
149
|
+
# the object every comparator actually reads.
|
|
150
|
+
def where_clause(row)
|
|
151
|
+
{ field: text(row[:field]), op: text(row[:op]), value: text(row[:value]) }
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# One object in the IR, two fields in the language.
|
|
155
|
+
def order_by(row)
|
|
156
|
+
field = text(row[:order_field])
|
|
157
|
+
return nil if field.to_s.empty?
|
|
158
|
+
|
|
159
|
+
{ field: field, direction: text(row[:order_way]) }
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def limit(row)
|
|
163
|
+
ceiling = text(row[:limit])
|
|
164
|
+
return nil if ceiling.to_s.empty?
|
|
165
|
+
|
|
166
|
+
{ value: ceiling }
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def transition(row)
|
|
170
|
+
{
|
|
171
|
+
command: text(row[:command]),
|
|
172
|
+
from_state: text(row[:from_state]),
|
|
173
|
+
to_state: text(row[:to_state])
|
|
174
|
+
}
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def head(row)
|
|
178
|
+
{
|
|
179
|
+
aggregate: text(row[:aggregate]),
|
|
180
|
+
# A String, like an entity's identified_by. The IR is not uniform about
|
|
181
|
+
# this and only a round trip says so.
|
|
182
|
+
as: text(row[:as]),
|
|
183
|
+
many: text(row[:many]).to_s == "true"
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def group_by_field(row) = { field: text(row[:field]) }
|
|
188
|
+
|
|
189
|
+
# `count`'s own boolean, read back the SAME way `head`'s own
|
|
190
|
+
# `many` is (`text(row[:many]).to_s == "true"`) — except a
|
|
191
|
+
# `ReadModel.Count` command is dispatched AT ALL only when
|
|
192
|
+
# `@count` was truthy (`MetaValidator::Judge#setters` skips a
|
|
193
|
+
# setter whose every source is absent), so an undeclared read
|
|
194
|
+
# model's own `count` field never gets written and comes back
|
|
195
|
+
# `nil` here, never `"false"` — matching `ReadModel#to_h`'s own
|
|
196
|
+
# `true`/`nil` pair (never `false`) exactly, rather than the
|
|
197
|
+
# unconditional `true`/`false` `head`'s own `many` needs (every
|
|
198
|
+
# head DOES get a `Gather` dispatch, declared or derived).
|
|
199
|
+
def read_model_count(row) = (true if text(row[:count]).to_s == "true")
|
|
200
|
+
|
|
201
|
+
# THE APPEND FLATTENING, IN REVERSE.
|
|
202
|
+
#
|
|
203
|
+
# An append binds several fields at once and the language's Change holds one
|
|
204
|
+
# field/kind/source triple, so the walk offers an append once PER BINDING.
|
|
205
|
+
# Rebuilding groups those rows back into the single mutation the IR keeps —
|
|
206
|
+
# the only place here that undoes something rather than simply reading it.
|
|
207
|
+
def mutations(row)
|
|
208
|
+
Array(row[:mutations])
|
|
209
|
+
.group_by { |change| [text(change[:target]), text(change[:op])] }
|
|
210
|
+
.map { |(target, op), bindings| mutation(target, op, bindings) }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# `sign:` — read the SAME way the declared side computes it
|
|
214
|
+
# (`Bluebook::Mutation.sign_for`, item #5 of the whole-project
|
|
215
|
+
# table-unification survey), not stored on any row here — the
|
|
216
|
+
# meta-domain's own Change entity carries no `sign` field of its
|
|
217
|
+
# own (it is a pure function of `op`, nothing to persist), so
|
|
218
|
+
# reconstruction recomputes it the same way a freshly-built
|
|
219
|
+
# Mutation's own `to_h` lambda does, rather than leaving the key
|
|
220
|
+
# silently absent (spec/round_trip_spec's whole point: a field the
|
|
221
|
+
# language does not hold is a named gap, not a byte-for-byte one).
|
|
222
|
+
def mutation(target, op, bindings)
|
|
223
|
+
base = { target: target.to_sym, op: op.to_sym, sign: Hecks::Bluebook::Mutation.sign_for(op) }
|
|
224
|
+
# `:delegate` (CommandBuilder#delegates_to's own comment) rides
|
|
225
|
+
# the SAME multi-binding shape `:append` does.
|
|
226
|
+
return base.merge(fields: appended(bindings)) if ["append", "delegate"].include?(op)
|
|
227
|
+
|
|
228
|
+
base.merge(source: classified(bindings.first))
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def appended(bindings)
|
|
232
|
+
bindings.to_h { |binding| [text(binding[:field]).to_sym, text(binding[:source])] }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def classified(binding)
|
|
236
|
+
kind = text(binding[:kind])
|
|
237
|
+
value = text(binding[:source])
|
|
238
|
+
|
|
239
|
+
return { kind: kind, name: value } if %w[argument state].include?(kind)
|
|
240
|
+
|
|
241
|
+
{ kind: "literal", value: decode_literal(value) }
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module MetaValidator
|
|
4
|
+
# S14, ADR 0026 — DISPATCHES THE LANGUAGE'S OWN GRAMMAR TABLE INTO
|
|
5
|
+
# ITSELF, once, so `Keyword`/`Argument`'s own `status` genuinely IS a
|
|
6
|
+
# lifecycle — checked at real dispatch time (the same admission/
|
|
7
|
+
# coercion/lifecycle-guard door every other command goes through),
|
|
8
|
+
# not merely declared and never exercised.
|
|
9
|
+
#
|
|
10
|
+
# THE SOURCE STAYS STATIC. Aggregate-local `KeywordSeed`/
|
|
11
|
+
# `ArgumentSeed` value objects (still hand-written `member` rows —
|
|
12
|
+
# now beside the concepts they spell) are what gets WRITTEN ; this
|
|
13
|
+
# is what turns them into what gets READ. `Judge`/`Reconstruction`
|
|
14
|
+
# already draw exactly this line everywhere else in the meta-domain
|
|
15
|
+
# (a chapter's own DECLARATIONS versus what gets DISPATCHED from
|
|
16
|
+
# them) — this runs the same distinction one level further out, for
|
|
17
|
+
# the language's own grammar table.
|
|
18
|
+
#
|
|
19
|
+
# A DEDICATED RUNTIME, not `MetaValidator.fresh_runtime`. That one
|
|
20
|
+
# is reserved for `Judge`'s own bootstrap (dispatching a CHAPTER's
|
|
21
|
+
# declarations INTO the meta-domain's grammar) — a different act
|
|
22
|
+
# from this one (dispatching the meta-domain's OWN grammar table
|
|
23
|
+
# data into a live "Bluebook" domain instance). Sharing the runtime
|
|
24
|
+
# would let one boot's own repository state leak into the other's.
|
|
25
|
+
#
|
|
26
|
+
# Usage:
|
|
27
|
+
#
|
|
28
|
+
# MetaValidator.syntax_table # => { keywords: [...], arguments: [...] }
|
|
29
|
+
#
|
|
30
|
+
# each row a plain Hash, string values, `status` included — the
|
|
31
|
+
# exact shape `ParserTable`/`syntax_conformance_spec` already read
|
|
32
|
+
# off the OLD closed-set members, so neither consumer had to change
|
|
33
|
+
# what it does with a row, only where the row comes from.
|
|
34
|
+
module SyntaxBoot
|
|
35
|
+
module_function
|
|
36
|
+
|
|
37
|
+
# Memoized the same way `MetaValidator.grammar_registry` itself
|
|
38
|
+
# is — the ~284-command dispatch sequence below is real work, not
|
|
39
|
+
# something three separate callers (ParserTable, syntax_
|
|
40
|
+
# conformance_spec, bin/reference) should each pay for on every
|
|
41
|
+
# call.
|
|
42
|
+
#
|
|
43
|
+
# KEYED BY THE GRAMMAR REGISTRY'S OWN CHAPTER SET, not by a
|
|
44
|
+
# "ready" flag. `boot` reads exactly two things: the registry's
|
|
45
|
+
# "Bluebook" chapter (the core seed rows) and every chapter in the
|
|
46
|
+
# registry that `attaches_to` a core context (Paging's rows). So
|
|
47
|
+
# the table is a pure function of which chapter OBJECTS the
|
|
48
|
+
# registry holds — and that is the cache key: the same chapters,
|
|
49
|
+
# by identity, mean the same table; a chapter replaced (the
|
|
50
|
+
# fixpoint judge swapping a raw chapter for its assembled self)
|
|
51
|
+
# or added (`load_attached_grammar_into`) means a fresh boot.
|
|
52
|
+
#
|
|
53
|
+
# WHY NOT THE EARLIER `grammar_registry_ready?` GUARD. That guard
|
|
54
|
+
# was right about the hazard — a snapshot taken mid-build, before
|
|
55
|
+
# Paging attached, would be missing limit/offset/cursor/nulls
|
|
56
|
+
# forever — and wrong about the cost of its cure. It refused to
|
|
57
|
+
# cache ANYTHING until the whole grammar registry had finished
|
|
58
|
+
# building, calling that window "narrow" and recomputing in it
|
|
59
|
+
# "cheap". Measured (hecks_ai_training, a six-entity chess domain,
|
|
60
|
+
# 2026-08-22): every `word_gate_dispatch` landing in that window
|
|
61
|
+
# re-ran the full ~284-dispatch boot at ~0.76s each — 42 times per
|
|
62
|
+
# process, 32 of a 35-second `Hecks.boot`, 95% of which had
|
|
63
|
+
# nothing to do with the domain being booted. Keying on the
|
|
64
|
+
# chapter set closes the same hazard by construction (a snapshot
|
|
65
|
+
# can only be served while the chapters it was read from are
|
|
66
|
+
# still the chapters the registry holds) and lets the window's
|
|
67
|
+
# own repeated, identical calls share one boot. A registry reset
|
|
68
|
+
# (fixpoint_spec's own `@grammar_registry = nil`) yields new
|
|
69
|
+
# chapter objects, so it invalidates this the same way it always
|
|
70
|
+
# invalidated `grammar_registry_ready?`.
|
|
71
|
+
#
|
|
72
|
+
# `equal?`, NOT `==`, on the chapters — identity is the fact being
|
|
73
|
+
# tracked. Holding the chapter objects themselves (not their ids)
|
|
74
|
+
# in the key also means a collected chapter can never hand its id
|
|
75
|
+
# to a newcomer behind this cache's back.
|
|
76
|
+
def call
|
|
77
|
+
chapters = MetaValidator.grammar_registry.bluebooks.to_a
|
|
78
|
+
return @call if @call && same_chapters?(@call_chapters, chapters)
|
|
79
|
+
|
|
80
|
+
result = boot
|
|
81
|
+
@call = result
|
|
82
|
+
@call_chapters = chapters
|
|
83
|
+
result
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def same_chapters?(cached, current)
|
|
87
|
+
cached.size == current.size &&
|
|
88
|
+
cached.zip(current).all? { |(cached_name, cached_chapter), (name, chapter)| cached_name == name && cached_chapter.equal?(chapter) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def boot
|
|
92
|
+
bluebook = MetaValidator.grammar_registry.bluebook("Bluebook")
|
|
93
|
+
# `MetaValidator.fresh_runtime`, not a brand-new `Runtime::
|
|
94
|
+
# Registry` — the grammar registry's own copy already has
|
|
95
|
+
# "Bluebook" registered (`grammar_registry`'s own boot already
|
|
96
|
+
# ran `registry.add_bluebook`) AND its adapter ports already
|
|
97
|
+
# loaded ; a standalone registry would need both wired by hand.
|
|
98
|
+
# `fresh_runtime` resets `@repositories` on the SAME registry —
|
|
99
|
+
# the identical isolation `Judge.new` already relies on for
|
|
100
|
+
# every real domain it judges, proven safe by every dispatch
|
|
101
|
+
# this session has ever made.
|
|
102
|
+
runtime = MetaValidator.fresh_runtime
|
|
103
|
+
|
|
104
|
+
declare_syntax(runtime, bluebook)
|
|
105
|
+
admit_keywords(runtime, bluebook)
|
|
106
|
+
admit_arguments(runtime, bluebook)
|
|
107
|
+
|
|
108
|
+
read_back(runtime, bluebook)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# An Integer stays an Integer — `position` is `Position`-typed
|
|
112
|
+
# (`attribute :value, Integer`), so stringifying it fails the type
|
|
113
|
+
# gate rather than feeding it, the same reading `Judge#v` gives.
|
|
114
|
+
def v(text)
|
|
115
|
+
return { value: text } if text.is_a?(Integer)
|
|
116
|
+
|
|
117
|
+
{ value: text.to_s }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# ABSENT STAYS ABSENT. A seed row's own optional columns ("was",
|
|
121
|
+
# "at", "named", ...) are empty strings, not nil — `Literal`/CSV-
|
|
122
|
+
# shaped grammar data has no `nil` to write — so this is the one
|
|
123
|
+
# place that decides "" means "not given" for the purpose of an
|
|
124
|
+
# `optional: true` command argument, the same reading `Judge#v`
|
|
125
|
+
# makes for the meta-domain's own dispatches.
|
|
126
|
+
def optional(text)
|
|
127
|
+
return nil if text.nil? || text.to_s.empty?
|
|
128
|
+
|
|
129
|
+
v(text)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# `Syntax.Declare`'s own `reference_to Bluebook` names the CHAPTER
|
|
133
|
+
# it belongs to — the same fact every other top-level aggregate's
|
|
134
|
+
# own creating command carries (`ProcessManager.Declare`,
|
|
135
|
+
# `Policy.Declare`, ...). This fresh runtime holds no chapter
|
|
136
|
+
# record of its own yet (nothing else here needs one), so one is
|
|
137
|
+
# declared first, named after the real chapter, purely to satisfy
|
|
138
|
+
# the reference — its own vision/classification are never read
|
|
139
|
+
# by anything this boot does.
|
|
140
|
+
def declare_syntax(runtime, bluebook)
|
|
141
|
+
syntax = bluebook.aggregate("Syntax")
|
|
142
|
+
runtime.dispatch("Bluebook::Bluebook.Declare", name: v(bluebook.hecks_name),
|
|
143
|
+
vision: v("the language's own grammar table, dispatched into itself"),
|
|
144
|
+
classification: v("core"))
|
|
145
|
+
runtime.dispatch("Bluebook::Syntax.Declare", bluebook: bluebook.hecks_name, name: v(syntax.hecks_name))
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# `to: "Syntax"` NAMES THE RECORD ALREADY OPENED BY `declare_syntax`
|
|
149
|
+
# ABOVE — an append onto an existing aggregate, not a second creation
|
|
150
|
+
# of it. This used to smuggle `name: v("Syntax")` into the payload
|
|
151
|
+
# instead, the pre-routing convention `Judge#appends` (the same
|
|
152
|
+
# append shape, for `ValueObject.Member`/`ProcessManager.Handler`)
|
|
153
|
+
# already left behind for `to:`/`with:` — carrying the receiver in
|
|
154
|
+
# the payload made `Syntax.Keyword`'s own `command.creates?` (true:
|
|
155
|
+
# it declares no `reference_to`) look like a fresh identity to mint,
|
|
156
|
+
# which collided with the very "Syntax" row `declare_syntax` had
|
|
157
|
+
# just opened.
|
|
158
|
+
def admit_keywords(runtime, bluebook)
|
|
159
|
+
all_rows(bluebook, "KeywordSeed").each_with_index do |row, index|
|
|
160
|
+
runtime.dispatch("Bluebook::Syntax.Keyword", to: "Syntax",
|
|
161
|
+
with: { position: v(index),
|
|
162
|
+
word: v(row[:word]), context: v(row[:context]), body: v(row[:body]),
|
|
163
|
+
inner: v(row[:inner]), opens: v(row[:opens]), fills: v(row[:fills]),
|
|
164
|
+
was: optional(row[:was]),
|
|
165
|
+
resolves_via: optional(row[:resolves_via]),
|
|
166
|
+
disambiguator: optional(row[:disambiguator]),
|
|
167
|
+
calls: optional(row[:calls]) })
|
|
168
|
+
|
|
169
|
+
next unless row[:status].to_s == "deprecated"
|
|
170
|
+
|
|
171
|
+
runtime.dispatch("Bluebook::Syntax.Keyword.Deprecate", to: { aggregate: "Syntax", entity: index.to_s })
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def admit_arguments(runtime, bluebook)
|
|
176
|
+
all_rows(bluebook, "ArgumentSeed").each_with_index do |row, index|
|
|
177
|
+
runtime.dispatch("Bluebook::Syntax.Argument", to: "Syntax",
|
|
178
|
+
with: { position: v(index),
|
|
179
|
+
keyword: v(row[:keyword]), context: v(row[:context]),
|
|
180
|
+
at: optional(row[:at]), named: optional(row[:named]),
|
|
181
|
+
kind: v(row[:kind]), required: v(row[:required]), fills: v(row[:fills]),
|
|
182
|
+
selects: optional(row[:selects]), pair_key_fills: optional(row[:pair_key_fills]),
|
|
183
|
+
pair_value_fills: optional(row[:pair_value_fills]),
|
|
184
|
+
pairs_shape: optional(row[:pairs_shape]), variadic: optional(row[:variadic]),
|
|
185
|
+
minimum: optional(row[:minimum]),
|
|
186
|
+
coerce: optional(row[:coerce]), blank_message: optional(row[:blank_message]) })
|
|
187
|
+
|
|
188
|
+
next unless row[:status].to_s == "deprecated"
|
|
189
|
+
|
|
190
|
+
runtime.dispatch("Bluebook::Syntax.Argument.Deprecate", to: { aggregate: "Syntax", entity: index.to_s })
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# EVERY AGGREGATE-LOCAL TABLE IN EVERY LOADED LANGUAGE CHAPTER.
|
|
195
|
+
# The table's presence is the registration: no chapter, aggregate,
|
|
196
|
+
# filename, or context catalog is maintained here. This finds the core
|
|
197
|
+
# Bluebook concepts, the sibling artifact languages (World, Hecksagon,
|
|
198
|
+
# Port, Adapter, Translation), and attached sub-languages alike.
|
|
199
|
+
# Concatenated into ONE sequence because `position` is minted from the
|
|
200
|
+
# walk index and must not collide across concepts.
|
|
201
|
+
def all_rows(bluebook, name)
|
|
202
|
+
seed_chapters(bluebook).flat_map { |chapter| rows(chapter, name) }
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Keep the core chapter first, then registry insertion order for every
|
|
206
|
+
# sibling/extension. The name rejection avoids reading the same core
|
|
207
|
+
# object twice without relying on object identity across fixpoint
|
|
208
|
+
# assembly.
|
|
209
|
+
def seed_chapters(bluebook)
|
|
210
|
+
[bluebook] + MetaValidator.grammar_registry.bluebooks.values.reject { |chapter| chapter.name == bluebook.name }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# The seed rows themselves — plain hashes, string values, read from
|
|
214
|
+
# every aggregate that owns a same-named local value object. Repeating
|
|
215
|
+
# the value-object shape is deliberate: each concept remains readable
|
|
216
|
+
# by itself, while this discovery is the only grouping mechanism.
|
|
217
|
+
def rows(bluebook, name)
|
|
218
|
+
bluebook.aggregates.flat_map do |aggregate|
|
|
219
|
+
value_object = aggregate.value_objects.find { |vo| vo.hecks_name == name }
|
|
220
|
+
next [] unless value_object
|
|
221
|
+
|
|
222
|
+
value_object.members.map { |row| row.to_h.transform_values(&:to_s) }
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Reads the dispatched result back into the SAME shape `rows`
|
|
227
|
+
# above hands the seed data in as — plain hashes, string values,
|
|
228
|
+
# `status` included — so `ParserTable`/`syntax_conformance_spec`
|
|
229
|
+
# need not know or care that a real dispatch happened in between.
|
|
230
|
+
def read_back(runtime, bluebook)
|
|
231
|
+
syntax = bluebook.aggregate("Syntax")
|
|
232
|
+
repository = runtime.registry.repository("Bluebook", syntax)
|
|
233
|
+
instance = repository.find(Naming.identity([syntax.hecks_name]))
|
|
234
|
+
|
|
235
|
+
{
|
|
236
|
+
keywords: Array(instance[:keywords]).map { |row| stringify(row) },
|
|
237
|
+
arguments: Array(instance[:arguments]).map { |row| stringify(row) }
|
|
238
|
+
}
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def stringify(row)
|
|
242
|
+
row.to_h.each_with_object({}) do |(key, cell), out|
|
|
243
|
+
out[key] = scalar(cell).to_s
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def scalar(cell)
|
|
248
|
+
return cell.to_h.values.first if cell.respond_to?(:to_h) && !cell.is_a?(String)
|
|
249
|
+
|
|
250
|
+
cell
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module MetaValidator
|
|
4
|
+
# Offers a built translation (a `translations/*.bluebook` edge,
|
|
5
|
+
# `Hecks.data_translation`'s own real, established file convention —
|
|
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.
|
|
22
|
+
class TranslationJudge
|
|
23
|
+
attr_reader :refusals
|
|
24
|
+
|
|
25
|
+
def initialize(translation)
|
|
26
|
+
@translation = translation
|
|
27
|
+
@refusals = []
|
|
28
|
+
@runtime = MetaValidator.fresh_runtime
|
|
29
|
+
judge!
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def v(text) = text.nil? ? nil : { value: text.to_s }
|
|
35
|
+
|
|
36
|
+
def args(pairs) = pairs.compact
|
|
37
|
+
|
|
38
|
+
# `Runtime::AlreadyExists` is rescued HERE but not by World/Port/
|
|
39
|
+
# Adapter's own sibling judges — found live, not by inspection.
|
|
40
|
+
# Those three each judge a SINGLE aggregate per build (Port/Adapter)
|
|
41
|
+
# or a Hash keyed by verb (World's own settings, deduped by
|
|
42
|
+
# construction), so a duplicate-identity Declare can never reach
|
|
43
|
+
# their own runtime. `TranslationBuilder#aggregate` appends every
|
|
44
|
+
# block to a plain Array (`@aggregates << builder.build`) with no
|
|
45
|
+
# dedup — two `aggregate "Account" do ... end` blocks in the same
|
|
46
|
+
# translation are syntactically legal and reach here for real. Left
|
|
47
|
+
# unrescued, the second Declare's `AlreadyExists` crashed straight
|
|
48
|
+
# through `call_translation` instead of becoming a clean refusal —
|
|
49
|
+
# confirmed via direct dispatch before this fix.
|
|
50
|
+
def offer(label)
|
|
51
|
+
yield
|
|
52
|
+
rescue Runtime::GivenNotMet, Runtime::InvariantViolation, Runtime::TypeMismatch,
|
|
53
|
+
Runtime::NotFound, Runtime::AlreadyExists => e
|
|
54
|
+
@refusals << "#{label}: #{e.message}"
|
|
55
|
+
rescue Runtime::UnknownVerb
|
|
56
|
+
nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def send_to(verb, label, to: nil, with: {})
|
|
60
|
+
offer(label) { @runtime.dispatch(verb, to: to, with: args(with)) }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def judge!
|
|
64
|
+
t = @translation
|
|
65
|
+
send_to("Translation::Translation.Declare", t.domain,
|
|
66
|
+
with: { domain: v(t.domain), from: v(t.from), to: v(t.to) })
|
|
67
|
+
|
|
68
|
+
# `id:`, computed the SAME way — `Naming.identity([domain, from,
|
|
69
|
+
# to])` — Translation's own identity is COMPOSITE
|
|
70
|
+
# (`identified_by :domain, :from, :to`), the same reason
|
|
71
|
+
# `Wiring.Set`'s own self-reference dispatch (world.bluebook,
|
|
72
|
+
# `WorldJudge#judge_wiring`) needs a computed `id:` rather than
|
|
73
|
+
# a bare field value — a single-field identity (TranslationAggregate's
|
|
74
|
+
# own `name`) is the ONE case where the bare value itself IS the
|
|
75
|
+
# id, confirmed live via direct dispatch testing, not assumed.
|
|
76
|
+
translation_id = Naming.identity([t.domain, t.from, t.to])
|
|
77
|
+
Array(t.retired).each do |name|
|
|
78
|
+
send_to("Translation::Translation.Retire", t.domain, to: translation_id,
|
|
79
|
+
with: { value: v(name) })
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
Array(t.aggregates).each { |aggregate| judge_aggregate(t, aggregate) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def judge_aggregate(translation, aggregate)
|
|
86
|
+
name = aggregate.name
|
|
87
|
+
parent = {
|
|
88
|
+
domain: v(translation.domain),
|
|
89
|
+
from: v(translation.from),
|
|
90
|
+
to: v(translation.to)
|
|
91
|
+
}
|
|
92
|
+
send_to("Translation::TranslationAggregate.Declare", name,
|
|
93
|
+
with: { translation_ref: parent, name: v(name), was: v(aggregate.was) })
|
|
94
|
+
|
|
95
|
+
Hash(aggregate.renames).each do |from, to|
|
|
96
|
+
send_to("Translation::TranslationAggregate.AddRename", name, to: name,
|
|
97
|
+
with: { from: v(from), to: v(to) })
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
Array(aggregate.moves).each do |move|
|
|
101
|
+
send_to("Translation::TranslationAggregate.AddMove", name, to: name,
|
|
102
|
+
with: { from: v(move.from), to: v(move.to) })
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
Array(aggregate.converts).each do |convert|
|
|
106
|
+
send_to("Translation::TranslationAggregate.AddConvert", name, to: name,
|
|
107
|
+
with: { from: v(convert.from), to: v(convert.to), values: v(convert.values.inspect) })
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
Array(aggregate.drops).each do |dropped|
|
|
111
|
+
send_to("Translation::TranslationAggregate.AddDrop", name, to: name,
|
|
112
|
+
with: { value: v(dropped) })
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
Array(aggregate.retypes).each do |retype|
|
|
116
|
+
send_to("Translation::TranslationAggregate.AddRetype", name, to: name,
|
|
117
|
+
with: { from: v(retype.from), to: v(retype.to) })
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
Array(aggregate.computes).each do |compute|
|
|
121
|
+
send_to("Translation::TranslationAggregate.AddCompute", name, to: name,
|
|
122
|
+
with: { from: v(compute.from), to: v(compute.to), sql: v(compute.sql) })
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
Array(aggregate.rekeys).each do |rekey|
|
|
126
|
+
send_to("Translation::TranslationAggregate.AddRekey", name, to: name,
|
|
127
|
+
with: { sql: v(rekey.sql) })
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
Array(aggregate.backfills).each do |backfill|
|
|
131
|
+
send_to("Translation::TranslationAggregate.AddBackfill", name, to: name,
|
|
132
|
+
with: { name: v(backfill.name), default: v(backfill.default.inspect) })
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|