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,267 @@
|
|
|
1
|
+
Hecks.bluebook "Translation" do
|
|
2
|
+
aggregate "TranslationAggregate" do
|
|
3
|
+
description "One aggregate's own move from one pinned era to the next — a table of rules, or a deliberate acknowledgment that a rule is still unresolved."
|
|
4
|
+
|
|
5
|
+
belongs_to Translation, as: :translation_ref
|
|
6
|
+
|
|
7
|
+
identified_by TranslationAggregateName, as: :name
|
|
8
|
+
|
|
9
|
+
# `TranslationAggregateName` — a DEDICATED type for the identity
|
|
10
|
+
# field, not the shared `TranslationName` every non-identity field
|
|
11
|
+
# below uses. Found live, not by inspection: reusing one value-
|
|
12
|
+
# object type for BOTH an aggregate's own identity field and a
|
|
13
|
+
# sibling non-identity field on the same aggregate broke the
|
|
14
|
+
# single-field-VO identity-unwrap path — the stored `id` came back
|
|
15
|
+
# as a stringified Hash (`"{:value=>\"Account\"}"`) instead of the
|
|
16
|
+
# bare scalar (`"Account"`), so a self-reference to this aggregate
|
|
17
|
+
# could never find the record `Declare` had just created. Reusing
|
|
18
|
+
# the SAME type across MULTIPLE identity fields (Translation's own
|
|
19
|
+
# `TranslationEraName`, for both `from` and `to`) is unaffected —
|
|
20
|
+
# confirmed directly, not assumed — so the real trigger is identity
|
|
21
|
+
# + non-identity sharing, not reuse itself. A genuine framework bug,
|
|
22
|
+
# out of scope to fix here; every other self-hosted construct in
|
|
23
|
+
# this language already avoids it by convention (a dedicated type
|
|
24
|
+
# per identity field), which this now matches too.
|
|
25
|
+
attribute :was, TranslationName, optional: true
|
|
26
|
+
|
|
27
|
+
value_object "TranslationAggregateName" do
|
|
28
|
+
attribute :value, String
|
|
29
|
+
invariant("a translation aggregate names itself") { !value.to_s.empty? }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The parent arrives as an ordinary value fact at declaration time. Its
|
|
33
|
+
# fields mirror Translation's compound identity, while `translation_ref`
|
|
34
|
+
# above retains the resulting canonical identity as a structural edge.
|
|
35
|
+
value_object "TranslationIdentity" do
|
|
36
|
+
attribute :domain, TranslationDomainName
|
|
37
|
+
attribute :from, TranslationEraName
|
|
38
|
+
attribute :to, TranslationEraName
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
attribute :renames, list_of(TranslationRename)
|
|
42
|
+
attribute :moves, list_of(TranslationMove)
|
|
43
|
+
attribute :converts, list_of(TranslationConvert)
|
|
44
|
+
attribute :drops, list_of(TranslationName)
|
|
45
|
+
attribute :retypes, list_of(TranslationRetype)
|
|
46
|
+
attribute :computes, list_of(TranslationCompute)
|
|
47
|
+
attribute :rekeys, list_of(TranslationRekey)
|
|
48
|
+
attribute :backfills, list_of(TranslationBackfill)
|
|
49
|
+
|
|
50
|
+
# Field names throughout mirror lib/hecks/bluebook/translation.rb
|
|
51
|
+
# EXACTLY (`Struct.new(:from, :to)` etc.) — the real Ruby records
|
|
52
|
+
# TranslationJudge dispatches from, not the builder's own local
|
|
53
|
+
# parameter names (`move(old_path, to:)`'s `old_path` becomes the
|
|
54
|
+
# struct's own `from`).
|
|
55
|
+
value_object "TranslationRename" do
|
|
56
|
+
attribute :from, TranslationName
|
|
57
|
+
attribute :to, TranslationName
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
value_object "TranslationMove" do
|
|
61
|
+
attribute :from, TranslationName
|
|
62
|
+
attribute :to, TranslationName
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
value_object "TranslationConvert" do
|
|
66
|
+
attribute :from, TranslationName
|
|
67
|
+
attribute :to, TranslationName
|
|
68
|
+
attribute :values, TranslationLiteralText
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
value_object "TranslationRetype" do
|
|
72
|
+
attribute :from, TranslationName
|
|
73
|
+
attribute :to, TranslationName
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
value_object "TranslationCompute" do
|
|
77
|
+
attribute :from, TranslationName
|
|
78
|
+
attribute :to, TranslationName
|
|
79
|
+
attribute :sql, TranslationLiteralText
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
value_object "TranslationRekey" do
|
|
83
|
+
attribute :sql, TranslationLiteralText
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
value_object "TranslationBackfill" do
|
|
87
|
+
attribute :name, TranslationName
|
|
88
|
+
attribute :default, TranslationLiteralText
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
command "Declare" do
|
|
92
|
+
role "Deployment"
|
|
93
|
+
goal "Open one aggregate's own move from one pinned era to the next"
|
|
94
|
+
|
|
95
|
+
attribute :translation_ref, TranslationIdentity
|
|
96
|
+
attribute :name, TranslationAggregateName
|
|
97
|
+
attribute :was, TranslationName, optional: true
|
|
98
|
+
|
|
99
|
+
sets :translation_ref
|
|
100
|
+
sets :name
|
|
101
|
+
sets :was
|
|
102
|
+
|
|
103
|
+
emits "TranslationAggregateDeclared"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
command "AddRename" do
|
|
107
|
+
role "Deployment"
|
|
108
|
+
goal "Move data at an old field name to its new one, unchanged"
|
|
109
|
+
|
|
110
|
+
attribute :from, TranslationName
|
|
111
|
+
attribute :to, TranslationName
|
|
112
|
+
|
|
113
|
+
sets :renames, append: { from: :from, to: :to }
|
|
114
|
+
|
|
115
|
+
emits "TranslationRenameAdded"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
command "AddMove" do
|
|
119
|
+
role "Deployment"
|
|
120
|
+
goal "Move data at an old path to a new one, unchanged"
|
|
121
|
+
|
|
122
|
+
attribute :from, TranslationName
|
|
123
|
+
attribute :to, TranslationName
|
|
124
|
+
|
|
125
|
+
sets :moves, append: { from: :from, to: :to }
|
|
126
|
+
|
|
127
|
+
emits "TranslationMoveAdded"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
command "AddConvert" do
|
|
131
|
+
role "Deployment"
|
|
132
|
+
goal "Move data at an old path to a new one, translating its own values through an exhaustive table"
|
|
133
|
+
|
|
134
|
+
attribute :from, TranslationName
|
|
135
|
+
attribute :to, TranslationName
|
|
136
|
+
attribute :values, TranslationLiteralText
|
|
137
|
+
|
|
138
|
+
sets :converts, append: { from: :from, to: :to, values: :values }
|
|
139
|
+
|
|
140
|
+
emits "TranslationConvertAdded"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
command "AddDrop" do
|
|
144
|
+
role "Deployment"
|
|
145
|
+
goal "Acknowledge, deliberately, that a field's own data does not survive"
|
|
146
|
+
|
|
147
|
+
attribute :value, TranslationName
|
|
148
|
+
|
|
149
|
+
sets :drops, append: { value: :value }
|
|
150
|
+
|
|
151
|
+
emits "TranslationDropAdded"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
command "AddRetype" do
|
|
155
|
+
role "Deployment"
|
|
156
|
+
goal "Declare that an old type name and a new one mean the same shape"
|
|
157
|
+
|
|
158
|
+
attribute :from, TranslationName
|
|
159
|
+
attribute :to, TranslationName
|
|
160
|
+
|
|
161
|
+
sets :retypes, append: { from: :from, to: :to }
|
|
162
|
+
|
|
163
|
+
emits "TranslationRetypeAdded"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
command "AddCompute" do
|
|
167
|
+
role "Deployment"
|
|
168
|
+
goal "Move data at an old path to a new one, transformed by a real SQL expression"
|
|
169
|
+
|
|
170
|
+
attribute :from, TranslationName
|
|
171
|
+
attribute :to, TranslationName
|
|
172
|
+
attribute :sql, TranslationLiteralText
|
|
173
|
+
|
|
174
|
+
sets :computes, append: { from: :from, to: :to, sql: :sql }
|
|
175
|
+
|
|
176
|
+
emits "TranslationComputeAdded"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
command "AddRekey" do
|
|
180
|
+
role "Deployment"
|
|
181
|
+
goal "Recompute this aggregate's own identity by a real SQL expression"
|
|
182
|
+
|
|
183
|
+
attribute :sql, TranslationLiteralText
|
|
184
|
+
|
|
185
|
+
sets :rekeys, append: { sql: :sql }
|
|
186
|
+
|
|
187
|
+
emits "TranslationRekeyAdded"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
command "AddBackfill" do
|
|
191
|
+
role "Deployment"
|
|
192
|
+
goal "Name a newly required attribute and the value an existing record reads until written for real"
|
|
193
|
+
|
|
194
|
+
attribute :name, TranslationName
|
|
195
|
+
attribute :default, TranslationLiteralText
|
|
196
|
+
|
|
197
|
+
sets :backfills, append: { name: :name, default: :default }
|
|
198
|
+
|
|
199
|
+
emits "TranslationBackfillAdded"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# HOW TRANSLATIONAGGREGATE IS SPELLED. These rows live with the concept
|
|
203
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
204
|
+
# Contexts represented here: TranslationAggregate.
|
|
205
|
+
value_object "KeywordSeed" do
|
|
206
|
+
attribute :word, String
|
|
207
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
208
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
209
|
+
attribute :inner, String
|
|
210
|
+
attribute :opens, String
|
|
211
|
+
attribute :fills, String
|
|
212
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
213
|
+
attribute :was, String
|
|
214
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
215
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
216
|
+
|
|
217
|
+
member word: "rename", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "renames", calls: "rename_impl"
|
|
218
|
+
member word: "move", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "moves", calls: "move_impl"
|
|
219
|
+
member word: "convert", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "converts", calls: "convert_impl"
|
|
220
|
+
member word: "drop", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "drops"
|
|
221
|
+
member word: "retype", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "retypes", calls: "retype_impl"
|
|
222
|
+
member word: "compute", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "computes", calls: "compute_impl"
|
|
223
|
+
member word: "rekey", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "rekeys", calls: "rekey_impl"
|
|
224
|
+
member word: "backfill", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "backfills", calls: "backfill_impl"
|
|
225
|
+
member word: "unresolved", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "", calls: "unresolved_impl"
|
|
226
|
+
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
value_object "ArgumentSeed" do
|
|
230
|
+
attribute :keyword, String
|
|
231
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
232
|
+
attribute :at, String
|
|
233
|
+
attribute :named, String
|
|
234
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
235
|
+
attribute :required, String
|
|
236
|
+
attribute :fills, String
|
|
237
|
+
attribute :selects, String
|
|
238
|
+
attribute :pair_key_fills, String
|
|
239
|
+
attribute :pair_value_fills, String
|
|
240
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
241
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
242
|
+
attribute :variadic, String
|
|
243
|
+
attribute :coerce, String
|
|
244
|
+
attribute :blank_message, String
|
|
245
|
+
|
|
246
|
+
member keyword: "rename", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "old_name"
|
|
247
|
+
member keyword: "rename", context: "TranslationAggregate", at: "", named: "to", kind: "symbol", required: "true", fills: "to"
|
|
248
|
+
member keyword: "move", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
|
|
249
|
+
member keyword: "move", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
|
|
250
|
+
member keyword: "convert", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
|
|
251
|
+
member keyword: "convert", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
|
|
252
|
+
member keyword: "convert", context: "TranslationAggregate", at: "", named: "values", kind: "literal", required: "true", fills: "values"
|
|
253
|
+
member keyword: "drop", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "name", blank_message: "a drop needs a name"
|
|
254
|
+
member keyword: "retype", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_type"
|
|
255
|
+
member keyword: "retype", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
|
|
256
|
+
member keyword: "compute", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
|
|
257
|
+
member keyword: "compute", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
|
|
258
|
+
member keyword: "compute", context: "TranslationAggregate", at: "", named: "sql", kind: "text", required: "true", fills: "sql"
|
|
259
|
+
member keyword: "rekey", context: "TranslationAggregate", at: "", named: "sql", kind: "text", required: "true", fills: "sql"
|
|
260
|
+
member keyword: "backfill", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "name"
|
|
261
|
+
member keyword: "backfill", context: "TranslationAggregate", at: "", named: "default", kind: "literal", required: "true", fills: "default"
|
|
262
|
+
member keyword: "unresolved", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "name"
|
|
263
|
+
member keyword: "unresolved", context: "TranslationAggregate", at: "", named: "candidates", kind: "list", required: "false", fills: "candidates"
|
|
264
|
+
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Hecks.bluebook "World" do
|
|
2
|
+
aggregate "Wiring" do
|
|
3
|
+
description "One adapter binding inside a world — the verb it answers, the adapter it names, and the values that adapter needs. Its own root because a world's settings are an open map, which no value object can hold."
|
|
4
|
+
|
|
5
|
+
# `as:` is required here — Wiring ALSO holds an ordinary `world` text
|
|
6
|
+
# attribute below (the same string, but a value rather than a reference),
|
|
7
|
+
# so the bare reference name would collide with it.
|
|
8
|
+
belongs_to World, as: :world_ref
|
|
9
|
+
|
|
10
|
+
# THE WORLD IT IS IN, AND THE VERB IT ANSWERS. One world binds one adapter per
|
|
11
|
+
# verb — that is what a binding IS — so the verb names the wiring, and the
|
|
12
|
+
# world says whose.
|
|
13
|
+
identified_by :world, :verb
|
|
14
|
+
|
|
15
|
+
attribute :world, WiringText
|
|
16
|
+
attribute :verb, WiringText
|
|
17
|
+
attribute :adapter, WiringText
|
|
18
|
+
attribute :settings, list_of(Setting)
|
|
19
|
+
|
|
20
|
+
value_object "WiringText" do
|
|
21
|
+
attribute :value, String
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
value_object "Setting" do
|
|
25
|
+
attribute :key, String
|
|
26
|
+
attribute :value, String
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
command "Declare" do
|
|
30
|
+
role "Deployment"
|
|
31
|
+
goal "Bind one adapter in a world"
|
|
32
|
+
|
|
33
|
+
attribute :world_ref, WorldName
|
|
34
|
+
attribute :world, WiringText
|
|
35
|
+
attribute :verb, WiringText
|
|
36
|
+
attribute :adapter, WiringText
|
|
37
|
+
|
|
38
|
+
given("a wiring names its verb") { !verb.value.to_s.empty? }
|
|
39
|
+
|
|
40
|
+
sets :world_ref
|
|
41
|
+
sets :world
|
|
42
|
+
sets :verb
|
|
43
|
+
sets :adapter
|
|
44
|
+
|
|
45
|
+
emits "WiringDeclared"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
command "Set" do
|
|
49
|
+
role "Deployment"
|
|
50
|
+
goal "Give one value the bound adapter needs"
|
|
51
|
+
|
|
52
|
+
attribute :key, WiringText
|
|
53
|
+
attribute :value, WiringText
|
|
54
|
+
|
|
55
|
+
given("a setting names its key") { !key.value.to_s.empty? }
|
|
56
|
+
|
|
57
|
+
sets :settings, append: { key: :key, value: :value }
|
|
58
|
+
|
|
59
|
+
emits "SettingGiven"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Hecks.bluebook "World" do
|
|
2
|
+
aggregate "World" do
|
|
3
|
+
description "One .world — the per-deployment values a domain's adapters need. A sibling artifact to the bluebook, not part of it : the same domain runs in many worlds."
|
|
4
|
+
|
|
5
|
+
identified_by WorldName, as: :domain
|
|
6
|
+
|
|
7
|
+
attribute :realm, Realm
|
|
8
|
+
attribute :latest, Latest
|
|
9
|
+
|
|
10
|
+
value_object "WorldName" do
|
|
11
|
+
attribute :value, String
|
|
12
|
+
invariant("a world names its domain") { !value.to_s.empty? }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
value_object "Realm" do
|
|
16
|
+
attribute :value, String
|
|
17
|
+
invariant("a realm says something") { !value.to_s.empty? }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
value_object "Latest" do
|
|
21
|
+
attribute :value, String
|
|
22
|
+
invariant("a latest version says something") { !value.to_s.empty? }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
command "Declare" do
|
|
26
|
+
role "Deployment"
|
|
27
|
+
goal "Open a world for a domain"
|
|
28
|
+
|
|
29
|
+
attribute :domain, WorldName
|
|
30
|
+
attribute :realm, Realm, optional: true
|
|
31
|
+
attribute :latest, Latest, optional: true
|
|
32
|
+
|
|
33
|
+
sets :domain
|
|
34
|
+
sets :realm
|
|
35
|
+
sets :latest
|
|
36
|
+
|
|
37
|
+
emits "WorldDeclared"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# HOW WORLD IS SPELLED. These rows live with the concept
|
|
41
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
42
|
+
# Contexts represented here: File, World.
|
|
43
|
+
value_object "KeywordSeed" do
|
|
44
|
+
attribute :word, String
|
|
45
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
46
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
47
|
+
attribute :inner, String
|
|
48
|
+
attribute :opens, String
|
|
49
|
+
attribute :fills, String
|
|
50
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
51
|
+
attribute :was, String
|
|
52
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
53
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
54
|
+
|
|
55
|
+
member word: "world", context: "File", body: "keywords", inner: "World", opens: "World", fills: ""
|
|
56
|
+
member word: "realm", context: "World", body: "none", inner: "", opens: "", fills: "realm", calls: "realm_impl"
|
|
57
|
+
member word: "latest", context: "World", body: "none", inner: "", opens: "", fills: "latest", calls: "latest_impl"
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
value_object "ArgumentSeed" do
|
|
62
|
+
attribute :keyword, String
|
|
63
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
64
|
+
attribute :at, String
|
|
65
|
+
attribute :named, String
|
|
66
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
67
|
+
attribute :required, String
|
|
68
|
+
attribute :fills, String
|
|
69
|
+
attribute :selects, String
|
|
70
|
+
attribute :pair_key_fills, String
|
|
71
|
+
attribute :pair_value_fills, String
|
|
72
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
73
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
74
|
+
attribute :variadic, String
|
|
75
|
+
attribute :coerce, String
|
|
76
|
+
attribute :blank_message, String
|
|
77
|
+
|
|
78
|
+
member keyword: "world", context: "File", at: "1", named: "", kind: "text", required: "true", fills: "domain"
|
|
79
|
+
member keyword: "realm", context: "World", at: "1", named: "", kind: "text", required: "true", fills: "realm"
|
|
80
|
+
member keyword: "latest", context: "World", at: "1", named: "", kind: "text", required: "true", fills: "latest"
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
# THE ONE SPELLING FOR A CAPTURED RUBY LITERAL ON THE WIRE.
|
|
3
|
+
#
|
|
4
|
+
# Several `to_h` fields hold a value the author wrote in a bluebook —
|
|
5
|
+
# `where(status: { eq: "open" })`, `then_set append: { direction: { value:
|
|
6
|
+
# "credit" } }`, `dispatch ... with: { number: :source }`, an attribute's
|
|
7
|
+
# `default:` — as TEXT, because the export has to stand on its own and a
|
|
8
|
+
# String field cannot say "this one was a Symbol". Every such field is the
|
|
9
|
+
# same question and now gets the same answer.
|
|
10
|
+
#
|
|
11
|
+
# It was three answers before, and they disagreed on both axes that matter.
|
|
12
|
+
# `Mutation#appended_fields` spelled a Symbol BARE and everything else
|
|
13
|
+
# `inspect`; `QuerySpecification.render_value` spelled a Symbol with a COLON
|
|
14
|
+
# and everything else `to_s`. So `:amount` crossed as "amount" in a mutation
|
|
15
|
+
# and ":amount" in a saga binding — the same value, two spellings, and each
|
|
16
|
+
# reader had to know which field it was looking at. Worse, `to_s`/`inspect`
|
|
17
|
+
# on a Hash is Ruby's OWN rendering, which moved under us: 3.3 writes
|
|
18
|
+
# `{:value=>"credit"}` and 3.4 writes `{value: "credit"}` for the identical
|
|
19
|
+
# Hash, so the wire format was silently pinned to an interpreter version.
|
|
20
|
+
#
|
|
21
|
+
# SELF-DESCRIBING IS THE RULE, stated once here rather than inherited from
|
|
22
|
+
# whatever `inspect` happens to do: a symbol wears its colon, a string wears
|
|
23
|
+
# its quotes, a hash wears `{key: value}` braces, a list wears its brackets,
|
|
24
|
+
# and a number, a boolean and nil are bare. `read` is the exact inverse, and
|
|
25
|
+
# is the only thing that should ever take one of these strings apart.
|
|
26
|
+
# A MUTATION SOURCE THAT READS THE RECORD'S OWN STATE — `sets :positions,
|
|
27
|
+
# append: { knights: state(:knights) }`. A bare Symbol in a mutation
|
|
28
|
+
# source always names a command ARGUMENT (and imports it as one when
|
|
29
|
+
# the target's own field carries the same name — `CommandBuilder
|
|
30
|
+
# #resolve_append_fields!`); before this there was no way to say "the
|
|
31
|
+
# value this field already holds", so a command could not snapshot its
|
|
32
|
+
# own record — chess's threefold repetition needs exactly that, a
|
|
33
|
+
# position copied off the board every ply. Spelled `state(:name)` on
|
|
34
|
+
# the wire, read back by `Literal.read`; classified `kind: "state"` in
|
|
35
|
+
# a set's own source (`Behaviour::Mutation#classified_source`).
|
|
36
|
+
StateRef = Struct.new(:name) do
|
|
37
|
+
def to_s = "state(:#{name})"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
module Literal
|
|
41
|
+
module_function
|
|
42
|
+
|
|
43
|
+
def render(value)
|
|
44
|
+
case value
|
|
45
|
+
when nil then "nil"
|
|
46
|
+
when StateRef then value.to_s
|
|
47
|
+
when true, false then value.to_s
|
|
48
|
+
when Symbol then ":#{value}"
|
|
49
|
+
when Integer, Float then value.to_s
|
|
50
|
+
when String then quote(value)
|
|
51
|
+
when Hash then "{#{value.map { |key, held| "#{key}: #{render(held)}" }.join(', ')}}"
|
|
52
|
+
when Array then "[#{value.map { |held| render(held) }.join(', ')}]"
|
|
53
|
+
else
|
|
54
|
+
raise ArgumentError, "#{value.class} has no pinned literal spelling — teach Literal.render one " \
|
|
55
|
+
"rather than letting #to_s decide it"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Read one back. Tolerant of a bare word on purpose: the language stores a
|
|
60
|
+
# closed set's members and a few hand-written fields as plain text that was
|
|
61
|
+
# never rendered, and those must stay the strings they are.
|
|
62
|
+
def read(text)
|
|
63
|
+
raw = text.to_s.strip
|
|
64
|
+
return nil if raw.empty? || raw == "nil"
|
|
65
|
+
return true if raw == "true"
|
|
66
|
+
return false if raw == "false"
|
|
67
|
+
return raw.to_i if raw.match?(/\A-?\d+\z/)
|
|
68
|
+
return raw.to_f if raw.match?(/\A-?\d+\.\d+\z/)
|
|
69
|
+
return raw[1..].to_sym if raw.start_with?(":")
|
|
70
|
+
return StateRef.new(raw[7..-2].to_sym) if raw.match?(/\Astate\(:[A-Za-z_][A-Za-z0-9_]*\)\z/)
|
|
71
|
+
return unquote(raw) if quoted?(raw)
|
|
72
|
+
return read_hash(raw) if raw.start_with?("{") && raw.end_with?("}")
|
|
73
|
+
return read_array(raw) if raw.start_with?("[") && raw.end_with?("]")
|
|
74
|
+
|
|
75
|
+
raw
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
ESCAPED = { '"' => '\\"', "\\" => "\\\\" }.freeze
|
|
79
|
+
|
|
80
|
+
def quote(text) = "\"#{text.gsub(/["\\]/) { |char| ESCAPED[char] }}\""
|
|
81
|
+
|
|
82
|
+
def quoted?(raw) = raw.length >= 2 && raw.start_with?('"') && raw.end_with?('"')
|
|
83
|
+
|
|
84
|
+
def unquote(raw) = raw[1..-2].gsub(/\\(.)/) { ::Regexp.last_match(1) }
|
|
85
|
+
|
|
86
|
+
def read_hash(raw)
|
|
87
|
+
split_items(raw[1..-2]).to_h do |item|
|
|
88
|
+
key, _, held = item.partition(":")
|
|
89
|
+
[key.strip.to_sym, read(held)]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def read_array(raw) = split_items(raw[1..-2]).map { |item| read(item) }
|
|
94
|
+
|
|
95
|
+
# Split on the commas that are actually SEPARATORS — never one inside a
|
|
96
|
+
# quoted string or a nested brace/bracket. Scanned rather than
|
|
97
|
+
# `String#split(", ")`, which tore `"a, b"` in half and lost the second
|
|
98
|
+
# field of anything nested.
|
|
99
|
+
def split_items(body)
|
|
100
|
+
items = []
|
|
101
|
+
current = +""
|
|
102
|
+
depth = 0
|
|
103
|
+
quoting = false
|
|
104
|
+
escaping = false
|
|
105
|
+
|
|
106
|
+
body.each_char do |char|
|
|
107
|
+
current << char
|
|
108
|
+
next (escaping = false) if escaping
|
|
109
|
+
next (escaping = true) if quoting && char == "\\"
|
|
110
|
+
next (quoting = !quoting) if char == '"'
|
|
111
|
+
next if quoting
|
|
112
|
+
|
|
113
|
+
depth += 1 if "{[".include?(char)
|
|
114
|
+
depth -= 1 if "}]".include?(char)
|
|
115
|
+
next unless char == "," && depth.zero?
|
|
116
|
+
|
|
117
|
+
current.chop!
|
|
118
|
+
items << current
|
|
119
|
+
current = +""
|
|
120
|
+
end
|
|
121
|
+
items << current
|
|
122
|
+
items.map(&:strip).reject(&:empty?)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
data/lib/hecks/naming.rb
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Naming
|
|
3
|
+
# WHAT SEPARATES THE PARTS OF A DERIVED IDENTITY.
|
|
4
|
+
#
|
|
5
|
+
# An identity of several parts is their JOIN, and the join has to be spelled the
|
|
6
|
+
# same everywhere or two readers name two different records off one declaration.
|
|
7
|
+
# It was spelled three ways at once here — "::" for an aggregate under a
|
|
8
|
+
# chapter, "." for everything under an aggregate, "#" for the three that keyed
|
|
9
|
+
# off position — and each was written where it happened to be needed. Once the
|
|
10
|
+
# runtime derived the same identity, the runtime made a FOURTH, and a reference
|
|
11
|
+
# that resolved by string comparison found nothing.
|
|
12
|
+
IDENTITY_JOIN = ":".freeze
|
|
13
|
+
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
# The parts of an identity, joined in declaration order.
|
|
17
|
+
def identity(parts) = Array(parts).join(IDENTITY_JOIN)
|
|
18
|
+
|
|
19
|
+
def demodulise(type)
|
|
20
|
+
type.to_s.split("::").last.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# snake_case -> PascalCase. The name a synthesised closed-set value object
|
|
24
|
+
# takes when an attribute declares one inline. The derivation is part of
|
|
25
|
+
# the IR contract: the same bluebook must always produce the same name.
|
|
26
|
+
def pascal(text)
|
|
27
|
+
text.to_s.split("_").map { |part| part.sub(/\A(.)/) { Regexp.last_match(1).upcase } }.join
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def snake(text)
|
|
31
|
+
text.to_s
|
|
32
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
33
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
34
|
+
.downcase
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# The name a COLLECTION of something takes.
|
|
38
|
+
#
|
|
39
|
+
# There were two of these and one was wrong. A read model's gathered heads
|
|
40
|
+
# derived their name with a bare `"#{snake(target)}s"`, so the meta-domain's
|
|
41
|
+
# own whole-bluebook read model handed back `querys`, `entitys`, `policys`
|
|
42
|
+
# and `dispatchs` — and every check was green, because the checks compared
|
|
43
|
+
# the wrong rule against itself. Agreement is not correctness; it never was.
|
|
44
|
+
#
|
|
45
|
+
# So: one pluraliser, three rules, and every collection name flows through it.
|
|
46
|
+
def plural(text)
|
|
47
|
+
word = text.to_s
|
|
48
|
+
return "#{word[0..-2]}ies" if word.match?(/[^aeiou]y\z/)
|
|
49
|
+
return "#{word}es" if word.match?(/(s|x|z|ch|sh)\z/)
|
|
50
|
+
|
|
51
|
+
"#{word}s"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# `has_many`'s undo — the plural WRITTEN, back to the singular the target
|
|
55
|
+
# aggregate is actually named. Deliberately the crude half of a pair: `plural`
|
|
56
|
+
# above earns its precision (three suffix rules) because getting a COLLECTION
|
|
57
|
+
# name wrong reads as a typo forever ; this only ever recovers a name someone
|
|
58
|
+
# already wrote as a real aggregate, so "ies -> y, trailing s dropped" is the
|
|
59
|
+
# whole rule — enough for `has_many Invoices` to resolve to the aggregate
|
|
60
|
+
# actually named Invoice.
|
|
61
|
+
def singularize(text)
|
|
62
|
+
word = text.to_s
|
|
63
|
+
return "#{word[0..-4]}y" if word.length > 3 && word.end_with?("ies")
|
|
64
|
+
return word[0..-2] if word.length > 1 && word.end_with?("s")
|
|
65
|
+
|
|
66
|
+
word
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def reference_key(type)
|
|
70
|
+
snake(demodulise(type)).to_sym
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def split_dotted(dotted)
|
|
74
|
+
first, second = dotted.to_s.split(".", 2)
|
|
75
|
+
[first.to_s, second.to_s]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def qualifier(dotted)
|
|
79
|
+
text = dotted.to_s
|
|
80
|
+
text.include?(".") ? text.split(".", 2).first : nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def unqualified(dotted)
|
|
84
|
+
text = dotted.to_s
|
|
85
|
+
text.include?(".") ? text.split(".", 2).last : text
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def split_verb(verb)
|
|
89
|
+
path, command = verb.to_s.split(".", 2)
|
|
90
|
+
domain, aggregate = path.to_s.split("::", 2)
|
|
91
|
+
return nil unless domain && aggregate && command
|
|
92
|
+
|
|
93
|
+
[domain, aggregate, command]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# `trigger Account::Debit` / `dispatch Account::Debit` — a bare
|
|
97
|
+
# CONSTANT reference (`ConstShim`'s own `ScopedConstant`, S0b), not
|
|
98
|
+
# text (ADR 0025, "events and reactions" — command references become
|
|
99
|
+
# first-class). Ruby's `::` joins EVERY segment the same way a
|
|
100
|
+
# constant path always does, but a command's own `hecks_fqn` joins
|
|
101
|
+
# its aggregate with `.` (`Construct#hecks_separator`'s default,
|
|
102
|
+
# only an AGGREGATE overrides it to `::`) — so only the LAST `::`
|
|
103
|
+
# becomes a `.`; everything before it (the chapter, when a domain is
|
|
104
|
+
# spelled at all: `Banking::Account::Debit`) stays `::`-joined.
|
|
105
|
+
#
|
|
106
|
+
# A STRING PASSES THROUGH UNCHANGED, on purpose — legacy era text
|
|
107
|
+
# (S0a's own shadow-parsed spelling) already mixes `::` (domain) and
|
|
108
|
+
# `.` (command) correctly on its own, e.g. `"Banking::Account.Debit"`,
|
|
109
|
+
# and re-splitting that by content rather than by TYPE would corrupt
|
|
110
|
+
# it (its own last `::` sits between the domain and the aggregate,
|
|
111
|
+
# not the aggregate and the command). Only an actual constant object
|
|
112
|
+
# — never seen holding a `.` of its own — needs the rewrite at all.
|
|
113
|
+
def command_ref(value)
|
|
114
|
+
return value.to_s if value.is_a?(::String) || value.is_a?(::Symbol)
|
|
115
|
+
|
|
116
|
+
text = value.to_s
|
|
117
|
+
path, _, command = text.rpartition("::")
|
|
118
|
+
path.empty? ? text : "#{path}.#{command}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|