hecks 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +4 -6
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +17 -98
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +5 -48
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +31 -141
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -194
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +100 -597
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/cli/document.rb +3 -21
- data/lib/hecks/cli/ir.rb +3 -5
- data/lib/hecks/cli/mcp.rb +2 -3
- data/lib/hecks/cli/mcp_door.rb +19 -114
- data/lib/hecks/cli/model_check.rb +18 -85
- data/lib/hecks/cli/project_cli.rb +7 -40
- data/lib/hecks/cli/project_diagrams.rb +0 -7
- data/lib/hecks/cli/run.rb +12 -58
- data/lib/hecks/cli/smoke_test.rb +2 -16
- data/lib/hecks/cli/stores.rb +1 -2
- data/lib/hecks/cli.rb +18 -24
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +82 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +9 -90
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +150 -678
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +2 -15
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +3 -6
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/gem_publisher.rb +2 -3
- data/lib/hecks/release/runner/npm_publisher.rb +6 -20
- data/lib/hecks/release/runner/preflight.rb +4 -19
- data/lib/hecks/release/runner/tagger.rb +2 -9
- data/lib/hecks/release/runner.rb +3 -32
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +99 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +141 -568
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +26 -81
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +3 -2
|
@@ -3,53 +3,18 @@ require_relative "../forms/field_shape"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Projector
|
|
6
|
-
# A bluebook
|
|
7
|
-
#
|
|
8
|
-
# ## What this is for
|
|
9
|
-
#
|
|
10
|
-
# `DocsProjector` already answers "what can I call and what does it
|
|
11
|
-
# want" for the person implementing against a domain — tables of
|
|
12
|
-
# arguments, shapes, refusal reasons. That is the wrong register for
|
|
13
|
-
# the person who can actually say whether the domain is right: the
|
|
14
|
-
# subject-matter expert who knows what an account is and has never
|
|
15
|
-
# read a markdown table in their life. This projects the same IR as
|
|
16
|
-
# sentences instead — "Debit — take money out. Issued by a Teller.
|
|
17
|
-
# It only goes through if the balance covers it." — so a domain can
|
|
18
|
-
# be read back to the person who can validate it without them
|
|
19
|
-
# learning the DSL first.
|
|
20
|
-
#
|
|
21
|
-
# Same source, same guarantee `DocsProjector` gives: nothing here is
|
|
22
|
-
# invented. Every sentence quotes a `description`, `goal`, or `given`
|
|
23
|
-
# already declared in the chapter; where a chapter says nothing, this
|
|
24
|
-
# says nothing rather than manufacturing a sentence out of an
|
|
25
|
-
# identifier. Registered as `:narrate` beside `:docs`, same call shape
|
|
26
|
-
# (`Projector.call(:narrate, bluebook: ...)`), same aggregate-scoping
|
|
27
|
-
# via `options[:aggregate]`.
|
|
28
|
-
#
|
|
29
|
-
# ## What it does not do
|
|
30
|
-
#
|
|
31
|
-
# Replace `DocsProjector`. A shape table still says "id of a
|
|
32
|
-
# Customer" more precisely than any sentence would, and an
|
|
33
|
-
# implementer still wants that. This is the other document the same
|
|
34
|
-
# IR is owed — one written for the reader who is being asked "is
|
|
35
|
-
# this right?", not "how do I call it?"
|
|
6
|
+
# A bluebook projected as prose an SME can read back and confirm.
|
|
7
|
+
# Every sentence quotes a declared `description`, `goal` or `given`; nothing is invented.
|
|
36
8
|
module NarrateProjector
|
|
37
9
|
module_function
|
|
38
10
|
|
|
39
|
-
# Projects `bluebook` as prose
|
|
40
|
-
#
|
|
41
|
-
# `options[:heading]` sets the top heading level, exactly as
|
|
42
|
-
# `DocsProjector` does — so this, too, can be spliced into a larger
|
|
43
|
-
# document rather than always starting at H1.
|
|
11
|
+
# Projects `bluebook` as prose; `options[:heading]` sets the top heading level.
|
|
44
12
|
#
|
|
45
13
|
# @param bluebook [Bluebook::Behaviour::Chapter] the chapter to narrate
|
|
46
|
-
# @param options [Hash]
|
|
47
|
-
#
|
|
48
|
-
# @
|
|
49
|
-
#
|
|
50
|
-
# @return [String] the narrative, as Markdown prose, ending in a newline
|
|
51
|
-
# @raise [Runtime::NotFound] if `options[:aggregate]` names no aggregate `bluebook`
|
|
52
|
-
# declares
|
|
14
|
+
# @param options [Hash] `:heading` (Integer, default 1) and `:aggregate` (narrows to one
|
|
15
|
+
# aggregate, omitting the chapter intro and reactions)
|
|
16
|
+
# @return [String] Markdown prose ending in a newline
|
|
17
|
+
# @raise [Runtime::NotFound] if `options[:aggregate]` names no declared aggregate
|
|
53
18
|
def call(bluebook:, options: {})
|
|
54
19
|
depth = (options[:heading] || 1).to_i
|
|
55
20
|
only = options[:aggregate]
|
|
@@ -63,14 +28,6 @@ module Hecks
|
|
|
63
28
|
"#{sections.compact.join("\n\n").rstrip}\n"
|
|
64
29
|
end
|
|
65
30
|
|
|
66
|
-
# ── the chapter ───────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
# Narrates the chapter-level intro: its vision, classification, former
|
|
69
|
-
# name, and the aggregates it's told through.
|
|
70
|
-
#
|
|
71
|
-
# @param bluebook [Bluebook::Behaviour::Chapter] the chapter to narrate
|
|
72
|
-
# @param depth [Integer] the heading level for the chapter's own title
|
|
73
|
-
# @return [String] the intro's Markdown prose
|
|
74
31
|
def chapter_intro(bluebook, depth)
|
|
75
32
|
parts = [DocsProjector.h(depth, bluebook.name)]
|
|
76
33
|
parts << bluebook.vision if bluebook.vision
|
|
@@ -85,14 +42,6 @@ module Hecks
|
|
|
85
42
|
parts.join("\n\n")
|
|
86
43
|
end
|
|
87
44
|
|
|
88
|
-
# ── one aggregate ─────────────────────────────────────────────────
|
|
89
|
-
|
|
90
|
-
# Narrates one aggregate: its description, identity, references,
|
|
91
|
-
# lifecycle, commands, queries, and nested entities.
|
|
92
|
-
#
|
|
93
|
-
# @param aggregate [Bluebook::Aggregate] the aggregate to narrate
|
|
94
|
-
# @param depth [Integer] the heading level for the aggregate's own title
|
|
95
|
-
# @return [String] the aggregate's Markdown prose
|
|
96
45
|
def aggregate_narrative(aggregate, depth)
|
|
97
46
|
parts = [DocsProjector.h(depth, aggregate.hecks_name)]
|
|
98
47
|
parts << aggregate.description if aggregate.description
|
|
@@ -113,23 +62,12 @@ module Hecks
|
|
|
113
62
|
parts.compact.join("\n\n")
|
|
114
63
|
end
|
|
115
64
|
|
|
116
|
-
# Names how a holder is identified.
|
|
117
|
-
#
|
|
118
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] the holder to describe
|
|
119
|
-
# @return [String, nil] a sentence naming `holder`'s identity fields, or nil if
|
|
120
|
-
# it declares none
|
|
121
65
|
def identity_sentence(holder)
|
|
122
66
|
return nil if holder.identity_heads.empty?
|
|
123
67
|
|
|
124
68
|
"Every #{holder.hecks_name} is identified by its #{to_sentence_list(holder.identity_heads.map { |h| "`#{h}`" })}."
|
|
125
69
|
end
|
|
126
70
|
|
|
127
|
-
# Narrates one entity nested under `aggregate`.
|
|
128
|
-
#
|
|
129
|
-
# @param aggregate [Bluebook::Aggregate] the entity's own owning aggregate
|
|
130
|
-
# @param entity [Bluebook::Entity] the entity to narrate
|
|
131
|
-
# @param depth [Integer] the heading level for the entity's own title
|
|
132
|
-
# @return [String] the entity's Markdown prose
|
|
133
71
|
def entity_narrative(aggregate, entity, depth)
|
|
134
72
|
parts = [DocsProjector.h(depth, "#{entity.hecks_name} (within #{aggregate.hecks_name})")]
|
|
135
73
|
parts << entity.description if entity.description
|
|
@@ -142,13 +80,6 @@ module Hecks
|
|
|
142
80
|
parts.compact.join("\n\n")
|
|
143
81
|
end
|
|
144
82
|
|
|
145
|
-
# ── the machine ───────────────────────────────────────────────────
|
|
146
|
-
|
|
147
|
-
# Narrates a holder's own lifecycle transitions.
|
|
148
|
-
#
|
|
149
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] the holder to describe
|
|
150
|
-
# @return [String, nil] a sentence per lifecycle transition, or nil if `holder`
|
|
151
|
-
# declares no lifecycle
|
|
152
83
|
def lifecycle_narrative(holder)
|
|
153
84
|
lifecycle = holder.lifecycle or return nil
|
|
154
85
|
|
|
@@ -161,15 +92,6 @@ module Hecks
|
|
|
161
92
|
sentences.join(" ")
|
|
162
93
|
end
|
|
163
94
|
|
|
164
|
-
# ── the verbs ─────────────────────────────────────────────────────
|
|
165
|
-
|
|
166
|
-
# Narrates every command a holder declares.
|
|
167
|
-
#
|
|
168
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] the holder whose
|
|
169
|
-
# commands to narrate
|
|
170
|
-
# @param depth [Integer] the heading level for the "What can happen" section
|
|
171
|
-
# @return [String, nil] the section's Markdown prose, or nil if `holder`
|
|
172
|
-
# declares no command
|
|
173
95
|
def verbs_narrative(holder, depth)
|
|
174
96
|
return nil if holder.commands.empty?
|
|
175
97
|
|
|
@@ -178,18 +100,7 @@ module Hecks
|
|
|
178
100
|
"#{header}\n\n#{body}"
|
|
179
101
|
end
|
|
180
102
|
|
|
181
|
-
#
|
|
182
|
-
# below states one unrelated fact about `command` (its goal, who
|
|
183
|
-
# issues it, whether it creates the holder, what it takes, what it
|
|
184
|
-
# references, what gates it, what it guarantees, what it emits), in
|
|
185
|
-
# the fixed order a reader expects them; nothing after the first
|
|
186
|
-
# sentence depends on anything before it. Same nil-or-string +
|
|
187
|
-
# `compact.join` shape `aggregate_narrative`/`entity_narrative`
|
|
188
|
-
# already use above for the identical reason.
|
|
189
|
-
#
|
|
190
|
-
# @param command [Bluebook::Command] the command to narrate
|
|
191
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] `command`'s own holder
|
|
192
|
-
# @return [String] the command's own paragraph
|
|
103
|
+
# Each sentence states one independent fact, so nil-or-string plus `compact.join` suffices.
|
|
193
104
|
def command_paragraph(command, holder)
|
|
194
105
|
[
|
|
195
106
|
command_headline_sentence(command),
|
|
@@ -203,48 +114,25 @@ module Hecks
|
|
|
203
114
|
].compact.join(" ")
|
|
204
115
|
end
|
|
205
116
|
|
|
206
|
-
# The goal
|
|
207
|
-
# exactly as declared, not recased to fit mid-sentence, because the
|
|
208
|
-
# promise this whole projector makes is that a sentence here is a
|
|
209
|
-
# sentence the chapter actually wrote.
|
|
210
|
-
#
|
|
211
|
-
# @param command [Bluebook::Command] the command to name
|
|
212
|
-
# @return [String] the command's own bold name, plus its goal if it declares one
|
|
117
|
+
# The goal is quoted exactly as declared, never recased to fit mid-sentence.
|
|
213
118
|
def command_headline_sentence(command)
|
|
214
119
|
"**#{command.hecks_name}**#{command.goal ? " — #{command.goal}." : '.'}"
|
|
215
120
|
end
|
|
216
121
|
|
|
217
|
-
# Names who issues a command.
|
|
218
|
-
#
|
|
219
|
-
# @param command [Bluebook::Command] the command to describe
|
|
220
|
-
# @return [String, nil] a sentence naming who issues `command`, or nil if it
|
|
221
|
-
# declares no role
|
|
222
122
|
def command_role_sentence(command)
|
|
223
123
|
return nil unless command.role
|
|
224
124
|
|
|
225
125
|
"Issued by #{a_or_an(command.role)} #{command.role}."
|
|
226
126
|
end
|
|
227
127
|
|
|
228
|
-
# `acts_on.nil?`, not `creates
|
|
229
|
-
#
|
|
230
|
-
# `Command#acts_on`'s own comment), so reading it directly here would
|
|
231
|
-
# tell an SME that `LedgerEntry.Amend` brings a new ledger entry into
|
|
232
|
-
# being, which is exactly backwards.
|
|
233
|
-
# @param command [Bluebook::Command] the command to check
|
|
234
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] `command`'s own holder
|
|
235
|
-
# @return [String, nil] a sentence saying `command` creates `holder`, or nil if
|
|
236
|
-
# `command` acts on an existing record instead
|
|
128
|
+
# `acts_on.nil?`, not `creates?`: `creates?` is true for every entity verb, which would
|
|
129
|
+
# wrongly say `LedgerEntry.Amend` creates a new ledger entry.
|
|
237
130
|
def command_creation_sentence(command, holder)
|
|
238
131
|
return nil unless command.acts_on.nil?
|
|
239
132
|
|
|
240
133
|
"This is how a new #{holder.hecks_name} comes into being."
|
|
241
134
|
end
|
|
242
135
|
|
|
243
|
-
# Lists a command's own non-reference arguments.
|
|
244
|
-
#
|
|
245
|
-
# @param command [Bluebook::Command] the command to describe
|
|
246
|
-
# @return [String, nil] a sentence listing `command`'s non-reference arguments,
|
|
247
|
-
# or nil if it declares none
|
|
248
136
|
def command_arguments_sentence(command)
|
|
249
137
|
arguments = command.attributes.reject(&:reference?)
|
|
250
138
|
return nil if arguments.empty?
|
|
@@ -252,11 +140,6 @@ module Hecks
|
|
|
252
140
|
"It takes #{to_sentence_list(arguments.map { |a| Forms::Humanize.label(a.name.to_s).downcase })}."
|
|
253
141
|
end
|
|
254
142
|
|
|
255
|
-
# Names what a command references.
|
|
256
|
-
#
|
|
257
|
-
# @param command [Bluebook::Command] the command to describe
|
|
258
|
-
# @return [String, nil] a sentence naming what `command` references, or nil if
|
|
259
|
-
# it declares no reference argument
|
|
260
143
|
def command_references_sentence(command)
|
|
261
144
|
refs = command.attributes.select(&:reference?)
|
|
262
145
|
return nil if refs.empty?
|
|
@@ -264,12 +147,6 @@ module Hecks
|
|
|
264
147
|
"It's aimed at one existing #{to_sentence_list(refs.map { |r| r.type.target_name })}, by id."
|
|
265
148
|
end
|
|
266
149
|
|
|
267
|
-
# Lists a command's own required conditions.
|
|
268
|
-
#
|
|
269
|
-
# @param command [Bluebook::Command] the command to describe
|
|
270
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] `command`'s own holder
|
|
271
|
-
# @return [String, nil] a sentence listing every required condition, or nil if
|
|
272
|
-
# `command` declares none
|
|
273
150
|
def command_conditions_sentence(command, holder)
|
|
274
151
|
conditions = conditions_of(command, holder)
|
|
275
152
|
return nil if conditions.empty?
|
|
@@ -277,11 +154,6 @@ module Hecks
|
|
|
277
154
|
"It only goes through if #{conditions.join('; ')}."
|
|
278
155
|
end
|
|
279
156
|
|
|
280
|
-
# Lists what a command guarantees when it succeeds.
|
|
281
|
-
#
|
|
282
|
-
# @param command [Bluebook::Command] the command to describe
|
|
283
|
-
# @return [String, nil] a sentence listing `command`'s own `ensures`, or nil if
|
|
284
|
-
# it declares none
|
|
285
157
|
def command_guarantees_sentence(command)
|
|
286
158
|
guarantees = command.ensures.map(&:description)
|
|
287
159
|
return nil if guarantees.empty?
|
|
@@ -289,27 +161,14 @@ module Hecks
|
|
|
289
161
|
"When it succeeds: #{guarantees.join('; ')}."
|
|
290
162
|
end
|
|
291
163
|
|
|
292
|
-
# Names what a command records.
|
|
293
|
-
#
|
|
294
|
-
# @param command [Bluebook::Command] the command to describe
|
|
295
|
-
# @return [String, nil] a sentence naming what `command` records, or nil if it
|
|
296
|
-
# emits nothing
|
|
297
164
|
def command_emits_sentence(command)
|
|
298
165
|
return nil if command.emits.empty?
|
|
299
166
|
|
|
300
167
|
"It records `#{command.emits.join('`, `')}` as a fact."
|
|
301
168
|
end
|
|
302
169
|
|
|
303
|
-
#
|
|
304
|
-
#
|
|
305
|
-
# lifecycle edge, a reference's existence, and the command's own
|
|
306
|
-
# `given`s), but kept positive rather than phrased as a refusal
|
|
307
|
-
# reason. "Refused unless not X" is a sentence a reader has to
|
|
308
|
-
# invert in their head; "only goes through if X" is not.
|
|
309
|
-
#
|
|
310
|
-
# @param command [Bluebook::Command] the command to gather conditions for
|
|
311
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] `command`'s own holder
|
|
312
|
-
# @return [Array<String>] every required condition, stated positively
|
|
170
|
+
# Required conditions stated positively ("only goes through if X"), from the lifecycle
|
|
171
|
+
# edge and the command's `given`s.
|
|
313
172
|
def conditions_of(command, holder)
|
|
314
173
|
conditions = []
|
|
315
174
|
|
|
@@ -328,14 +187,6 @@ module Hecks
|
|
|
328
187
|
conditions + command.givens.map(&:description)
|
|
329
188
|
end
|
|
330
189
|
|
|
331
|
-
# ── the reads ─────────────────────────────────────────────────────
|
|
332
|
-
|
|
333
|
-
# Narrates every query as one line per question.
|
|
334
|
-
#
|
|
335
|
-
# @param queries [Array<Bluebook::Query>] the queries to narrate
|
|
336
|
-
# @param holder_name [String] the queries' own holder's name
|
|
337
|
-
# @param depth [Integer] the heading level for the "Questions you can ask" section
|
|
338
|
-
# @return [String, nil] the section's Markdown prose, or nil if `queries` is empty
|
|
339
190
|
def queries_narrative(queries, holder_name, depth)
|
|
340
191
|
return nil if queries.empty?
|
|
341
192
|
|
|
@@ -343,10 +194,7 @@ module Hecks
|
|
|
343
194
|
lines = queries.map do |query|
|
|
344
195
|
shape = query.to_h
|
|
345
196
|
takes = Array(shape[:attributes]).map { |a| Forms::Humanize.label(a[:name].to_s).downcase }
|
|
346
|
-
# `w[:value]` already
|
|
347
|
-
# `Literal.render`ed string (see lib/hecks/literal.rb), not a raw
|
|
348
|
-
# Ruby value, so wrapping it in `.inspect` here would quote an
|
|
349
|
-
# already-quoted string a second time.
|
|
197
|
+
# `w[:value]` is already `Literal.render`ed (quoted), so no `.inspect`.
|
|
350
198
|
filters = Array(shape[:wheres]).map { |w| "`#{w[:field]}` #{op_words(w[:op])} #{w[:value]}" }
|
|
351
199
|
|
|
352
200
|
sentence = "- **#{query.hecks_name}**"
|
|
@@ -359,23 +207,10 @@ module Hecks
|
|
|
359
207
|
"#{header}\n\n#{lines.join("\n")}"
|
|
360
208
|
end
|
|
361
209
|
|
|
362
|
-
# Translates a query comparator into plain English.
|
|
363
|
-
#
|
|
364
|
-
# @param comparator [String, Symbol] a where-clause comparator, such as `:eq`
|
|
365
|
-
# @return [String] the comparator in plain words, or `comparator.to_s` verbatim
|
|
366
|
-
# for one this file has no rendering rule for
|
|
367
210
|
def op_words(comparator)
|
|
368
211
|
{ eq: "is", lt: "under", lte: "at most", gt: "over", gte: "at least" }[comparator.to_s.to_sym] || comparator.to_s
|
|
369
212
|
end
|
|
370
213
|
|
|
371
|
-
# ── what happens on its own ───────────────────────────────────────
|
|
372
|
-
|
|
373
|
-
# Narrates what happens on its own: every policy and every saga.
|
|
374
|
-
#
|
|
375
|
-
# @param bluebook [Bluebook::Behaviour::Chapter] the chapter to narrate
|
|
376
|
-
# @param depth [Integer] the heading level for the "Reactions" section
|
|
377
|
-
# @return [String, nil] the section's Markdown prose, or nil if `bluebook`
|
|
378
|
-
# declares no policy and no process manager
|
|
379
214
|
def reactions_narrative(bluebook, depth)
|
|
380
215
|
return nil if bluebook.policies.empty? && bluebook.process_managers.empty?
|
|
381
216
|
|
|
@@ -395,19 +230,10 @@ module Hecks
|
|
|
395
230
|
parts.join("\n\n")
|
|
396
231
|
end
|
|
397
232
|
|
|
398
|
-
# ── small sentence carpentry ──────────────────────────────────────
|
|
399
|
-
|
|
400
|
-
# Both now live in `Naming` (a second projection, the glossary,
|
|
401
|
-
# needed them); kept here as names so this file reads as it did.
|
|
402
|
-
#
|
|
403
|
-
# @param items [Array<#to_s>] items to join, in order
|
|
404
|
-
# @param conj [String] conjunction placed before the last item
|
|
405
|
-
# @return [String] the joined sentence fragment, `""` for an empty `items`
|
|
406
233
|
def to_sentence_list(items, conj: "and") = Naming.to_sentence_list(items, conj: conj)
|
|
407
234
|
|
|
408
|
-
# Picks the
|
|
235
|
+
# Picks the article for `word`.
|
|
409
236
|
#
|
|
410
|
-
# @param word [String, Symbol] the word the article precedes
|
|
411
237
|
# @return [String] `"a"` or `"an"`
|
|
412
238
|
def a_or_an(word) = Naming.a_or_an(word)
|
|
413
239
|
end
|
|
@@ -1,89 +1,26 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Projector
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# this only removes the second step, so a target declares its own key
|
|
6
|
-
# beside its own implementation instead of being registered from
|
|
7
|
-
# somewhere else that has to be kept in sync with it.
|
|
3
|
+
# A projection target declares its own registration key beside its own
|
|
4
|
+
# implementation, instead of a separate registry entry that can drift.
|
|
8
5
|
#
|
|
9
6
|
# module Hecks::Projections::OIDC
|
|
10
7
|
# extend Hecks::Projector::Target
|
|
11
8
|
# projects_as :oidc
|
|
12
|
-
#
|
|
13
|
-
# module_function
|
|
14
|
-
#
|
|
15
|
-
# def call(bluebook:, options: {}) = { ... }
|
|
9
|
+
# def self.call(bluebook:, options: {}) = { ... }
|
|
16
10
|
# end
|
|
17
11
|
#
|
|
18
|
-
# Named `Target`, not `Projection`,
|
|
19
|
-
# means two other things in this codebase: `Ports::Projection` is
|
|
20
|
-
# read-model catch-up (events folded into view state), and `bin/project`
|
|
21
|
-
# forces that catch-up by hand. Neither has anything to do with
|
|
22
|
-
# "canonical IR in, external artifact out". A third meaning under the
|
|
23
|
-
# same word would make the two impossible to grep apart — and from a
|
|
24
|
-
# domain's point of view `project(X)` really does read as "project to
|
|
25
|
-
# a target", so the narrower word is also the more accurate one.
|
|
12
|
+
# Named `Target`, not `Projection`, which already means read-model catch-up elsewhere.
|
|
26
13
|
module Target
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# `requires:` names a capability, not a shape word.
|
|
32
|
-
#
|
|
33
|
-
# This began as `from: :chapter` / `from: :any` — two hand-kept
|
|
34
|
-
# symbols, admitted by duck-typing on `.aggregates`, which is a
|
|
35
|
-
# guess at what "is a chapter" means. The capabilities were already
|
|
36
|
-
# real by then: `Hecks::IR` is the ability to emit IR (its own
|
|
37
|
-
# header says so), and `Behaviour::Chapter` is the ability to answer
|
|
38
|
-
# as a chapter. So a projection names the module it needs, and
|
|
39
|
-
# admission is a genuine check rather than a proxy for one.
|
|
40
|
-
#
|
|
41
|
-
# projects_as :ir, requires: Hecks::IR
|
|
42
|
-
# projects_as :vocabulary # chapter, the default
|
|
43
|
-
#
|
|
44
|
-
# It also composes: a projection needing two capabilities names
|
|
45
|
-
# both, instead of a third symbol being invented for the pair.
|
|
46
|
-
#
|
|
47
|
-
# The fail-quiet this closes, unchanged in substance: every
|
|
48
|
-
# construct emits its own IR, so handing a projector an aggregate
|
|
49
|
-
# instead of a chapter is the natural thing to try. `bluebook:` was
|
|
50
|
-
# only ever a parameter name, never a contract. `:oidc` failed
|
|
51
|
-
# loudly (no `aggregates` method), but `:shape` returned
|
|
52
|
-
# `{"name" => "Order", "aggregates" => []}` — well-formed,
|
|
53
|
-
# confident, and wrong.
|
|
54
|
-
# `declares:` names an aggregate the chapter must have.
|
|
55
|
-
#
|
|
56
|
-
# A capability says what a construct can do; this says what it must
|
|
57
|
-
# carry. `:vocabulary` needs a chapter declaring a Vocabulary
|
|
58
|
-
# aggregate, `:parser_table` one declaring Syntax — declared here
|
|
59
|
-
# rather than as a `raise` in the projection's own body, so the
|
|
60
|
-
# requirement is stated instead of written as behaviour. The
|
|
61
|
-
# registry refuses before the projection runs, so the projection
|
|
62
|
-
# itself carries no guard about its own admission.
|
|
63
|
-
# `emits:` says what kind of artifact comes back.
|
|
64
|
-
#
|
|
65
|
-
# `:artifact` (the default) is one thing — a Hash, or a String.
|
|
66
|
-
# `:files` is a tree: a Hash of relative path => contents, which is
|
|
67
|
-
# what a reference-page or codegen projection produces.
|
|
68
|
-
#
|
|
69
|
-
# Declared rather than sniffed, deliberately. Inferring a tree from
|
|
70
|
-
# an ordinary Hash is guesswork — `{"name" => "Pizzas"}` is
|
|
71
|
-
# indistinguishable from a one-file tree — so `write` asks what the
|
|
72
|
-
# projection said rather than inspecting what it returned.
|
|
73
|
-
# Registers `self` as a projection target under `key`, and stores the
|
|
74
|
-
# capability and aggregate requirements `admits!` later checks against.
|
|
14
|
+
# Registers `self` as a projection target under `key`; the registry
|
|
15
|
+
# checks `requires`/`declares` before a projection ever runs, so a
|
|
16
|
+
# projection carries no admission guard of its own.
|
|
75
17
|
#
|
|
76
|
-
# @param key [String, Symbol]
|
|
77
|
-
# @param requires [Module, Array<Module>, nil] capability module(s)
|
|
78
|
-
#
|
|
79
|
-
# @param declares [String, Symbol, Array
|
|
80
|
-
#
|
|
81
|
-
# @param
|
|
82
|
-
# a single Hash or String) or `:files` (a path => contents tree)
|
|
83
|
-
# @param needs_world [Boolean] whether `self` is an export — a target that reads a
|
|
84
|
-
# domain's `.world`/`.hecksagon` bindings, not only its declaration. `false` (the
|
|
85
|
-
# default) for an ordinary projection; `true` refuses a `Projector.call` made with
|
|
86
|
-
# no `world:`.
|
|
18
|
+
# @param key [String, Symbol] key to register `self` under
|
|
19
|
+
# @param requires [Module, Array<Module>, nil] capability module(s) required;
|
|
20
|
+
# nil/empty means `Bluebook::Behaviour::Chapter`
|
|
21
|
+
# @param declares [String, Symbol, Array, nil] aggregate name(s) the chapter must declare
|
|
22
|
+
# @param emits [Symbol] :artifact (a Hash/String, the default) or :files (a path => tree)
|
|
23
|
+
# @param needs_world [Boolean] true refuses a call made with no `world:` bindings
|
|
87
24
|
# @return [Symbol] the registered key
|
|
88
25
|
def projects_as(key, requires: nil, declares: nil, emits: :artifact, needs_world: false)
|
|
89
26
|
@projection_emits = emits
|