hecks 2.8.0 → 3.0.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 +50 -7
- 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 +32 -100
- 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 +10 -32
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +149 -136
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +48 -38
- 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 +76 -62
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- 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 +56 -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 +39 -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 +11 -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 +16 -50
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +49 -67
- 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 +96 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
- 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 +42 -89
- 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 +148 -197
- 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 +38 -43
- 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 +46 -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 +39 -661
- data/lib/hecks/bluebook/hexagon.rb +18 -33
- 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 +25 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +87 -352
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +122 -596
- data/lib/hecks/bluebook/pattern_subset.rb +49 -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 +27 -51
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +9 -99
- 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/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +5 -23
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +4 -6
- data/lib/hecks/cli/mcp.rb +5 -6
- data/lib/hecks/cli/model_check.rb +24 -88
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +223 -64
- data/lib/hecks/cli/project_diagrams.rb +4 -10
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +15 -61
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +7 -19
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -6
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +216 -73
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +14 -34
- data/lib/hecks/doors/handle.rb +206 -0
- data/lib/hecks/doors/json_door.rb +132 -0
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
- data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
- data/lib/hecks/doors/ruby_door.rb +77 -0
- data/lib/hecks/doors.rb +61 -0
- 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 +5 -72
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +23 -51
- data/lib/hecks/forms/app.rb +21 -76
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- 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 +31 -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/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- 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/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/kernel_capabilities.rb +194 -0
- 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 +26 -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 +19 -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 +83 -198
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -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_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- 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 +44 -144
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
- 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 +19 -76
- 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 +43 -127
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- 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 +50 -47
- 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/translation.rb +1 -0
- 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 +47 -108
- 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/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +12 -44
- 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 +40 -207
- data/lib/hecks/projections/deploy/lambda.rb +191 -708
- 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/preview.sh.erb +1 -1
- 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 +3 -59
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +48 -147
- 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 +22 -584
- 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 +16 -43
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +13 -32
- data/lib/hecks/projections/reference.rb +4 -18
- data/lib/hecks/projections/rust_vocabulary.rb +13 -251
- 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 +154 -400
- 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/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- 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 +5 -8
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +15 -9
- data/lib/hecks/release/runner/npm_publisher.rb +9 -53
- data/lib/hecks/release/runner/preflight.rb +29 -20
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +31 -23
- data/lib/hecks/release/runner.rb +60 -38
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +15 -39
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- 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 +27 -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 +50 -104
- data/lib/hecks/runtime/dispatcher.rb +134 -243
- 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 +14 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +109 -194
- data/lib/hecks/runtime/outbox.rb +39 -262
- data/lib/hecks/runtime/policy_interpreter.rb +43 -202
- data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
- data/lib/hecks/runtime/query_interpreter.rb +122 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- 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 +28 -87
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +213 -227
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +156 -247
- data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
- 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 +162 -760
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +15 -84
- data/lib/hecks/runtime.rb +35 -69
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +155 -582
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- 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 +52 -90
- 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
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +478 -12
- data/lib/hecks/facade/cli_door.rb +0 -178
- data/lib/hecks/facade/cli_runner.rb +0 -271
- data/lib/hecks/facade/handle.rb +0 -293
- data/lib/hecks/facade/json_door.rb +0 -247
- data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
- data/lib/hecks/facade/surface/chapter.rb +0 -116
- data/lib/hecks/facade/surface.rb +0 -61
- data/lib/hecks/mcp_door_scope.rb +0 -176
|
@@ -2,137 +2,77 @@ require_relative "../naming"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Projector
|
|
5
|
-
#
|
|
5
|
+
# Projects a bluebook as its own command-line surface: the verb tree, argument spec
|
|
6
|
+
# and usage text. Nothing executes here; the generic runner (`hecks run`) parses against it.
|
|
6
7
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# already stated in the chapter. A hand-written CLI restates all of it and
|
|
10
|
-
# then drifts — and the first thing to drift is the help text, which is the
|
|
11
|
-
# only part anybody reads.
|
|
12
|
-
#
|
|
13
|
-
# ## What is projected
|
|
14
|
-
#
|
|
15
|
-
# This answers the surface only — the verb tree, the argument spec, the
|
|
16
|
-
# usage text — and nothing executes here. One small generic runner
|
|
17
|
-
# (`bin/run`) boots a domain, asks for this, parses against it and
|
|
18
|
-
# dispatches.
|
|
19
|
-
#
|
|
20
|
-
# ## Why project rather than generate
|
|
21
|
-
#
|
|
22
|
-
# The alternative was generating an executable per domain, which is what
|
|
23
|
-
# `bin/project_rust` does for a whole runtime and would be the more
|
|
24
|
-
# spectacular version of this. It was not taken: a generated program is a
|
|
25
|
-
# second copy of the dispatch logic, and it needs regenerating on every
|
|
26
|
-
# bluebook edit — a second tax beside the era gate, paid for a file nobody
|
|
27
|
-
# reads. Projecting the surface keeps one dispatcher and a help text that
|
|
28
|
-
# cannot be stale, because it is computed at the moment it is printed.
|
|
29
|
-
#
|
|
30
|
-
# ## The typing is the point
|
|
31
|
-
#
|
|
32
|
-
# A CLI hands everything over as a String. `sequence.value=99` has to
|
|
33
|
-
# become the Integer 99 or the runtime refuses it, and the only honest
|
|
34
|
-
# place to learn that is the value object's own declared field type. A CLI
|
|
35
|
-
# that guessed — "it looks like a number" — would send 99 for a version
|
|
36
|
-
# string of "99" and be wrong in a way nobody could see.
|
|
8
|
+
# Argument types come from the declared field types, never from guessing at the
|
|
9
|
+
# string: `sequence.value=99` must become 99, and a version "99" must stay a String.
|
|
37
10
|
module CliProjector
|
|
38
11
|
module_function
|
|
39
12
|
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
# A chapter may legally declare a command and a query of one name: the
|
|
43
|
-
# language namespaces them and `Banking::Account.Open` is both, in the
|
|
44
|
-
# corpus, today. A single flat list of subcommands has to pick one, and
|
|
45
|
-
# picking silently is how `Ticket.Filed` sat undetected in this
|
|
46
|
-
# repository for a day.
|
|
47
|
-
#
|
|
48
|
-
# So a question is asked with `ask`: `bin/run ask account.open`. It is
|
|
49
|
-
# this codebase own word — `Query::AskOption`, "the ask" — it is
|
|
50
|
-
# shell-safe where a `?` suffix would be eaten by globbing, and it makes
|
|
51
|
-
# the collision impossible rather than detected. It also reads as what it
|
|
52
|
-
# is: everything under `ask` changes nothing.
|
|
13
|
+
# Projects the verb and question tables and the usage text. Commands and queries are
|
|
14
|
+
# separate namespaces (a chapter may declare both under one name); ask a query with `ask`.
|
|
53
15
|
#
|
|
54
16
|
# @param bluebook [Bluebook::Chapter] the booted domain to project
|
|
55
|
-
# @param options [Hash{Symbol => Object}] `:program` (
|
|
56
|
-
# `
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# @raise [Bluebook::DSL::Malformed] if two verbs project to the same command-line
|
|
63
|
-
# name
|
|
17
|
+
# @param options [Hash{Symbol => Object}] `:program` (default `"hecks run"`) for the usage
|
|
18
|
+
# text; `:verb` and `:ask` select one verb's `--help` text; `:names` maps a launcher
|
|
19
|
+
# name to the command it stands for (`{ "mcp" => "serve_mcp" }`); `:mint_run_keys` makes a
|
|
20
|
+
# creating verb's `run` key optional, since the launcher mints it
|
|
21
|
+
# @return [Hash{Symbol => Object}] `:verbs`, `:questions`, `:names` (alias tables) and
|
|
22
|
+
# `:usage` (pre-rendered help text)
|
|
23
|
+
# @raise [Bluebook::DSL::Malformed] if two verbs project to the same command-line name
|
|
64
24
|
def call(bluebook:, options: {})
|
|
65
25
|
verbs = {}
|
|
66
26
|
questions = {}
|
|
67
27
|
|
|
68
|
-
bluebook.aggregates.each
|
|
69
|
-
aggregate.commands.each { |c| claim(verbs, name_for(aggregate, c), command_spec(bluebook, aggregate, nil, c)) }
|
|
70
|
-
aggregate.queries.each { |q| claim(questions, name_for(aggregate, q), query_spec(bluebook, aggregate, nil, q)) }
|
|
71
|
-
|
|
72
|
-
aggregate.entities.each do |entity|
|
|
73
|
-
entity.commands.each do |c|
|
|
74
|
-
claim(verbs, name_for(aggregate, c, entity), command_spec(bluebook, aggregate, entity, c))
|
|
75
|
-
end
|
|
76
|
-
entity.queries.each do |q|
|
|
77
|
-
claim(questions, name_for(aggregate, q, entity), query_spec(bluebook, aggregate, entity, q))
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# A port is a verb too, and leaving it off the map was a real gap
|
|
82
|
-
# rather than a tasteful omission. The runtime has always dispatched
|
|
83
|
-
# a port operation by exactly the same name as a command — the
|
|
84
|
-
# projection simply never listed one, so `run_specs` and `file`
|
|
85
|
-
# answered "no such verb" while working perfectly through Ruby.
|
|
86
|
-
#
|
|
87
|
-
# It matters most for the caller with no other door. An agent that
|
|
88
|
-
# may not shell out reaches this domain only through the projected
|
|
89
|
-
# CLI, and a port it cannot see is a capability it does not have.
|
|
90
|
-
aggregate.ports.each do |port|
|
|
91
|
-
port.operations.each { |o| claim(verbs, name_for(aggregate, o), port_spec(bluebook, aggregate, port, o)) }
|
|
92
|
-
end
|
|
93
|
-
end
|
|
28
|
+
bluebook.aggregates.each { |aggregate| claim_aggregate(verbs, questions, bluebook, aggregate) }
|
|
94
29
|
|
|
95
|
-
# A report
|
|
96
|
-
#
|
|
97
|
-
# the projection simply never listed one — so the composed reads worked
|
|
98
|
-
# from Ruby and did not exist for anybody whose only door is the command
|
|
99
|
-
# line.
|
|
100
|
-
#
|
|
101
|
-
# It matters most for exactly what a report is for. Every other question
|
|
102
|
-
# here answers with rows and leaves the arithmetic to the reader; a
|
|
103
|
-
# `group_by` report is the one that counts. An agent that cannot reach
|
|
104
|
-
# it can list bugs all day and never answer "how are we doing".
|
|
105
|
-
#
|
|
106
|
-
# **One dot, not two** — a report belongs to the chapter rather than to any
|
|
107
|
-
# aggregate (that is what rootless means), so it is addressed
|
|
108
|
-
# `QualityControl.BugsByStatus` where a query is
|
|
109
|
-
# `QualityControl::Bug.Queue`. `Dispatcher#query` splits on precisely
|
|
110
|
-
# that difference.
|
|
30
|
+
# A report belongs to the chapter, not an aggregate, so it is addressed
|
|
31
|
+
# `Chapter.Report` (one dot) where a query is `Chapter::Aggregate.Query`.
|
|
111
32
|
bluebook.read_models.each do |model|
|
|
112
33
|
claim(questions, Naming.snake(model.hecks_name), report_spec(bluebook, model))
|
|
113
34
|
end
|
|
114
35
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
# always accepted; `names` maps every accepted one to its canonical
|
|
120
|
-
# key, and the display name is the shortest that is unambiguous.
|
|
121
|
-
shorten(verbs)
|
|
122
|
-
shorten(questions)
|
|
36
|
+
mint_run_keys(verbs) if options[:mint_run_keys]
|
|
37
|
+
|
|
38
|
+
# The display name is the shortest unambiguous one; both spellings are accepted.
|
|
39
|
+
display_names([verbs, questions], options[:names])
|
|
123
40
|
|
|
124
41
|
{ verbs: verbs, questions: questions,
|
|
125
42
|
names: { command: aliases(verbs), question: aliases(questions) },
|
|
126
43
|
usage: usage(bluebook, verbs, questions, options) }
|
|
127
44
|
end
|
|
128
45
|
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
46
|
+
# Claims the verbs and questions of one aggregate and its entities and ports.
|
|
47
|
+
#
|
|
48
|
+
# @param verbs [Hash{String => Hash}] the verb map, mutated in place
|
|
49
|
+
# @param questions [Hash{String => Hash}] the question map, mutated in place
|
|
50
|
+
# @param bluebook [Bluebook::Chapter] the booted domain
|
|
51
|
+
# @param aggregate [Bluebook::Aggregate] the aggregate to claim
|
|
52
|
+
# @return [void]
|
|
53
|
+
def claim_aggregate(verbs, questions, bluebook, aggregate)
|
|
54
|
+
aggregate.commands.each { |c| claim(verbs, name_for(aggregate, c), command_spec(bluebook, aggregate, nil, c)) }
|
|
55
|
+
aggregate.queries.each { |q| claim(questions, name_for(aggregate, q), query_spec(bluebook, aggregate, nil, q)) }
|
|
56
|
+
|
|
57
|
+
aggregate.entities.each do |entity|
|
|
58
|
+
entity.commands.each do |c|
|
|
59
|
+
claim(verbs, name_for(aggregate, c, entity), command_spec(bluebook, aggregate, entity, c))
|
|
60
|
+
end
|
|
61
|
+
entity.queries.each do |q|
|
|
62
|
+
claim(questions, name_for(aggregate, q, entity), query_spec(bluebook, aggregate, entity, q))
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Port operations dispatch by the same name as a command, so they are verbs too.
|
|
67
|
+
aggregate.ports.each do |port|
|
|
68
|
+
port.operations.each { |o| claim(verbs, name_for(aggregate, o), port_spec(bluebook, aggregate, port, o)) }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Sets `:short` on each spec: the last segment when exactly one verb ends in it,
|
|
73
|
+
# else the full name (two aggregates both declaring `Close` keep both spellings).
|
|
133
74
|
#
|
|
134
|
-
# @param specs [Hash{String => Hash}] the verb or question map
|
|
135
|
-
# mutated in place: each spec hash gains a `:short` key
|
|
75
|
+
# @param specs [Hash{String => Hash}] the verb or question map, mutated in place
|
|
136
76
|
# @return [void]
|
|
137
77
|
def shorten(specs)
|
|
138
78
|
tails = specs.keys.group_by { |name| name.split(".").last }
|
|
@@ -142,30 +82,68 @@ module Hecks
|
|
|
142
82
|
end
|
|
143
83
|
end
|
|
144
84
|
|
|
145
|
-
#
|
|
85
|
+
# Marks the `run` key of each creating verb `minted`: optional, and never filled by a bare
|
|
86
|
+
# word, since the launcher makes one when it is left out.
|
|
87
|
+
def mint_run_keys(verbs)
|
|
88
|
+
verbs.each_value do |spec|
|
|
89
|
+
next unless spec[:creates]
|
|
90
|
+
|
|
91
|
+
spec[:arguments] = spec[:arguments].map do |argument|
|
|
92
|
+
next argument unless argument[:path] == "run.value"
|
|
93
|
+
|
|
94
|
+
argument.merge(required: false, minted: true, note: "minted when omitted")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Sets the display name of every spec in each map: shortened, then renamed by `names`.
|
|
146
100
|
#
|
|
147
|
-
# @param
|
|
148
|
-
#
|
|
149
|
-
# @return [
|
|
150
|
-
|
|
101
|
+
# @param maps [Array<Hash{String => Hash}>] the verb and question maps, mutated in place
|
|
102
|
+
# @param names [Hash, nil] the chapter's launcher names
|
|
103
|
+
# @return [void]
|
|
104
|
+
def display_names(maps, names)
|
|
105
|
+
maps.each do |specs|
|
|
106
|
+
shorten(specs)
|
|
107
|
+
rename(specs, names)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Gives a command the launcher name a chapter's `names` table assigns it.
|
|
112
|
+
#
|
|
113
|
+
# The alias replaces the short name in help, so it is listed once; the spelling it
|
|
114
|
+
# replaced keeps working (`:short_was`, read by `aliases`). A table entry naming no
|
|
115
|
+
# command in `specs` belongs to the other namespace and is skipped.
|
|
116
|
+
#
|
|
117
|
+
# @param specs [Hash{String => Hash}] the verb or question map, mutated in place
|
|
118
|
+
# @param names [Hash{String, Symbol => String, Symbol}, nil] launcher name to command name
|
|
119
|
+
# @return [void]
|
|
120
|
+
# @raise [Bluebook::DSL::Malformed] if a launcher name is already another command's name
|
|
121
|
+
def rename(specs, names)
|
|
122
|
+
Hash(names).each do |launcher_name, command|
|
|
123
|
+
found = specs.find { |key, spec| [key, spec[:short]].include?(command.to_s) }
|
|
124
|
+
next unless found
|
|
125
|
+
|
|
126
|
+
taken = specs.values.any? { |spec| spec[:short] == launcher_name.to_s }
|
|
127
|
+
raise Bluebook::DSL::Malformed, "launcher name #{launcher_name.to_s.inspect} is already a command" if taken
|
|
128
|
+
|
|
129
|
+
found.last[:short_was] = found.last[:short]
|
|
130
|
+
found.last[:short] = launcher_name.to_s
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Maps every accepted spelling (full name, `:short` and a renamed command's old short
|
|
135
|
+
# name) to the full name.
|
|
151
136
|
def aliases(specs)
|
|
152
137
|
specs.each_with_object({}) do |(name, spec), map|
|
|
153
138
|
map[name] = name
|
|
154
139
|
map[spec[:short]] = name
|
|
140
|
+
map[spec[:short_was]] = name if spec[:short_was]
|
|
155
141
|
end
|
|
156
142
|
end
|
|
157
143
|
|
|
158
|
-
#
|
|
159
|
-
#
|
|
160
|
-
# subcommands. Refused here rather than silently resolving to whichever
|
|
161
|
-
# was walked first, which is how `Ticket.Filed` (a command) and
|
|
162
|
-
# `Ticket.Filed` (a query) sat undetected until something flattened them.
|
|
144
|
+
# Stores `spec` under `name`, refusing a second claim rather than silently
|
|
145
|
+
# keeping whichever verb was walked first.
|
|
163
146
|
#
|
|
164
|
-
# @param verbs [Hash{String => Hash}] the verb or question map being built,
|
|
165
|
-
# mutated in place
|
|
166
|
-
# @param name [String] the command-line name this spec claims
|
|
167
|
-
# @param spec [Hash{Symbol => Object}] the spec hash to store under `name`
|
|
168
|
-
# @return [void]
|
|
169
147
|
# @raise [Bluebook::DSL::Malformed] if `name` is already claimed by another verb
|
|
170
148
|
def claim(verbs, name, spec)
|
|
171
149
|
if verbs.key?(name)
|
|
@@ -177,15 +155,7 @@ module Hecks
|
|
|
177
155
|
verbs[name] = spec
|
|
178
156
|
end
|
|
179
157
|
|
|
180
|
-
#
|
|
181
|
-
# snake-cased.
|
|
182
|
-
#
|
|
183
|
-
# @param aggregate [Bluebook::Aggregate] the verb's owning aggregate
|
|
184
|
-
# @param verb [Bluebook::Command, Bluebook::Query, Bluebook::PortOperation]
|
|
185
|
-
# the command, query or port operation being named
|
|
186
|
-
# @param entity [Bluebook::Entity, nil] the entity the verb is declared on, or `nil`
|
|
187
|
-
# for an aggregate-level verb
|
|
188
|
-
# @return [String] the dotted, snake-cased command-line name
|
|
158
|
+
# The dotted command-line name, `aggregate[.entity].verb`, snake-cased.
|
|
189
159
|
def name_for(aggregate, verb, entity = nil)
|
|
190
160
|
parts = [Naming.snake(aggregate.hecks_name)]
|
|
191
161
|
parts << Naming.snake(entity.hecks_name) if entity
|
|
@@ -193,39 +163,15 @@ module Hecks
|
|
|
193
163
|
parts.join(".")
|
|
194
164
|
end
|
|
195
165
|
|
|
196
|
-
#
|
|
197
|
-
# for display in help text.
|
|
198
|
-
#
|
|
199
|
-
# @param bluebook [Bluebook::Chapter] the verb's owning chapter
|
|
200
|
-
# @param aggregate [Bluebook::Aggregate] the verb's owning aggregate
|
|
201
|
-
# @param verb [Bluebook::Command, Bluebook::Query, Bluebook::PortOperation]
|
|
202
|
-
# the command, query or port operation being named
|
|
203
|
-
# @param entity [Bluebook::Entity, nil] the entity the verb is declared on, or `nil`
|
|
204
|
-
# for an aggregate-level verb
|
|
205
|
-
# @return [String] the fully-qualified name, as the language spells it
|
|
166
|
+
# The verb's language name, `Chapter::Aggregate[.Entity].Verb`, for help text.
|
|
206
167
|
def fqn(bluebook, aggregate, verb, entity = nil)
|
|
207
168
|
[bluebook.name, "::", aggregate.hecks_name, ".",
|
|
208
169
|
entity ? "#{entity.hecks_name}." : "", verb.hecks_name].join
|
|
209
170
|
end
|
|
210
171
|
|
|
211
|
-
# The
|
|
212
|
-
# `
|
|
213
|
-
# aggregate
|
|
214
|
-
# `:entity` or `nil`, because a port is declared on an aggregate, never
|
|
215
|
-
# an entity), and this is exactly the same "how do I name the record"
|
|
216
|
-
# question a command with a receiver already answers, so it is answered
|
|
217
|
-
# once, here, rather than duplicated.
|
|
218
|
-
#
|
|
219
|
-
# `nil` — a creating command — takes none: there is no existing record
|
|
220
|
-
# yet for `to=` to name.
|
|
221
|
-
#
|
|
222
|
-
# @param receiver [Symbol, nil] `:entity`, `:aggregate`, or `nil` for a creating
|
|
223
|
-
# command that names no existing record
|
|
224
|
-
# @param aggregate [Bluebook::Aggregate] the aggregate the record belongs to
|
|
225
|
-
# @param entity [Bluebook::Entity, nil] the entity to name, required when
|
|
226
|
-
# `receiver` is `:entity`
|
|
227
|
-
# @return [Array<Hash{Symbol => Object}>] the `to`/`to.aggregate`+`to.entity` option
|
|
228
|
-
# specs this receiver needs, or `[]` for `nil`
|
|
172
|
+
# The options that name the record a verb acts on, before its own arguments.
|
|
173
|
+
# `nil` (a creating command) takes none: there is no record yet.
|
|
174
|
+
# Ports always pass `:aggregate`, since a port is declared on an aggregate.
|
|
229
175
|
def receiver_options(receiver, aggregate, entity)
|
|
230
176
|
case receiver
|
|
231
177
|
when :entity
|
|
@@ -243,20 +189,6 @@ module Hecks
|
|
|
243
189
|
end
|
|
244
190
|
end
|
|
245
191
|
|
|
246
|
-
# ── one verb ──────────────────────────────────────────────────────
|
|
247
|
-
|
|
248
|
-
# Projects one command into the spec `verb_help` and `CliRunner` both read.
|
|
249
|
-
#
|
|
250
|
-
# @param bluebook [Bluebook::Chapter] the command's owning chapter
|
|
251
|
-
# @param aggregate [Bluebook::Aggregate] the command's owning aggregate
|
|
252
|
-
# @param entity [Bluebook::Entity, nil] the entity the command is declared on, or
|
|
253
|
-
# `nil` for an aggregate-level command
|
|
254
|
-
# @param command [Bluebook::Command] the command being projected
|
|
255
|
-
# @return [Hash{Symbol => Object}] `:verb` (fully-qualified name), `:kind` (`:command`),
|
|
256
|
-
# `:summary`, `:role` (String, nil if the command declares none), `:role_gated`
|
|
257
|
-
# (Boolean), `:creates` (Boolean), `:receiver` (`:entity`, `:aggregate` or `nil`),
|
|
258
|
-
# `:legacy_receiver` (`:id` or `nil`), `:legacy_arguments`, `:refusals`
|
|
259
|
-
# (see `refusals`) and `:arguments` (see `options_for`)
|
|
260
192
|
def command_spec(bluebook, aggregate, entity, command)
|
|
261
193
|
holder = entity || aggregate
|
|
262
194
|
arguments = command.attributes.flat_map { |a| options_for(a, holder, aggregate) }
|
|
@@ -266,16 +198,9 @@ module Hecks
|
|
|
266
198
|
(command.creates? ? nil : :aggregate)
|
|
267
199
|
end
|
|
268
200
|
|
|
269
|
-
# The receiver
|
|
270
|
-
#
|
|
271
|
-
#
|
|
272
|
-
# projected option list makes the human-facing request complete while
|
|
273
|
-
# CommandRequest can remove them before it builds with: from the
|
|
274
|
-
# command's declared facts.
|
|
275
|
-
#
|
|
276
|
-
# Existing aggregate scripts may still spell the receiver id=... .
|
|
277
|
-
# That alias is deliberately hidden from help and recorded separately
|
|
278
|
-
# as legacy_arguments; new help and examples teach only to=... .
|
|
201
|
+
# The receiver paths stay in the projected option list so the request is complete;
|
|
202
|
+
# CommandRequest strips them before building `with:`. `id=...` is still accepted
|
|
203
|
+
# for aggregate receivers but hidden from help, which teaches only `to=...`.
|
|
279
204
|
arguments = receiver_options(receiver, aggregate, entity) + arguments
|
|
280
205
|
legacy_arguments = receiver == :aggregate ? [{ path: "id", type: "String", required: true }] : []
|
|
281
206
|
|
|
@@ -284,55 +209,22 @@ module Hecks
|
|
|
284
209
|
creates: command.creates?,
|
|
285
210
|
receiver: receiver, legacy_receiver: (receiver == :aggregate ? :id : nil),
|
|
286
211
|
legacy_arguments: legacy_arguments,
|
|
287
|
-
refusals: refusals(command, holder),
|
|
212
|
+
refusals: refusals(command, holder), requirements: requirements(command),
|
|
213
|
+
arguments: arguments }
|
|
288
214
|
end
|
|
289
215
|
|
|
290
|
-
# A port operation reads as a verb but reports as a boundary
|
|
291
|
-
#
|
|
292
|
-
# `creates: false` because it makes no record, and `refusals: []`
|
|
293
|
-
# because it has none in the sense every other verb means: a command's
|
|
294
|
-
# refusals are sentences the chapter will say back to you, and an
|
|
295
|
-
# outbound operation's failure is somebody else's sentence, unknowable
|
|
296
|
-
# from here.
|
|
297
|
-
#
|
|
298
|
-
# The summary names both endings, which is the one thing a caller most
|
|
299
|
-
# needs and cannot infer. `run_specs` looks like it either works or
|
|
300
|
-
# errors; what it actually does is answer `SpecsCompleted` even when the
|
|
301
|
-
# suite is red, and refuse only when rspec could not run. Somebody
|
|
302
|
-
# reading `--help` should not have to open the hecksagon to find that
|
|
303
|
-
# out.
|
|
304
|
-
#
|
|
305
|
-
# @param bluebook [Bluebook::Chapter] the port's owning chapter
|
|
306
|
-
# @param aggregate [Bluebook::Aggregate] the aggregate the port is declared on
|
|
307
|
-
# @param port [Bluebook::DomainPort] the port the operation is declared on
|
|
308
|
-
# @param operation [Bluebook::PortOperation] the operation being projected
|
|
309
|
-
# @return [Hash{Symbol => Object}] `:verb` (the `Aggregate.port.operation` name),
|
|
310
|
-
# `:kind` (`:command`), `:creates` (`false`), `:receiver` (`:aggregate`),
|
|
311
|
-
# `:refusals` (`[]`), `:role` (String, who calls whom through the port),
|
|
312
|
-
# `:role_gated` (`false`), `:summary` (see `port_summary`) and `:arguments`
|
|
313
|
-
# (see `options_for`)
|
|
216
|
+
# A port operation reads as a verb but reports as a boundary: it creates no
|
|
217
|
+
# record, and an outbound failure is the other side's sentence, so `refusals` is empty.
|
|
314
218
|
def port_spec(bluebook, aggregate, port, operation)
|
|
315
219
|
arguments = receiver_options(:aggregate, aggregate, nil) +
|
|
316
220
|
operation.attributes.flat_map { |a| options_for(a, aggregate, aggregate) }
|
|
317
221
|
|
|
318
|
-
#
|
|
319
|
-
#
|
|
320
|
-
# `Dispatcher#dispatch` splits a verb into head and sub and looks the
|
|
321
|
-
# head up as a port, so a port operation is addressed
|
|
322
|
-
# `Aggregate.Port.Operation` — three parts where a command has two.
|
|
323
|
-
# But nobody should have to type `sweep.toolchain.run_specs`: which
|
|
324
|
-
# port a verb goes out through is wiring, and the caller's business is
|
|
325
|
-
# what they want done. So the projection spells the verb in full and
|
|
326
|
-
# names it short, which is the same split `shorten` already makes.
|
|
222
|
+
# `Dispatcher#dispatch` looks the head up as a port, so the wire name is
|
|
223
|
+
# `Aggregate.Port.Operation`; the short name (see `shorten`) hides the port.
|
|
327
224
|
{ verb: [fqn(bluebook, aggregate, operation).sub(/\.[^.]+\z/, ""), port.name, operation.hecks_name].join("."),
|
|
328
225
|
kind: :command, creates: false, receiver: :aggregate, refusals: [],
|
|
329
|
-
# `role:`
|
|
330
|
-
#
|
|
331
|
-
# "issued by" line. A port operation never reaches
|
|
332
|
-
# `CommandRules::Authorization#refuse_role_mismatch` (only
|
|
333
|
-
# `CommandInterpreter`/`EntityInterpreter` call it, never the port
|
|
334
|
-
# dispatch path), so `role_gated: false` always, unlike
|
|
335
|
-
# `command_spec` where the same key name means a real one.
|
|
226
|
+
# `role:` is help text only; port dispatch never reaches the role check,
|
|
227
|
+
# so `role_gated` is always false here.
|
|
336
228
|
role: if operation.outbound?
|
|
337
229
|
"#{aggregate.hecks_name} asking #{port.name}"
|
|
338
230
|
else
|
|
@@ -342,26 +234,16 @@ module Hecks
|
|
|
342
234
|
summary: port_summary(port, operation), arguments: arguments }
|
|
343
235
|
end
|
|
344
236
|
|
|
345
|
-
# Names both endings a port operation
|
|
346
|
-
#
|
|
347
|
-
#
|
|
348
|
-
# @param port [Bluebook::DomainPort] the operation's owning port
|
|
349
|
-
# @param operation [Bluebook::PortOperation] the operation being summarized
|
|
350
|
-
# @return [String] one line, worded for `--help`
|
|
237
|
+
# Names both endings of a port operation, since `--help` is where a caller
|
|
238
|
+
# learns that e.g. a spec run answers `SpecsCompleted` even when the suite is red.
|
|
351
239
|
def port_summary(port, operation)
|
|
352
240
|
return "#{port.name} reports it; emits #{operation.emits.join(', ')}" unless operation.outbound?
|
|
353
241
|
|
|
354
242
|
"Ask #{port.name} — answers #{operation.answers}, refuses #{operation.refuses}"
|
|
355
243
|
end
|
|
356
244
|
|
|
357
|
-
# A rootless report takes nothing; a rooted one takes the id of the
|
|
358
|
-
#
|
|
359
|
-
#
|
|
360
|
-
# @param bluebook [Bluebook::Chapter] the report's owning chapter
|
|
361
|
-
# @param model [Bluebook::ReadModel] the report being projected
|
|
362
|
-
# @return [Hash{Symbol => Object}] `:verb` (`Chapter.ReportName`), `:kind`
|
|
363
|
-
# (`:query`), `:summary` and `:arguments` (`[]`, or one required id option
|
|
364
|
-
# named after the model's `reference_name` when it declares a `reference_target`)
|
|
245
|
+
# A rootless report takes nothing; a rooted one takes the id of the record it
|
|
246
|
+
# is a view of, under the name the model gave that reference.
|
|
365
247
|
def report_spec(bluebook, model)
|
|
366
248
|
arguments =
|
|
367
249
|
if model.reference_target
|
|
@@ -375,15 +257,6 @@ module Hecks
|
|
|
375
257
|
summary: model.description, arguments: arguments }
|
|
376
258
|
end
|
|
377
259
|
|
|
378
|
-
# Projects one query into the spec `verb_help` and `CliRunner` both read.
|
|
379
|
-
#
|
|
380
|
-
# @param bluebook [Bluebook::Chapter] the query's owning chapter
|
|
381
|
-
# @param aggregate [Bluebook::Aggregate] the query's owning aggregate
|
|
382
|
-
# @param entity [Bluebook::Entity, nil] the entity the query is declared on, or
|
|
383
|
-
# `nil` for an aggregate-level query
|
|
384
|
-
# @param query [Bluebook::Query] the query being projected
|
|
385
|
-
# @return [Hash{Symbol => Object}] `:verb` (fully-qualified name), `:kind`
|
|
386
|
-
# (`:query`), `:summary` and `:arguments` (see `options_for`)
|
|
387
260
|
def query_spec(bluebook, aggregate, entity, query)
|
|
388
261
|
arguments = Array(query.to_h[:attributes]).flat_map do |declared|
|
|
389
262
|
attribute = query.attributes.find { |a| a.name.to_s == declared[:name].to_s }
|
|
@@ -391,38 +264,19 @@ module Hecks
|
|
|
391
264
|
end
|
|
392
265
|
|
|
393
266
|
{ verb: fqn(bluebook, aggregate, query, entity), kind: :query,
|
|
394
|
-
summary: query.description, arguments: arguments }
|
|
267
|
+
summary: query.description, arguments: arguments, returns: query.returns }
|
|
395
268
|
end
|
|
396
269
|
|
|
397
|
-
#
|
|
398
|
-
|
|
399
|
-
#
|
|
400
|
-
# `CommitRef` is `--commit.value`, because that is the shape the runtime
|
|
401
|
-
# wants and a flat `--commit` would have to guess which field it meant.
|
|
402
|
-
# Single-field value objects — almost all of them — read fine either way,
|
|
403
|
-
# and the runner accepts the short form for exactly those.
|
|
404
|
-
# Recursive, and it has to be. A value object may hold another one —
|
|
405
|
-
# pizzas' `Pizza` holds a `Price` and a `Size` — so stopping after one
|
|
406
|
-
# level produced `pizza.price_cents=1500` and sent the string "1500"
|
|
407
|
-
# where `{ cents: 1500 }` belonged.
|
|
408
|
-
#
|
|
409
|
-
# The runtime took it. `qa/FINDINGS.md` #2 is exactly that gap —
|
|
410
|
-
# `Value::Coercion.build` does not validate nested value objects — so a
|
|
411
|
-
# one-level CLI is not merely inconvenient, it is a machine for writing
|
|
412
|
-
# malformed records into a real store, which is what it did on its first
|
|
413
|
-
# run against the pizzas database.
|
|
270
|
+
# Flattens an attribute into one option per leaf field. A value object becomes
|
|
271
|
+
# dotted options (`--commit.value`), recursing into nested value objects so
|
|
272
|
+
# `{ cents: 1500 }` is never sent as the string "1500".
|
|
414
273
|
#
|
|
415
274
|
# @param attribute [Bluebook::Attribute] the field being projected
|
|
416
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity, Class]
|
|
417
|
-
# `attribute` is declared on; a `Bluebook::ValueObject` subclass on a recursive call
|
|
275
|
+
# @param holder [Bluebook::Aggregate, Bluebook::Entity, Class] what declares `attribute`
|
|
418
276
|
# @param aggregate [Bluebook::Aggregate] the top-level aggregate, kept across recursion
|
|
419
|
-
#
|
|
420
|
-
# @param
|
|
421
|
-
# @
|
|
422
|
-
# optional; `nil` defers to `attribute.optional?`
|
|
423
|
-
# @return [Array<Hash{Symbol => Object}>] one option spec per leaf field, each with
|
|
424
|
-
# `:path`, `:type`, `:required`, and optionally `:note`, `:enum`, `:pattern`,
|
|
425
|
-
# `:default`, `:list`
|
|
277
|
+
# @param prefix [String, nil] the dotted path built so far
|
|
278
|
+
# @param optional [Boolean, nil] whether an enclosing field already makes this one optional
|
|
279
|
+
# @return [Array<Hash{Symbol => Object}>] one option spec per leaf field
|
|
426
280
|
def options_for(attribute, holder, aggregate, prefix = nil, optional = nil)
|
|
427
281
|
path = [prefix, attribute.name].compact.join(".")
|
|
428
282
|
optional ||= attribute.optional?
|
|
@@ -431,19 +285,8 @@ module Hecks
|
|
|
431
285
|
value_object = value_object_for(attribute, holder, aggregate)
|
|
432
286
|
return [scalar_option(path, attribute, optional)] unless value_object
|
|
433
287
|
|
|
434
|
-
#
|
|
435
|
-
#
|
|
436
|
-
# Without this a `list_of(Tag)` projected exactly like a single Tag:
|
|
437
|
-
# one option, `tags.value`, indistinguishable from a scalar. So the
|
|
438
|
-
# help said to pass one, `CliDoor#bury` overwrote the leaf each time,
|
|
439
|
-
# and passing two tags stored the second and lost the first without
|
|
440
|
-
# saying anything. A missing argument is refused loudly; a forgotten
|
|
441
|
-
# one is not, which makes it the more expensive of the two by far.
|
|
442
|
-
#
|
|
443
|
-
# The flag is carried on the leaf rather than kept beside the
|
|
444
|
-
# attribute because the leaf is all `CliDoor` ever sees — it is handed
|
|
445
|
-
# a path and a spec, and reuniting them with the attribute that
|
|
446
|
-
# produced them would be a lookup that exists only to answer this.
|
|
288
|
+
# The list flag rides on each leaf: without it a repeated flag overwrote the
|
|
289
|
+
# leaf silently, and CliDoor only ever sees a path and a spec.
|
|
447
290
|
fields = value_object.attributes.flat_map do |field|
|
|
448
291
|
nested = value_object_for(field, value_object, aggregate)
|
|
449
292
|
next options_for(field, value_object, aggregate, path, optional) if nested
|
|
@@ -457,59 +300,31 @@ module Hecks
|
|
|
457
300
|
fields.map { |option| option.merge(list: true, note: [option[:note], "repeatable"].compact.join("; ")) }
|
|
458
301
|
end
|
|
459
302
|
|
|
460
|
-
# Projects a `reference_to` attribute as the id of the record it points at.
|
|
461
|
-
#
|
|
462
|
-
# @param attribute [Bluebook::Attribute] a `reference?` attribute
|
|
463
|
-
# @return [Hash{Symbol => Object}] `:path`, `:type` (`"String"`), `:required` and
|
|
464
|
-
# `:note`
|
|
465
303
|
def reference_option(attribute)
|
|
466
304
|
{ path: attribute.name.to_s, type: "String", required: !attribute.optional?,
|
|
467
305
|
note: "id of a #{attribute.type.target_name}" }
|
|
468
306
|
end
|
|
469
307
|
|
|
470
|
-
#
|
|
471
|
-
# value
|
|
472
|
-
#
|
|
473
|
-
# @param path [String] the dotted option path this field is reached at
|
|
474
|
-
# @param field [Bluebook::Attribute] the field being projected
|
|
475
|
-
# @param optional [Boolean] whether this option may be omitted
|
|
476
|
-
# @param enum [Array<Object>] the closed set of values this field admits, `[]` for
|
|
477
|
-
# an open field
|
|
478
|
-
# @return [Hash{Symbol => Object}] `:path`, `:type`, `:required`, plus `:enum` when
|
|
479
|
-
# `enum` is non-empty, `:pattern` when `field` declares one, and `:default` when
|
|
480
|
-
# `field` declares a non-nil one
|
|
308
|
+
# A `list_of` scalar carries `list: true, words: true`: the launcher reads a comma-separated
|
|
309
|
+
# value or a repeated name as the list's elements, since the runtime refuses a lone scalar.
|
|
481
310
|
def scalar_option(path, field, optional, enum: [])
|
|
482
311
|
option = { path: path, type: field.type.to_s, required: !optional }
|
|
312
|
+
option.merge!(list: true, words: true, note: "list: comma-separated or repeated") if field.list?
|
|
483
313
|
option[:enum] = enum unless enum.empty?
|
|
484
314
|
option[:pattern] = field.pattern if field.respond_to?(:pattern) && field.pattern
|
|
485
315
|
option[:default] = field.default if field.respond_to?(:default) && !field.default.nil?
|
|
486
316
|
option
|
|
487
317
|
end
|
|
488
318
|
|
|
489
|
-
# The values a `one_of` value object's field is closed to, for
|
|
490
|
-
# `:enum`.
|
|
491
|
-
#
|
|
492
|
-
# @param value_object [Class] a `Bluebook::ValueObject` subclass
|
|
493
|
-
# @param field [Bluebook::Attribute] the value object's field being projected
|
|
494
|
-
# @return [Array<Object>] the distinct values every declared member gives this
|
|
495
|
-
# field, or `[]` when the value object declares no closed set
|
|
319
|
+
# The values a `one_of` value object's field is closed to, or `[]` for an open one.
|
|
496
320
|
def closed_members(value_object, field)
|
|
497
321
|
return [] unless value_object.closed_set?
|
|
498
322
|
|
|
499
323
|
value_object.members.filter_map { |member| member[field.name] }.uniq
|
|
500
324
|
end
|
|
501
325
|
|
|
502
|
-
#
|
|
503
|
-
# `
|
|
504
|
-
# field).
|
|
505
|
-
#
|
|
506
|
-
# @param attribute [Bluebook::Attribute] the field whose type is being resolved
|
|
507
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity, Class, nil] the construct
|
|
508
|
-
# `attribute` is declared on, searched first
|
|
509
|
-
# @param aggregate [Bluebook::Aggregate, nil] the top-level aggregate, searched when
|
|
510
|
-
# `holder` does not declare the value object itself
|
|
511
|
-
# @return [Class, nil] the matching `Bluebook::ValueObject` subclass, or `nil` if
|
|
512
|
-
# `attribute`'s type names no value object in scope
|
|
326
|
+
# The `Bluebook::ValueObject` subclass an attribute's type names, searching
|
|
327
|
+
# `holder` then `aggregate`, or `nil` for a plain scalar.
|
|
513
328
|
def value_object_for(attribute, holder, aggregate)
|
|
514
329
|
[holder, aggregate].compact.each do |scope|
|
|
515
330
|
next unless scope.respond_to?(:value_objects)
|
|
@@ -520,15 +335,8 @@ module Hecks
|
|
|
520
335
|
nil
|
|
521
336
|
end
|
|
522
337
|
|
|
523
|
-
#
|
|
524
|
-
#
|
|
525
|
-
#
|
|
526
|
-
# @param command [Bluebook::Command] the command whose refusals are being projected
|
|
527
|
-
# @param holder [Bluebook::Aggregate, Bluebook::Entity] the aggregate or entity the
|
|
528
|
-
# command's lifecycle guard, if any, is checked against
|
|
529
|
-
# @return [Array<String>] one sentence per way the command can refuse: a lifecycle
|
|
530
|
-
# state mismatch, a missing referenced record per `reference_to` attribute, and
|
|
531
|
-
# each declared `given`'s description, in that order
|
|
338
|
+
# The conditions that refuse the verb when they hold, in the chapter's own words: a
|
|
339
|
+
# lifecycle state mismatch and a missing referenced record per `reference_to`.
|
|
532
340
|
def refusals(command, holder)
|
|
533
341
|
out = []
|
|
534
342
|
lifecycle = holder.lifecycle
|
|
@@ -537,28 +345,21 @@ module Hecks
|
|
|
537
345
|
end.flatten.uniq
|
|
538
346
|
out << "#{lifecycle.field} is not #{froms.join(' or ')}" if froms && !froms.empty?
|
|
539
347
|
out += command.attributes.select(&:reference?).map { |r| "no #{r.type.target_name} has that #{r.name}" }
|
|
540
|
-
out
|
|
348
|
+
out
|
|
541
349
|
end
|
|
542
350
|
|
|
543
|
-
#
|
|
351
|
+
# The conditions the verb needs: each `given` states what must hold, so the verb is
|
|
352
|
+
# refused unless it does.
|
|
353
|
+
def requirements(command) = command.givens.map(&:description)
|
|
544
354
|
|
|
545
355
|
# Renders the full verb/question table, or one verb's `--help` text when
|
|
546
356
|
# `options[:verb]` names one.
|
|
547
|
-
#
|
|
548
|
-
# @param bluebook [Bluebook::Chapter] the projected chapter, for its name and vision
|
|
549
|
-
# line
|
|
550
|
-
# @param verbs [Hash{String => Hash}] the projected, `shorten`ed command map
|
|
551
|
-
# @param questions [Hash{String => Hash}] the projected, `shorten`ed query map
|
|
552
|
-
# @param options [Hash{Symbol => Object}] `:program` (String), `:verb` (String, nil)
|
|
553
|
-
# and `:ask` (Boolean) — see `call`
|
|
554
|
-
# @return [String] the rendered help text
|
|
555
357
|
def usage(bluebook, verbs, questions, options)
|
|
556
|
-
program = options[:program] || "
|
|
358
|
+
program = options[:program] || "hecks run"
|
|
557
359
|
only = options[:verb]
|
|
558
360
|
|
|
559
|
-
#
|
|
560
|
-
#
|
|
561
|
-
# shares its name, which banking has and which is how this was found.
|
|
361
|
+
# `options[:ask]` picks the namespace when both hold the name; without it a
|
|
362
|
+
# question's `--help` would print the command sharing its name.
|
|
562
363
|
if only
|
|
563
364
|
pool = options[:ask] ? questions : verbs
|
|
564
365
|
key = aliases(pool)[only] || (options[:ask] ? nil : aliases(questions)[only])
|
|
@@ -582,40 +383,19 @@ module Hecks
|
|
|
582
383
|
out.join("\n")
|
|
583
384
|
end
|
|
584
385
|
|
|
585
|
-
#
|
|
586
|
-
# caller both forms exist.
|
|
587
|
-
#
|
|
588
|
-
# @param verbs [Hash{String => Hash}] the projected, `shorten`ed command map
|
|
589
|
-
# @return [String] `"<short> is also <full>"`, or `""` if every verb's short form
|
|
590
|
-
# is its full name (a one-aggregate domain, where no name ever collides)
|
|
386
|
+
# One verb whose full spelling differs from its short one, or `""` when none does.
|
|
591
387
|
def example_qualified(verbs)
|
|
592
388
|
name, spec = verbs.find { |key, value| key != value[:short] } || verbs.first
|
|
593
389
|
name ? "#{spec[:short]} is also #{name}" : ""
|
|
594
390
|
end
|
|
595
391
|
|
|
596
|
-
#
|
|
597
|
-
# the list is worth reading. A verb table wants the first sentence of
|
|
598
|
-
# that argument; `--help` still prints the whole thing.
|
|
599
|
-
#
|
|
600
|
-
# @param text [String, nil] the full description, or `nil`
|
|
601
|
-
# @return [String] the text up to and including its first `.`, or `""` for `nil`
|
|
392
|
+
# The verb table wants a query description's first sentence; `--help` prints all.
|
|
602
393
|
def first_sentence(text)
|
|
603
394
|
text.to_s.split(/(?<=\.)\s/).first.to_s
|
|
604
395
|
end
|
|
605
396
|
|
|
606
|
-
# Four
|
|
607
|
-
#
|
|
608
|
-
# others' content (only the output order is fixed, and stays fixed
|
|
609
|
-
# below), so each is its own method returning the lines it
|
|
610
|
-
# contributes — `[]` when it contributes none — concatenated in the
|
|
611
|
-
# same order the original inline version built them in.
|
|
612
|
-
#
|
|
613
|
-
# @param program [String] how the caller was invoked, echoed in the invocation line
|
|
614
|
-
# @param name [String] the verb's short display name
|
|
615
|
-
# @param spec [Hash{Symbol => Object}] the verb or question's projected spec (see
|
|
616
|
-
# `command_spec`, `port_spec`, `report_spec` or `query_spec`)
|
|
617
|
-
# @param ask [Boolean] whether this is a question, reached through `ask`
|
|
618
|
-
# @return [String] the verb's full `--help` text
|
|
397
|
+
# Four independent blocks, concatenated in fixed order: meta, invocation,
|
|
398
|
+
# arguments, refusals.
|
|
619
399
|
def verb_help(program, name, spec, ask: false)
|
|
620
400
|
out = verb_help_meta_lines(name, spec)
|
|
621
401
|
out.concat(verb_help_invocation_lines(program, name, spec, ask))
|
|
@@ -624,12 +404,6 @@ module Hecks
|
|
|
624
404
|
out.join("\n")
|
|
625
405
|
end
|
|
626
406
|
|
|
627
|
-
# Renders the name/summary heading, plus the dispatched or read verb and issuing
|
|
628
|
-
# role when the spec declares them.
|
|
629
|
-
#
|
|
630
|
-
# @param name [String] the verb's short display name
|
|
631
|
-
# @param spec [Hash{Symbol => Object}] the verb or question's projected spec
|
|
632
|
-
# @return [Array<String>] the meta block's lines
|
|
633
407
|
def verb_help_meta_lines(name, spec)
|
|
634
408
|
out = ["#{name} — #{spec[:summary]}", ""]
|
|
635
409
|
out << "dispatches #{spec[:verb]}" if spec[:kind] == :command
|
|
@@ -638,26 +412,11 @@ module Hecks
|
|
|
638
412
|
out
|
|
639
413
|
end
|
|
640
414
|
|
|
641
|
-
# Renders the one-line example invocation, with every argument's path as a
|
|
642
|
-
# placeholder.
|
|
643
|
-
#
|
|
644
|
-
# @param program [String] how the caller was invoked
|
|
645
|
-
# @param name [String] the verb's short display name
|
|
646
|
-
# @param spec [Hash{Symbol => Object}] the verb or question's projected spec, read
|
|
647
|
-
# for `:arguments`
|
|
648
|
-
# @param ask [Boolean] whether to show the `ask` form of the invocation
|
|
649
|
-
# @return [Array<String>] the invocation block's lines
|
|
650
415
|
def verb_help_invocation_lines(program, name, spec, ask)
|
|
651
416
|
invocation = ask ? "#{program} ask #{name}" : "#{program} #{name}"
|
|
652
417
|
["", " #{invocation}#{spec[:arguments].map { |a| " #{a[:path]}=…" }.join}", ""]
|
|
653
418
|
end
|
|
654
419
|
|
|
655
|
-
# Renders one line per declared argument: its type, admitted values, pattern,
|
|
656
|
-
# default and whether it is optional.
|
|
657
|
-
#
|
|
658
|
-
# @param spec [Hash{Symbol => Object}] the verb or question's projected spec, read
|
|
659
|
-
# for `:arguments`
|
|
660
|
-
# @return [Array<String>] the argument block's lines, `[]` if the verb takes none
|
|
661
420
|
def verb_help_argument_lines(spec)
|
|
662
421
|
return [] if spec[:arguments].empty?
|
|
663
422
|
|
|
@@ -675,15 +434,10 @@ module Hecks
|
|
|
675
434
|
lines << ""
|
|
676
435
|
end
|
|
677
436
|
|
|
678
|
-
# Renders the "refused when:" block, one line per way the verb can say no.
|
|
679
|
-
#
|
|
680
|
-
# @param spec [Hash{Symbol => Object}] the verb or question's projected spec, read
|
|
681
|
-
# for `:refusals`
|
|
682
|
-
# @return [Array<String>] the refusal block's lines, `[]` if the verb declares none
|
|
683
437
|
def verb_help_refusal_lines(spec)
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
438
|
+
[["refused when:", spec[:refusals]], ["refused unless:", spec[:requirements]]].flat_map do |heading, items|
|
|
439
|
+
Array(items).empty? ? [] : [heading, *items.map { |item| " #{item}" }, ""]
|
|
440
|
+
end
|
|
687
441
|
end
|
|
688
442
|
end
|
|
689
443
|
end
|