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,20 @@
|
|
|
1
|
+
# The expression and translation grammars, bound so they boot standing
|
|
2
|
+
# alone. Both are read-only in practice — Hecks::Grammar parses
|
|
3
|
+
# against them — but a binding is declared rather than defaulted.
|
|
4
|
+
Hecks.hecksagon "Expression" do
|
|
5
|
+
# Every command here declares `role "Language designer"` — only real
|
|
6
|
+
# access control once Governance can check it against something (S8).
|
|
7
|
+
uses_framework "Governance"
|
|
8
|
+
persisted_by "Memory"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Hecks.hecksagon "Translation" do
|
|
12
|
+
# Same reason as Expression, above — S8.
|
|
13
|
+
uses_framework "Governance"
|
|
14
|
+
persisted_by "Memory"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Hecks.hecksagon "Governance" do
|
|
18
|
+
Governance::RoleAssignment.persisted_by("Memory")
|
|
19
|
+
Governance::RoleTransition.persisted_by("Memory")
|
|
20
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"audience": "Expression",
|
|
3
|
+
"scopes": [
|
|
4
|
+
{
|
|
5
|
+
"scope": "expression:expression.admit",
|
|
6
|
+
"verb": "Expression::Expression.Admit",
|
|
7
|
+
"role": "System"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"scope": "expression:expression.extract",
|
|
11
|
+
"verb": "Expression::Expression.Extract",
|
|
12
|
+
"role": "System"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"scope": "expression:expression.note",
|
|
16
|
+
"verb": "Expression::Expression.Note",
|
|
17
|
+
"role": "System"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"scope": "expression:expression.reject",
|
|
21
|
+
"verb": "Expression::Expression.Reject",
|
|
22
|
+
"role": "System"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"scope": "expression:normalisation.admit",
|
|
26
|
+
"verb": "Expression::Normalisation.Admit",
|
|
27
|
+
"role": "Language designer"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"scope": "expression:normalisation.propose",
|
|
31
|
+
"verb": "Expression::Normalisation.Propose",
|
|
32
|
+
"role": "Language designer"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"scope": "expression:normalisation.read",
|
|
36
|
+
"verb": "Expression::Normalisation.Read",
|
|
37
|
+
"role": "Language designer"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"scope": "expression:normalisation.retire",
|
|
41
|
+
"verb": "Expression::Normalisation.Retire",
|
|
42
|
+
"role": "Language designer"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"scope": "expression:operator.admit",
|
|
46
|
+
"verb": "Expression::Operator.Admit",
|
|
47
|
+
"role": "Language designer"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"scope": "expression:operator.propose",
|
|
51
|
+
"verb": "Expression::Operator.Propose",
|
|
52
|
+
"role": "Language designer"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"scope": "expression:operator.render",
|
|
56
|
+
"verb": "Expression::Operator.Render",
|
|
57
|
+
"role": "Language designer"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"scope": "expression:operator.retire",
|
|
61
|
+
"verb": "Expression::Operator.Retire",
|
|
62
|
+
"role": "Language designer"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"roles": [
|
|
66
|
+
"Language designer",
|
|
67
|
+
"System"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
|
|
2
|
+
Hecks.bluebook "Translation" do
|
|
3
|
+
vision "The declared bridge from one era of a domain's storage shape to the next — every rule checkable, every loss written down, carried as one edge file."
|
|
4
|
+
generic
|
|
5
|
+
|
|
6
|
+
aggregate "Rule" do
|
|
7
|
+
description "One admitted way a value survives a shape change — its kind, where it reads from, where it writes to, and how it executes in every target that must apply it."
|
|
8
|
+
|
|
9
|
+
identified_by :source
|
|
10
|
+
|
|
11
|
+
attribute :kind, Kind
|
|
12
|
+
attribute :source, SourcePath
|
|
13
|
+
attribute :destination, DestinationPath
|
|
14
|
+
attribute :executions, list_of(Execution)
|
|
15
|
+
|
|
16
|
+
lifecycle :status, default: "proposed" do
|
|
17
|
+
transition "Admit" => "admitted", from: "proposed"
|
|
18
|
+
transition "Retire" => "retired", from: "admitted"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# THE CLOSED SET OF RULE KINDS — declared as members, not a hand-rolled
|
|
22
|
+
# OR-chain, so the set is data a conformance spec can hold the live
|
|
23
|
+
# builder to (spec/translation_vocabulary_conformance_spec.rb). Nine of
|
|
24
|
+
# these are TranslationAggregateBuilder's own rule methods ; "retired" is
|
|
25
|
+
# the edge-level declaration (TranslationBuilder#retired), in the set
|
|
26
|
+
# because it is one admitted way a shape survives — by not surviving.
|
|
27
|
+
value_object "Kind" do
|
|
28
|
+
attribute :value, String,
|
|
29
|
+
one_of: ["rename", "move", "convert", "drop", "retype", "retired", "compute", "rekey",
|
|
30
|
+
"backfill", "unresolved"]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
value_object "SourcePath" do
|
|
34
|
+
attribute :value, String
|
|
35
|
+
invariant("a rule reads from somewhere") { !value.to_s.empty? }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
value_object "DestinationPath" do
|
|
39
|
+
attribute :value, String
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
value_object "Target" do
|
|
43
|
+
attribute :value, String
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
value_object "Form" do
|
|
47
|
+
attribute :value, String
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
value_object "Execution" do
|
|
51
|
+
attribute :target, String
|
|
52
|
+
attribute :form, String
|
|
53
|
+
|
|
54
|
+
invariant("an execution must name its target") { !target.to_s.empty? }
|
|
55
|
+
invariant("an execution must have a form") { !form.to_s.empty? }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
command "Propose" do
|
|
59
|
+
role "Author"
|
|
60
|
+
goal "Put one way of surviving a shape change forward"
|
|
61
|
+
|
|
62
|
+
attribute :kind, Kind
|
|
63
|
+
attribute :source, SourcePath
|
|
64
|
+
attribute :destination, DestinationPath
|
|
65
|
+
|
|
66
|
+
emits "RuleProposed"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
command "Execute" do
|
|
70
|
+
role "Author"
|
|
71
|
+
goal "Declare how this rule runs in one target"
|
|
72
|
+
|
|
73
|
+
reference_to Rule
|
|
74
|
+
attribute :target, Target
|
|
75
|
+
attribute :form, Form
|
|
76
|
+
|
|
77
|
+
given("a retired rule takes no new executions") { status != "retired" }
|
|
78
|
+
|
|
79
|
+
sets :executions, append: { target: :target, form: :form }
|
|
80
|
+
|
|
81
|
+
emits "RuleExecuted"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
command "Admit" do
|
|
85
|
+
role "Author"
|
|
86
|
+
goal "Accept the rule — it executes identically in every target"
|
|
87
|
+
|
|
88
|
+
reference_to Rule
|
|
89
|
+
|
|
90
|
+
given("a rule must execute in every target before it is admitted") { executions.size >= 2 }
|
|
91
|
+
|
|
92
|
+
emits "RuleAdmitted"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
command "Retire" do
|
|
96
|
+
role "Author"
|
|
97
|
+
goal "Remove the rule from the language"
|
|
98
|
+
|
|
99
|
+
reference_to Rule
|
|
100
|
+
|
|
101
|
+
emits "RuleRetired"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
aggregate "Map" do
|
|
106
|
+
description "One translation edge between two minted eras — the ordered declarations that carry a domain's data across one shape change, sealed before anything boots through it."
|
|
107
|
+
|
|
108
|
+
identified_by :domain
|
|
109
|
+
|
|
110
|
+
attribute :domain, DomainName
|
|
111
|
+
attribute :from_shape, ShapeHash
|
|
112
|
+
attribute :to_shape, ShapeHash
|
|
113
|
+
attribute :declarations, list_of(Declaration)
|
|
114
|
+
|
|
115
|
+
lifecycle :status, default: "drafted" do
|
|
116
|
+
transition "Seal" => "sealed", from: "drafted"
|
|
117
|
+
transition "Supersede" => "superseded", from: "sealed"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
value_object "DomainName" do
|
|
121
|
+
attribute :value, String
|
|
122
|
+
invariant("an edge names the domain it translates") { !value.to_s.empty? }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
value_object "ShapeHash" do
|
|
126
|
+
attribute :value, String
|
|
127
|
+
invariant("an era is named by its minted hash") { !value.to_s.empty? }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
value_object "Kind" do
|
|
131
|
+
attribute :value, String
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
value_object "SourcePath" do
|
|
135
|
+
attribute :value, String
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
value_object "DestinationPath" do
|
|
139
|
+
attribute :value, String
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
value_object "Reason" do
|
|
143
|
+
attribute :value, String
|
|
144
|
+
invariant("a superseded edge says why") { !value.to_s.empty? }
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
value_object "Declaration" do
|
|
148
|
+
attribute :kind, String
|
|
149
|
+
attribute :source, String
|
|
150
|
+
attribute :destination, String
|
|
151
|
+
|
|
152
|
+
invariant("a declaration knows its kind") { !kind.to_s.empty? }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
command "Draft" do
|
|
156
|
+
role "Author"
|
|
157
|
+
goal "Open the edge between two eras"
|
|
158
|
+
|
|
159
|
+
attribute :domain, DomainName
|
|
160
|
+
attribute :from_shape, ShapeHash
|
|
161
|
+
attribute :to_shape, ShapeHash
|
|
162
|
+
|
|
163
|
+
emits "MapDrafted"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
command "Declare" do
|
|
167
|
+
role "Author"
|
|
168
|
+
goal "Write one rule into the edge"
|
|
169
|
+
|
|
170
|
+
reference_to Map
|
|
171
|
+
attribute :kind, Kind
|
|
172
|
+
attribute :source, SourcePath
|
|
173
|
+
attribute :destination, DestinationPath
|
|
174
|
+
|
|
175
|
+
given("a sealed edge takes no further declarations") { status == "drafted" }
|
|
176
|
+
|
|
177
|
+
sets :declarations, append: { kind: :kind, source: :source, destination: :destination }
|
|
178
|
+
|
|
179
|
+
emits "RuleDeclared"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
command "Seal" do
|
|
183
|
+
role "Author"
|
|
184
|
+
goal "Declare the edge complete — data can cross it"
|
|
185
|
+
|
|
186
|
+
reference_to Map
|
|
187
|
+
|
|
188
|
+
given("an empty edge explains nothing") { declarations.size >= 1 }
|
|
189
|
+
|
|
190
|
+
emits "MapSealed"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
command "Supersede" do
|
|
194
|
+
role "Author"
|
|
195
|
+
goal "Record that a corrected edge replaced this one"
|
|
196
|
+
|
|
197
|
+
reference_to Map
|
|
198
|
+
attribute :reason, Reason
|
|
199
|
+
|
|
200
|
+
emits "MapSuperseded"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
# The whole framework, deliberately: booting a grammar chapter exercises
|
|
4
|
+
# the DSL, the meta-validator, and the runtime — and nothing the entry
|
|
5
|
+
# point loads ever requires this file back, so the require is acyclic.
|
|
6
|
+
require_relative "../hecks"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
# The sublanguage grammar domains (grammar/*.bluebook) and the one boot
|
|
10
|
+
# path for reading them as DATA — the expression chapter replayed
|
|
11
|
+
# through its own admission ledger, so anything derived from it (the
|
|
12
|
+
# operator projections, the conformance specs) reads the set that
|
|
13
|
+
# actually survived the Admit gates, never a hand-copied list.
|
|
14
|
+
#
|
|
15
|
+
# Booted on CALL, never at require: the Prism adapter normalises every
|
|
16
|
+
# predicate through CanonicalForm while a bluebook loads, so the
|
|
17
|
+
# expression machinery cannot boot the chapter that configures it —
|
|
18
|
+
# this module exists precisely so generators and specs boot it in a
|
|
19
|
+
# scratch registry instead.
|
|
20
|
+
module Grammar
|
|
21
|
+
DIR = File.expand_path("grammar", __dir__)
|
|
22
|
+
LEDGER = File.join(DIR, "expression_operators.json")
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
# Boot the expression chapter and replay the admission ledger through
|
|
27
|
+
# its real commands. A refused step raises — a generator running off
|
|
28
|
+
# a half-admitted ledger would project a table the gates never
|
|
29
|
+
# accepted.
|
|
30
|
+
def expression
|
|
31
|
+
registry = Runtime::Registry.new
|
|
32
|
+
root = File.expand_path("../..", __dir__)
|
|
33
|
+
Hecks.with_registry(registry) do
|
|
34
|
+
Kernel.load(File.join(root, "lib/hecks/ports/persistence.port"))
|
|
35
|
+
Kernel.load(File.join(root, "lib/hecks/ports/extraction.port"))
|
|
36
|
+
Kernel.load(File.join(root, "lib/hecks/adapters/driven/memory.adapter"))
|
|
37
|
+
Kernel.load(File.join(root, "lib/hecks/adapters/driven/prism.adapter"))
|
|
38
|
+
Kernel.load(File.join(DIR, "expression.bluebook"))
|
|
39
|
+
end
|
|
40
|
+
dispatcher = Runtime::Dispatcher.new(registry)
|
|
41
|
+
|
|
42
|
+
JSON.parse(File.read(LEDGER)).fetch("steps").each do |step|
|
|
43
|
+
args = symbolize(step.fetch("args"))
|
|
44
|
+
begin
|
|
45
|
+
dispatcher.dispatch(step.fetch("verb"), **args)
|
|
46
|
+
rescue *Runtime::DOMAIN_REFUSALS => refusal
|
|
47
|
+
raise Runtime::WiringError,
|
|
48
|
+
"the admission ledger refused at #{step['verb']} #{step['args']} — #{refusal.message}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
dispatcher
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def admitted_operators(dispatcher = expression)
|
|
56
|
+
records(dispatcher, "Operator").select { |op| op[:status] == "admitted" }.map do |op|
|
|
57
|
+
{ symbol: op[:symbol].value, category: op[:category].value,
|
|
58
|
+
precedence: op[:precedence].value, arity: op[:arity].value,
|
|
59
|
+
renderings: Array(op[:renderings]).map { |r| { target: r[:target], form: r[:form] } } }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def admitted_normalisations(dispatcher = expression)
|
|
64
|
+
records(dispatcher, "Normalisation")
|
|
65
|
+
.select { |rule| rule[:status] == "admitted" }
|
|
66
|
+
.sort_by { |rule| rule[:position].value }
|
|
67
|
+
.map do |rule|
|
|
68
|
+
{ strategy: rule[:strategy].value, source_token: rule[:source_token].value,
|
|
69
|
+
replacement: rule[:replacement].value, boundary: rule[:boundary].value,
|
|
70
|
+
position: rule[:position].value }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def records(dispatcher, aggregate_name)
|
|
75
|
+
registry = dispatcher.registry
|
|
76
|
+
aggregate = registry.bluebook("Expression").aggregate(aggregate_name)
|
|
77
|
+
registry.repository("Expression", aggregate).all
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# THE OPERATORS THE LANGUAGE STANDS ON. Every guard and invariant in
|
|
81
|
+
# the language's own chapters — the meta-domain (Bluebook, World) and
|
|
82
|
+
# the grammar chapters beside this file — evaluates through the very
|
|
83
|
+
# operator table the ledger admits. An operator one of those
|
|
84
|
+
# predicates uses is SELF-BEARING: retire it and the language can no
|
|
85
|
+
# longer read its own rules — found the hard way, as a projection
|
|
86
|
+
# missing `!=` that could not boot the chapter to fix itself. This
|
|
87
|
+
# derives the set, with a usage site per operator, so the generator
|
|
88
|
+
# and the conformance spec can refuse the retirement BY NAME instead
|
|
89
|
+
# of wedging.
|
|
90
|
+
def self_bearing_operators
|
|
91
|
+
sites = Hash.new { |h, k| h[k] = [] }
|
|
92
|
+
|
|
93
|
+
chapters = Bluebook::MetaValidator.grammar_registry
|
|
94
|
+
.then { |reg| %w[Bluebook World].map { |name| reg.bluebook(name) } }
|
|
95
|
+
chapters += grammar_chapters
|
|
96
|
+
|
|
97
|
+
chapters.compact.each do |chapter|
|
|
98
|
+
chapter.aggregates.each do |aggregate|
|
|
99
|
+
aggregate.commands.each do |command|
|
|
100
|
+
command.givens.each do |given|
|
|
101
|
+
operators_in(given.canonical).each do |symbol|
|
|
102
|
+
sites[symbol] << "#{chapter.name} #{aggregate.name}.#{command.hecks_name}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
aggregate.value_objects.each do |value_object|
|
|
107
|
+
value_object.invariants.each do |invariant|
|
|
108
|
+
operators_in(invariant.canonical).each do |symbol|
|
|
109
|
+
sites[symbol] << "#{chapter.name} #{aggregate.name}::#{value_object.hecks_name}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
sites.transform_values(&:uniq)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Every grammar/*.bluebook chapter, booted the same way the corpus
|
|
120
|
+
# boots them — each alone, in a scratch registry.
|
|
121
|
+
def grammar_chapters
|
|
122
|
+
Dir[File.join(DIR, "*.bluebook")].sort.map do |chapter|
|
|
123
|
+
registry = Runtime::Registry.new
|
|
124
|
+
root = File.expand_path("../..", __dir__)
|
|
125
|
+
Hecks.with_registry(registry) do
|
|
126
|
+
Kernel.load(File.join(root, "lib/hecks/ports/persistence.port"))
|
|
127
|
+
Kernel.load(File.join(root, "lib/hecks/ports/extraction.port"))
|
|
128
|
+
Kernel.load(File.join(root, "lib/hecks/adapters/driven/memory.adapter"))
|
|
129
|
+
Kernel.load(File.join(root, "lib/hecks/adapters/driven/prism.adapter"))
|
|
130
|
+
Kernel.load(chapter)
|
|
131
|
+
end
|
|
132
|
+
registry.bluebooks.values.first
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Which admitted operators one canonical text evaluates through —
|
|
137
|
+
# the evaluator's own parse, walked for its operator nodes, leaves
|
|
138
|
+
# walked for the resolver's arithmetic.
|
|
139
|
+
def operators_in(canonical)
|
|
140
|
+
evaluator = Bluebook::Expression::Evaluator
|
|
141
|
+
node = begin
|
|
142
|
+
evaluator.parse(canonical)
|
|
143
|
+
rescue StandardError
|
|
144
|
+
return []
|
|
145
|
+
end
|
|
146
|
+
walk_operators(node, evaluator).uniq
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def walk_operators(node, evaluator)
|
|
150
|
+
resolver = Bluebook::Expression::Resolver
|
|
151
|
+
case node
|
|
152
|
+
when evaluator::Or then ["||"] + walk_operators(node.left, evaluator) + walk_operators(node.right, evaluator)
|
|
153
|
+
when evaluator::And then ["&&"] + walk_operators(node.left, evaluator) + walk_operators(node.right, evaluator)
|
|
154
|
+
when evaluator::Not then ["!"] + walk_operators(node.node, evaluator)
|
|
155
|
+
when evaluator::Compare
|
|
156
|
+
[node.operator.symbol] + walk_operators(node.left, evaluator) + walk_operators(node.right, evaluator)
|
|
157
|
+
when evaluator::Include
|
|
158
|
+
[".include?"] + walk_operators(node.haystack, evaluator) + walk_operators(node.needle, evaluator)
|
|
159
|
+
when evaluator::Resolve then walk_operators(node.expr, evaluator)
|
|
160
|
+
when resolver::Addition then ["+"] + walk_operators(node.left, evaluator) + walk_operators(node.right, evaluator)
|
|
161
|
+
when resolver::Modulo then [".modulo"] + walk_operators(node.receiver,
|
|
162
|
+
evaluator) + walk_operators(node.divisor, evaluator)
|
|
163
|
+
when Struct
|
|
164
|
+
node.members.flat_map { |member| walk_operators(node[member], evaluator) }
|
|
165
|
+
else
|
|
166
|
+
[]
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def symbolize(value)
|
|
171
|
+
case value
|
|
172
|
+
when Hash then value.to_h { |k, v| [k.to_sym, symbolize(v)] }
|
|
173
|
+
when Array then value.map { |v| symbolize(v) }
|
|
174
|
+
else value
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
data/lib/hecks/ir.rb
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
# WHAT A CONSTRUCT EMITS, DECLARED RATHER THAN WRITTEN OUT.
|
|
3
|
+
#
|
|
4
|
+
# `IR` is a thing this framework PRODUCES, not a thing its model IS.
|
|
5
|
+
# The language self-hosts, and its own bluebook declares aggregates
|
|
6
|
+
# named `Bluebook`, `Aggregate`, `Command`, `Entity`, `ValueObject`,
|
|
7
|
+
# `Policy`, `ReadModel` — there is no `IR` aggregate anywhere in the
|
|
8
|
+
# grammar. Where the grammar's own vision line does say IR it means the
|
|
9
|
+
# emission: "the IR it STORES must equal the IR the DSL builder
|
|
10
|
+
# PRODUCES". `IR_VERSION` says the same thing structurally — a version
|
|
11
|
+
# stamped on `to_h`'s output rather than on the object is a version of
|
|
12
|
+
# the EMISSION, which only makes sense if the two are different things.
|
|
13
|
+
#
|
|
14
|
+
# So emitting IR is a CAPABILITY a construct has, and this is that
|
|
15
|
+
# capability: `include Hecks::IR` and declare the shape once.
|
|
16
|
+
# The model it emits FROM is `Hecks::Bluebook` — a chapter class
|
|
17
|
+
# nesting everything a chapter declares. It is deliberately not named
|
|
18
|
+
# after this, its own output.
|
|
19
|
+
#
|
|
20
|
+
# Before this, eighteen constructs each hand-wrote a `to_h` that said
|
|
21
|
+
# the same four things in the same order — read a field, recurse into a
|
|
22
|
+
# child, recurse into a list, or compute something — and the shape of a
|
|
23
|
+
# construct was knowable only by reading a method body. Declared, it is
|
|
24
|
+
# data: `ir_spec` can be walked by anything that wants to know what a
|
|
25
|
+
# construct carries, which is the whole point of hanging emission off
|
|
26
|
+
# the model rather than burying it.
|
|
27
|
+
#
|
|
28
|
+
# include Hecks::IR # an instance-shaped construct
|
|
29
|
+
#
|
|
30
|
+
# emits_ir(
|
|
31
|
+
# name: :name, # send it
|
|
32
|
+
# identified_by: :identity_paths, # ...under a different key
|
|
33
|
+
# list: :list?, # ...predicates are fine
|
|
34
|
+
# attributes: many(:attributes), # map(&:to_h)
|
|
35
|
+
# lifecycle: one(:lifecycle), # &.to_h, nil-safe
|
|
36
|
+
# canonical_form: -> { CanonicalForm.table } # anything else
|
|
37
|
+
# )
|
|
38
|
+
#
|
|
39
|
+
# KEY ORDER IS THE DECLARATION ORDER, and that is load-bearing rather
|
|
40
|
+
# than cosmetic: `spec/golden/ir/*.json` pins the emitted form exactly,
|
|
41
|
+
# so a reordered declaration is a changed artifact and the golden specs
|
|
42
|
+
# will say so.
|
|
43
|
+
module IR
|
|
44
|
+
# THE TWO SHAPES A CONSTRUCT COMES IN, and why this module has two
|
|
45
|
+
# doors instead of hiding the difference.
|
|
46
|
+
#
|
|
47
|
+
# `Bluebook`/`Aggregate`/`Policy`/`ReadModel` are ordinary objects —
|
|
48
|
+
# metadata records, one instance per declaration. `Command`/`Entity`/
|
|
49
|
+
# `ValueObject` are anonymous CLASSES (`Class.new(self)`, see
|
|
50
|
+
# `Command.declare`), because those three are referenced as TYPES in
|
|
51
|
+
# a bluebook (`attribute :price, Money`) and a type has to be a real
|
|
52
|
+
# Ruby constant to be named.
|
|
53
|
+
#
|
|
54
|
+
# That split is real and not worth papering over, so:
|
|
55
|
+
#
|
|
56
|
+
# include Hecks::IR # instance-shaped — to_h is an instance method
|
|
57
|
+
# extend Hecks::IR # class-shaped — to_h is a class method
|
|
58
|
+
#
|
|
59
|
+
# Both get the same `emits_ir` and the same emission rules.
|
|
60
|
+
def self.included(base)
|
|
61
|
+
base.extend(Declares)
|
|
62
|
+
base.include(Emits)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.extended(base)
|
|
66
|
+
base.extend(Declares)
|
|
67
|
+
base.extend(Emits)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# A field that holds a list of constructs — each one emits itself.
|
|
71
|
+
Many = Struct.new(:source)
|
|
72
|
+
# A field that holds one construct, or nothing. `&.to_h`, never a
|
|
73
|
+
# crash on an undeclared lifecycle.
|
|
74
|
+
One = Struct.new(:source)
|
|
75
|
+
|
|
76
|
+
module Declares
|
|
77
|
+
def emits_ir(**spec)
|
|
78
|
+
@ir_spec = spec
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def many(source) = Many.new(source)
|
|
82
|
+
def one(source) = One.new(source)
|
|
83
|
+
|
|
84
|
+
# Walks the superclass chain so a `Class.new(ValueObject)` — which
|
|
85
|
+
# is what every declared value object actually IS — inherits the
|
|
86
|
+
# shape its base declared, rather than each anonymous subclass
|
|
87
|
+
# having to redeclare it.
|
|
88
|
+
def ir_spec
|
|
89
|
+
return @ir_spec if defined?(@ir_spec) && @ir_spec
|
|
90
|
+
|
|
91
|
+
superclass.ir_spec if respond_to?(:superclass) && superclass.respond_to?(:ir_spec)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
module Emits
|
|
96
|
+
def to_h
|
|
97
|
+
spec = ir_spec_for(self)
|
|
98
|
+
raise Undeclared, "#{self} emits IR but never declared its shape with emits_ir" unless spec
|
|
99
|
+
|
|
100
|
+
spec.to_h { |key, rule| [key, emit(rule)] }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
# An instance reads its class's declaration; a class-shaped
|
|
106
|
+
# construct IS the declaration holder.
|
|
107
|
+
def ir_spec_for(construct)
|
|
108
|
+
return construct.ir_spec if construct.respond_to?(:ir_spec)
|
|
109
|
+
|
|
110
|
+
construct.class.ir_spec
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def emit(rule)
|
|
114
|
+
case rule
|
|
115
|
+
when Many then public_send(rule.source).map(&:to_h)
|
|
116
|
+
when One then public_send(rule.source)&.to_h
|
|
117
|
+
when Symbol then public_send(rule)
|
|
118
|
+
when Proc then instance_exec(&rule)
|
|
119
|
+
else raise Undeclared, "#{rule.inspect} is not a way to emit a field"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class Undeclared < StandardError; end
|
|
125
|
+
end
|
|
126
|
+
end
|