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
|
@@ -1,59 +1,20 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
require_relative "../../hecks"
|
|
3
|
-
require_relative "mcp"
|
|
3
|
+
require_relative "../cli/mcp"
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
|
-
module
|
|
7
|
-
# The MCP door onto the storehouse bus:
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
module Doors
|
|
7
|
+
# The MCP door onto the storehouse bus: hand-rolled JSON-RPC over stdio, one
|
|
8
|
+
# server per booted domain. All logic and the JSON shape answered with live in
|
|
9
|
+
# `Storehouse`; this is plumbing only. A `role:`/`actor_id:` a caller sends is
|
|
10
|
+
# asserted, not verified, unless Governance is attached.
|
|
10
11
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# ## Identity is asserted, not verified
|
|
19
|
-
#
|
|
20
|
-
# `dispatch` and `query` take `role:` and `actor_id:`, bound for the call through
|
|
21
|
-
# `Hecks.as_caller`, so a role-gated command is checked against them rather than
|
|
22
|
-
# merely documented by `describe`; `dispatch` refuses a role-declaring command
|
|
23
|
-
# called without one. Nothing here verifies the claim beyond the string (or, with
|
|
24
|
-
# Governance attached, a `Governance::RoleAssignment` lookup). The readers take
|
|
25
|
-
# no role, and `query` gates on none.
|
|
26
|
-
#
|
|
27
|
-
# ## Stdio only, enforced
|
|
28
|
-
#
|
|
29
|
-
# The door has no authentication. `Mcp.call` runs
|
|
30
|
-
# `McpStdioGuard.enforce_stdio!` before this file loads, and `serve` prints the
|
|
31
|
-
# warning to stderr, never stdout, which carries the protocol. `domain:` is
|
|
32
|
-
# confined to `Storehouse::BOOT_ROOT` (`confine!`), but a domain within that
|
|
33
|
-
# root still boots real Ruby, so this is a code execution surface for anyone who
|
|
34
|
-
# can write to stdin. A network transport needs authentication first; see
|
|
35
|
-
# `docs/decisions/0062-mcp-servers-need-real-authentication-before-any-network-transport.md`.
|
|
36
|
-
#
|
|
37
|
-
# ## Reader mode
|
|
38
|
-
#
|
|
39
|
-
# Whoever spawns the door can narrow it with `HECKS_DOOR_TOOLS=readers` and
|
|
40
|
-
# `HECKS_DOOR_DOMAINS=<dir>[:<dir>...]` (`Hecks::McpDoorScope`, ADR 0072 decision 2).
|
|
41
|
-
# A reader door serves only `McpDoorScope::READER_TOOLS` (`query`, `events`,
|
|
42
|
-
# `state`, `catalog`, `describe`, `validate`, `domains`, `history`, `follow`), lists
|
|
43
|
-
# only those in `tools/list`, and refuses `dispatch` (so `dry_run` and `steps` too),
|
|
44
|
-
# `behaviors` and any other name with an answer that names the mode. Its `domain:`
|
|
45
|
-
# must resolve to one of the named directories, checked before anything boots, so no
|
|
46
|
-
# other domain's Ruby is loaded. The door keeps no domain loaded between calls, so
|
|
47
|
-
# the named list is the whole allowed set. This limits what one spawned agent can
|
|
48
|
-
# reach; it identifies no one and is not authentication. The names sit outside
|
|
49
|
-
# `HECKS_MCP_*` because the stdio guard refuses every name in that prefix but the
|
|
50
|
-
# transport, and that refusal belongs to ADR 0062. With neither variable set, the
|
|
51
|
-
# door serves every tool as described above.
|
|
52
|
-
#
|
|
53
|
-
# ## One boot per call
|
|
54
|
-
#
|
|
55
|
-
# `Hecks.boot(domain, install_facade: false)` is cheap, and it lets one server
|
|
56
|
-
# answer calls against two domains back to back with no shared, staling state.
|
|
12
|
+
# There is no authentication: `domain:` boots real Ruby confined to
|
|
13
|
+
# `Storehouse::BOOT_ROOT`, so this is a code execution surface for anyone who
|
|
14
|
+
# can write to stdin (ADR 0062). Spawning with `HECKS_DOOR_TOOLS=readers` and
|
|
15
|
+
# `HECKS_DOOR_DOMAINS=<dir>[:<dir>...]` narrows a door to read-only tools and
|
|
16
|
+
# named domains (`McpDoorScope`); this limits what one agent can reach and is
|
|
17
|
+
# not itself authentication.
|
|
57
18
|
module McpDoor
|
|
58
19
|
PROTOCOL_VERSION = "2024-11-05".freeze
|
|
59
20
|
|
|
@@ -271,29 +232,19 @@ module Hecks
|
|
|
271
232
|
|
|
272
233
|
module_function
|
|
273
234
|
|
|
274
|
-
#
|
|
275
|
-
#
|
|
276
|
-
# so a bad setting refuses to start the door before anything is written to stdout.
|
|
277
|
-
#
|
|
278
|
-
# @return [McpDoorScope]
|
|
235
|
+
# Read once, so a bad setting refuses to start the door before anything is
|
|
236
|
+
# written to stdout.
|
|
279
237
|
def scope
|
|
280
|
-
@scope ||= McpDoorScope.start!(server: Mcp::SERVER)
|
|
238
|
+
@scope ||= McpDoorScope.start!(server: CLI::Mcp::SERVER)
|
|
281
239
|
end
|
|
282
240
|
|
|
283
|
-
# The
|
|
284
|
-
# scope says about `domain:`.
|
|
285
|
-
#
|
|
286
|
-
# @return [Array<String>]
|
|
241
|
+
# The standing notes, then what this door's scope says about `domain:`.
|
|
287
242
|
def warning_notes
|
|
288
243
|
NOTES[0, 2] + (scope.restricted? ? scope.notes : [NOTES[2]])
|
|
289
244
|
end
|
|
290
245
|
|
|
291
|
-
# Prints the stdio warning to stderr, then answers one JSON-RPC request per
|
|
292
|
-
# line of `$stdin` until it closes.
|
|
293
|
-
#
|
|
294
|
-
# @return [void]
|
|
295
246
|
def serve
|
|
296
|
-
McpStdioGuard.warn!(server: Mcp::SERVER, notes: warning_notes)
|
|
247
|
+
McpStdioGuard.warn!(server: CLI::Mcp::SERVER, notes: warning_notes)
|
|
297
248
|
$stdout.sync = true
|
|
298
249
|
|
|
299
250
|
$stdin.each_line do |line|
|
|
@@ -315,29 +266,14 @@ module Hecks
|
|
|
315
266
|
end
|
|
316
267
|
end
|
|
317
268
|
|
|
318
|
-
#
|
|
319
|
-
#
|
|
320
|
-
# @param domain [String] the domain directory, e.g. `"examples/banking"`
|
|
321
|
-
# @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted domain
|
|
322
|
-
# @raise [Runtime::TypeMismatch] if `domain` resolves outside `Storehouse::BOOT_ROOT`, or,
|
|
323
|
-
# on a reader door, outside `HECKS_DOOR_DOMAINS`
|
|
324
|
-
# @raise [Runtime::WiringError] if the domain fails to boot
|
|
269
|
+
# `domain:` is confined to `Storehouse::BOOT_ROOT`, and further to a reader
|
|
270
|
+
# door's `HECKS_DOOR_DOMAINS`, before anything boots.
|
|
325
271
|
def boot(domain)
|
|
326
|
-
Hecks.boot(Storehouse.confine!(scope.admit_domain!(domain), "domain"),
|
|
272
|
+
Hecks.boot(Storehouse.confine!(scope.admit_domain!(domain), "domain"), install_doors: false)
|
|
327
273
|
end
|
|
328
274
|
|
|
329
|
-
#
|
|
330
|
-
#
|
|
331
|
-
# A closed-set dispatch table, one `when` per tool, so the size is the tool
|
|
332
|
-
# count and the shared `rescue` catches every branch's escape once.
|
|
333
|
-
#
|
|
334
|
-
# @param name [String] the tool name, one of `TOOLS`'s own `:name` values
|
|
335
|
-
# @param args [Hash{String => Object}] the tool's JSON arguments, shaped per that
|
|
336
|
-
# tool's `inputSchema`
|
|
337
|
-
# @return [Hash{Symbol => Object}] the delegated `Storehouse` result on a known
|
|
338
|
-
# tool name; `{ok: false, error: String}` for an unknown tool name or any
|
|
339
|
-
# `StandardError` this door did not anticipate (a domain refusal is already
|
|
340
|
-
# `{ok: false, ...}` from inside `Storehouse` itself)
|
|
275
|
+
# One `when` per tool, so the shared `rescue` catches every branch's escape
|
|
276
|
+
# once; a domain refusal is already `{ok: false, ...}` from `Storehouse`.
|
|
341
277
|
def call_tool(name, args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
342
278
|
case name
|
|
343
279
|
when "dispatch"
|
|
@@ -378,60 +314,29 @@ module Hecks
|
|
|
378
314
|
{ ok: false, error: "no such tool: #{name.inspect} — known: #{TOOLS.map { |t| t[:name] }.join(', ')}" }
|
|
379
315
|
end
|
|
380
316
|
rescue StandardError => e
|
|
381
|
-
#
|
|
382
|
-
#
|
|
383
|
-
# domain path or an argument shape `Facade::JsonDoor` could not symbolize,
|
|
384
|
-
# still answered as structured content rather than an MCP-level `isError`,
|
|
385
|
-
# so a calling agent reads one shape for every outcome.
|
|
317
|
+
# A defect, not a refusal: reaching here means a bad domain path or an
|
|
318
|
+
# argument shape `Doors::JsonDoor` could not symbolize.
|
|
386
319
|
{ ok: false, error: "#{e.class}: #{e.message}" }
|
|
387
320
|
end
|
|
388
321
|
|
|
389
|
-
# Runs one MCP tool call if this door's mode serves it, and refuses it otherwise.
|
|
390
|
-
#
|
|
391
|
-
# @param name [String] the tool name from the `tools/call` request
|
|
392
|
-
# @param args [Hash{String => Object}] the tool's JSON arguments
|
|
393
|
-
# @return [Hash{Symbol => Object}] the `call_tool` result, or `scope.refusal(name)`
|
|
394
|
-
# when a reader door does not serve `name`
|
|
395
322
|
def answer_tool(name, args)
|
|
396
323
|
return scope.refusal(name) unless scope.permits_tool?(name)
|
|
397
324
|
|
|
398
325
|
call_tool(name, args)
|
|
399
326
|
end
|
|
400
327
|
|
|
401
|
-
# Wraps a `call_tool` payload in the MCP `tools/call` result shape.
|
|
402
|
-
#
|
|
403
|
-
# @param payload [Hash{Symbol => Object}] a `call_tool` result
|
|
404
|
-
# @return [Hash{Symbol => Object}] `{content: [{type: "text", text: ...}], isError: Boolean}`,
|
|
405
|
-
# pretty-printing `payload` as the text and setting `isError` from `payload[:ok]`
|
|
406
328
|
def tool_result(payload)
|
|
407
329
|
{ content: [{ type: "text", text: JSON.pretty_generate(payload) }], isError: payload[:ok] == false }
|
|
408
330
|
end
|
|
409
331
|
|
|
410
|
-
# Writes one JSON-RPC success response line to stdout.
|
|
411
|
-
#
|
|
412
|
-
# @param id [String, Integer, nil] the request's own `id`, echoed back
|
|
413
|
-
# @param result [Object] the JSON-serializable result payload
|
|
414
|
-
# @return [void]
|
|
415
332
|
def send_response(id, result)
|
|
416
333
|
puts JSON.generate({ jsonrpc: "2.0", id: id, result: result })
|
|
417
334
|
end
|
|
418
335
|
|
|
419
|
-
# Writes one JSON-RPC error response line to stdout.
|
|
420
|
-
#
|
|
421
|
-
# @param id [String, Integer, nil] the request's own `id`, echoed back; nil when
|
|
422
|
-
# the request itself could not be parsed
|
|
423
|
-
# @param code [Integer] the JSON-RPC error code
|
|
424
|
-
# @param message [String] the error message
|
|
425
|
-
# @return [void]
|
|
426
336
|
def send_error(id, code, message)
|
|
427
337
|
puts JSON.generate({ jsonrpc: "2.0", id: id, error: { code: code, message: message } })
|
|
428
338
|
end
|
|
429
339
|
|
|
430
|
-
# Dispatches one parsed JSON-RPC request to its method and writes the response.
|
|
431
|
-
#
|
|
432
|
-
# @param request [Hash{String => Object}] one parsed JSON-RPC request, with
|
|
433
|
-
# `"id"`, `"method"`, and optional `"params"`
|
|
434
|
-
# @return [void]
|
|
435
340
|
def handle(request)
|
|
436
341
|
id = request["id"]
|
|
437
342
|
method = request["method"]
|
|
@@ -442,7 +347,7 @@ module Hecks
|
|
|
442
347
|
send_response(id, {
|
|
443
348
|
protocolVersion: PROTOCOL_VERSION,
|
|
444
349
|
capabilities: { tools: {} },
|
|
445
|
-
serverInfo: { name: Mcp::SERVER, version: "1.1.0" }
|
|
350
|
+
serverInfo: { name: CLI::Mcp::SERVER, version: "1.1.0" }
|
|
446
351
|
})
|
|
447
352
|
when "notifications/initialized"
|
|
448
353
|
nil # a notification — no id, no response
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require_relative "../runtime/errors"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Doors
|
|
5
|
+
# What a spawned hecks mcp may do: every tool by default, or only
|
|
6
|
+
# reader tools against named domains in reader mode — reach, not identity (ADR 0072).
|
|
7
|
+
class McpDoorScope
|
|
8
|
+
ENV_PREFIX = "HECKS_DOOR_".freeze
|
|
9
|
+
TOOLS_VARIABLE = "HECKS_DOOR_TOOLS".freeze
|
|
10
|
+
DOMAINS_VARIABLE = "HECKS_DOOR_DOMAINS".freeze
|
|
11
|
+
READERS = "readers".freeze
|
|
12
|
+
EXIT_STATUS = 2
|
|
13
|
+
|
|
14
|
+
# The tools a reader door serves — each reads a domain or the door's own
|
|
15
|
+
# audit log and writes no domain state. `validate` still boots its
|
|
16
|
+
# domain, so it stays bound to the allowed set like every other tool.
|
|
17
|
+
READER_TOOLS = %w[query events state catalog describe validate domains history follow].freeze
|
|
18
|
+
|
|
19
|
+
# Unrestricted when no HECKS_DOOR_* variable is set.
|
|
20
|
+
def self.from_env(env = ENV)
|
|
21
|
+
problems = setting_problems(env)
|
|
22
|
+
raise ArgumentError, problems.join("\n") unless problems.empty?
|
|
23
|
+
return new(allowed_domains: nil) unless env[TOOLS_VARIABLE]
|
|
24
|
+
|
|
25
|
+
new(allowed_domains: env[DOMAINS_VARIABLE].split(File::PATH_SEPARATOR).reject(&:empty?))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Refuses to stderr, not stdout, which carries the MCP protocol.
|
|
29
|
+
def self.start!(server:, env: ENV, stderr: $stderr)
|
|
30
|
+
from_env(env)
|
|
31
|
+
rescue ArgumentError, Runtime::TypeMismatch => e
|
|
32
|
+
e.message.each_line { |line| stderr.puts("#{server}: refusing to start: #{line.chomp}") }
|
|
33
|
+
exit(EXIT_STATUS)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.setting_problems(env)
|
|
37
|
+
unknown = env.keys.select { |name| name.start_with?(ENV_PREFIX) } - [TOOLS_VARIABLE, DOMAINS_VARIABLE]
|
|
38
|
+
problems = unknown.map do |name|
|
|
39
|
+
"environment #{name} is not accepted; the door takes only #{TOOLS_VARIABLE} and #{DOMAINS_VARIABLE}"
|
|
40
|
+
end
|
|
41
|
+
problems + mode_problems(env[TOOLS_VARIABLE], env[DOMAINS_VARIABLE])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.mode_problems(tools, domains)
|
|
45
|
+
if tools.nil?
|
|
46
|
+
domains.nil? ? [] : ["#{DOMAINS_VARIABLE} is set without #{TOOLS_VARIABLE}=#{READERS}; it only narrows a reader door"]
|
|
47
|
+
elsif tools != READERS
|
|
48
|
+
["#{TOOLS_VARIABLE}=#{tools.inspect} is not accepted; the only value is #{READERS.inspect}"]
|
|
49
|
+
elsif domains.to_s.split(File::PATH_SEPARATOR).none? { |path| !path.empty? }
|
|
50
|
+
["#{TOOLS_VARIABLE}=#{READERS} needs #{DOMAINS_VARIABLE}, the domains this door may read"]
|
|
51
|
+
else
|
|
52
|
+
[]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The named domains, resolved against Storehouse::BOOT_ROOT; nil when unrestricted.
|
|
57
|
+
attr_reader :allowed_domains
|
|
58
|
+
|
|
59
|
+
def initialize(allowed_domains:)
|
|
60
|
+
@allowed_domains = allowed_domains&.map { |path| Storehouse.confine!(path, DOMAINS_VARIABLE) }.freeze
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def restricted?
|
|
64
|
+
!@allowed_domains.nil?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def permits_tool?(name)
|
|
68
|
+
!restricted? || READER_TOOLS.include?(name)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def refusal(name)
|
|
72
|
+
{ ok: false,
|
|
73
|
+
error: "#{name.inspect} is refused: this door runs in reader mode (#{TOOLS_VARIABLE}=#{READERS}), " \
|
|
74
|
+
"which serves only #{READER_TOOLS.join(', ')}" }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Checked before anything boots, so a path outside the allowed set never reaches Kernel.load.
|
|
78
|
+
def admit_domain!(domain)
|
|
79
|
+
return domain unless restricted?
|
|
80
|
+
return domain if @allowed_domains.include?(Storehouse.confine!(domain, "domain"))
|
|
81
|
+
|
|
82
|
+
raise Runtime::TypeMismatch,
|
|
83
|
+
"domain: #{domain.inspect} is refused: this door runs in reader mode (#{TOOLS_VARIABLE}=#{READERS}) " \
|
|
84
|
+
"and reads only #{DOMAINS_VARIABLE}: #{@allowed_domains.join(', ')}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def notes
|
|
88
|
+
return [] unless restricted?
|
|
89
|
+
|
|
90
|
+
["Reader mode (#{TOOLS_VARIABLE}=#{READERS}): serves #{READER_TOOLS.join(', ')}; " \
|
|
91
|
+
"refuses dispatch (with dry_run and steps), behaviors and every other tool.",
|
|
92
|
+
"domain: boots only #{DOMAINS_VARIABLE}: #{@allowed_domains.join(', ')}.",
|
|
93
|
+
"Reader mode limits reach and identifies no one; it is not authentication."]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require_relative "../../bluebook/dsl/hecksagon_builder"
|
|
2
|
+
require_relative "../../bluebook/dsl/world_builder"
|
|
3
|
+
require_relative "../../bluebook/dsl/domain_port_builder"
|
|
4
|
+
require_relative "../../bluebook/dsl/const_shim"
|
|
5
|
+
require_relative "../../bluebook/dsl/binding_proxy"
|
|
6
|
+
require_relative "../../bluebook/hexagon"
|
|
7
|
+
require_relative "../handle"
|
|
8
|
+
require_relative "../../naming"
|
|
9
|
+
|
|
10
|
+
module Hecks
|
|
11
|
+
module Doors
|
|
12
|
+
module RubyDoor
|
|
13
|
+
# One aggregate's door: creating verbs and queries as module methods, CRUD
|
|
14
|
+
# delegation, and the `.hecksagon` binding/port hooks it lands on.
|
|
15
|
+
module AggregateDoor
|
|
16
|
+
# Builds one aggregate's door module: creating-command methods, query methods,
|
|
17
|
+
# find/all/count/events, project/docs/narrate, and the port/binding hooks.
|
|
18
|
+
#
|
|
19
|
+
# Kept as one method: `:port`/`:method_missing`/`:const_missing` below
|
|
20
|
+
# cross-reference each other and would lose that thread if split up.
|
|
21
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
22
|
+
def aggregate_module(dispatcher, domain, aggregate)
|
|
23
|
+
fqn = "#{domain}::#{aggregate.hecks_name}"
|
|
24
|
+
door = Module.new
|
|
25
|
+
|
|
26
|
+
aggregate.attributes.each do |attribute|
|
|
27
|
+
next unless RESERVED.include?(attribute.name.to_sym)
|
|
28
|
+
|
|
29
|
+
warn "[hecks] #{aggregate.hecks_name}##{attribute.name} shadows a built-in — no reader defined"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# `!` marks a creating command (Ruby's mutate-and-may-refuse convention).
|
|
33
|
+
# Without it, a query sharing the same business name (e.g. Account's
|
|
34
|
+
# "Open") would collide with the creating command's own bare name.
|
|
35
|
+
aggregate.commands.select(&:creates?).each do |command|
|
|
36
|
+
door.define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
|
|
37
|
+
Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate,
|
|
38
|
+
instance: dispatcher.dispatch("#{fqn}.#{command.hecks_name}", with: args).instance)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# A query is a bare module method (no `!`): it just reads and returns
|
|
43
|
+
# the same raw row array `dispatcher.query` itself answers.
|
|
44
|
+
aggregate.queries.each do |query|
|
|
45
|
+
door.define_singleton_method(Naming.snake(query.hecks_name)) do |**args|
|
|
46
|
+
dispatcher.query("#{fqn}.#{query.hecks_name}", **args)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
door.define_singleton_method(:fqn) { fqn }
|
|
51
|
+
door.define_singleton_method(:ir) { aggregate }
|
|
52
|
+
|
|
53
|
+
# Every construct emits its own IR, so an aggregate is a legitimate
|
|
54
|
+
# `project` target too. A chapter-scoped target refuses here via
|
|
55
|
+
# `Projector.admits!` rather than answering a confidently empty result.
|
|
56
|
+
door.define_singleton_method(:project) do |target, out: nil, **options|
|
|
57
|
+
key = Projector.key_for(target)
|
|
58
|
+
artifact = Projector.call(key, bluebook: aggregate, options: options)
|
|
59
|
+
return artifact unless out
|
|
60
|
+
|
|
61
|
+
Projector.write(artifact, out, as: Projector.emits_for(key))
|
|
62
|
+
end
|
|
63
|
+
door.define_singleton_method(:repository) { dispatcher.registry.repository(domain, aggregate) }
|
|
64
|
+
door.define_singleton_method(:commands) do
|
|
65
|
+
aggregate.commands.map { |c| "#{Naming.snake(c.hecks_name)}!" }.sort
|
|
66
|
+
end
|
|
67
|
+
door.define_singleton_method(:queries) { aggregate.queries.map { |q| Naming.snake(q.hecks_name) }.sort }
|
|
68
|
+
# This chapter's own `:docs` projection, narrowed to this aggregate.
|
|
69
|
+
door.define_singleton_method(:docs) do |**options|
|
|
70
|
+
Projector.call(:docs, bluebook: dispatcher.registry.bluebook(domain),
|
|
71
|
+
options: options.merge(aggregate: aggregate.hecks_name))
|
|
72
|
+
end
|
|
73
|
+
# Same narrowing as `:docs`, aimed at `:narrate`.
|
|
74
|
+
door.define_singleton_method(:narrate) do |**options|
|
|
75
|
+
Projector.call(:narrate, bluebook: dispatcher.registry.bluebook(domain),
|
|
76
|
+
options: options.merge(aggregate: aggregate.hecks_name))
|
|
77
|
+
end
|
|
78
|
+
door.define_singleton_method(:count) { dispatcher.registry.repository(domain, aggregate).count }
|
|
79
|
+
door.define_singleton_method(:events) { dispatcher.events.select { |event| event.aggregate == fqn } }
|
|
80
|
+
|
|
81
|
+
door.define_singleton_method(:find) do |id|
|
|
82
|
+
found = dispatcher.registry.repository(domain, aggregate).find(id)
|
|
83
|
+
found && Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: found)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
door.define_singleton_method(:all) do |**opts|
|
|
87
|
+
dispatcher.registry.repository(domain, aggregate).all(**opts).map do |instance|
|
|
88
|
+
Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: instance)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Re-resolves via `Hecks.current_registry` rather than the closed-over
|
|
93
|
+
# `aggregate`: this door can be stale from an earlier boot, and its own
|
|
94
|
+
# `aggregate` would silently port a discarded one instead of the live one.
|
|
95
|
+
door.define_singleton_method(:port) do |name, &block|
|
|
96
|
+
current = Hecks.current_registry&.bluebook(domain)&.aggregate(aggregate.hecks_name) or
|
|
97
|
+
raise Bluebook::DSL::Malformed, "#{fqn}.port(#{name.inspect}) called outside a boot"
|
|
98
|
+
|
|
99
|
+
built = Bluebook::DSL::ConstShim.with(->(const) { const }) do
|
|
100
|
+
Bluebook::DSL::DomainPortBuilder.build(name, owner: current.hecks_name, &block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# A `verb`-shaped port is a plain `Port`, the same struct `Hecks.port` registers —
|
|
104
|
+
# it belongs to no aggregate IR the way an operations-shaped `DomainPort` does, so
|
|
105
|
+
# it takes the registry's `add_port` directly. Mirrors `DSL::BindingProxy#port`,
|
|
106
|
+
# which handles the identical shape on a domain's first in-process boot (before
|
|
107
|
+
# this facade constant exists); this method is what a repeat boot reaches instead.
|
|
108
|
+
if built.is_a?(Bluebook::Port)
|
|
109
|
+
Hecks.current_registry.add_port(built)
|
|
110
|
+
return self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
built.operations.each do |operation|
|
|
114
|
+
operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = current }
|
|
115
|
+
end
|
|
116
|
+
current.add_port(built)
|
|
117
|
+
self
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
door.define_singleton_method(:method_missing) do |verb, *args, **kwargs, &block|
|
|
121
|
+
# A bare call starts a Privacy marking chain (see
|
|
122
|
+
# `BindingProxy#method_missing`), reached here when the door is already
|
|
123
|
+
# installed (a second in-process boot) rather than at parse time.
|
|
124
|
+
return Bluebook::DSL::AttributePath.new(fqn, [verb.to_s]) if args.empty? && kwargs.empty? && !block
|
|
125
|
+
|
|
126
|
+
collector = Bluebook::DSL::HecksagonBuilder.collector
|
|
127
|
+
world = Bluebook::DSL::WorldBuilder.current
|
|
128
|
+
# Inside a `.world` block the same qualified spelling records a world setting.
|
|
129
|
+
return world.record_binding(verb, args, kwargs, block) if world && !collector
|
|
130
|
+
return super(verb, *args, **kwargs, &block) unless collector
|
|
131
|
+
|
|
132
|
+
collector << Bluebook::Bind.new(
|
|
133
|
+
aggregate: fqn,
|
|
134
|
+
verb: verb.to_s,
|
|
135
|
+
adapter: args.first.to_s,
|
|
136
|
+
role: kwargs[:role]&.to_s
|
|
137
|
+
)
|
|
138
|
+
block&.call
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
door.define_singleton_method(:respond_to_missing?) do |name, include_private = false|
|
|
143
|
+
!Bluebook::DSL::HecksagonBuilder.collector.nil? || !Bluebook::DSL::WorldBuilder.current.nil? ||
|
|
144
|
+
super(name, include_private)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Uses `aggregate.hecks_name`, not the qualified `fqn`: qualifying it here
|
|
148
|
+
# would make `Account::Debit`'s meaning depend on whether a stale door
|
|
149
|
+
# from an earlier boot happens to be sitting on this process.
|
|
150
|
+
door.define_singleton_method(:const_missing) do |name|
|
|
151
|
+
resolver = Bluebook::DSL::ConstShim.resolver
|
|
152
|
+
return resolver.call("#{aggregate.hecks_name}::#{name}") if resolver
|
|
153
|
+
|
|
154
|
+
super(name)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
door
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require_relative "../../bluebook/dsl/binding_proxy"
|
|
2
|
+
require_relative "../../bluebook/dsl/const_shim"
|
|
3
|
+
require_relative "../../bluebook/dsl/hecksagon_builder"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Doors
|
|
7
|
+
module RubyDoor
|
|
8
|
+
# One chapter's module: vision and aggregate list on the singleton, one
|
|
9
|
+
# aggregate door per declared head, and a `const_missing` hook for undeclared names.
|
|
10
|
+
module Chapter
|
|
11
|
+
# Builds the anonymous module that stands for one booted chapter: `vision`,
|
|
12
|
+
# `aggregates`, `docs`, `narrate` and `project` as singleton methods, plus one
|
|
13
|
+
# nested constant per aggregate holding that aggregate's door.
|
|
14
|
+
#
|
|
15
|
+
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
16
|
+
# dispatcher each aggregate door closes over
|
|
17
|
+
# @param bluebook [Bluebook::Chapter] the chapter to project into a module
|
|
18
|
+
# @return [Module] a fresh, unnamed module; `RubyDoor.install` gives it its
|
|
19
|
+
# top-level name
|
|
20
|
+
# @raise [NameError] if an aggregate's name is not a valid constant name
|
|
21
|
+
def chapter_module(dispatcher, bluebook)
|
|
22
|
+
chapter = Module.new
|
|
23
|
+
chapter.define_singleton_method(:vision) { bluebook.vision }
|
|
24
|
+
chapter.define_singleton_method(:aggregates) { bluebook.aggregates.map(&:name).sort }
|
|
25
|
+
|
|
26
|
+
# The chapter's usage document, projected from its IR on each call so it
|
|
27
|
+
# cannot go stale.
|
|
28
|
+
chapter.define_singleton_method(:docs) do |**options|
|
|
29
|
+
Projector.call(:docs, bluebook: bluebook, options: options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The chapter read back in english, via `Projector::NarrateProjector`.
|
|
33
|
+
chapter.define_singleton_method(:narrate) do |**options|
|
|
34
|
+
Projector.call(:narrate, bluebook: bluebook, options: options)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Projects the chapter's IR through a target; `out:` writes the artifact and
|
|
38
|
+
# the remaining options go to the projector (`audience:` for OIDC).
|
|
39
|
+
#
|
|
40
|
+
# Pizzas.project(Projections::OIDC)
|
|
41
|
+
# Pizzas.project(Projections::Shape, out: "shape.json")
|
|
42
|
+
chapter.define_singleton_method(:project) do |target, out: nil, **options|
|
|
43
|
+
key = Projector.key_for(target)
|
|
44
|
+
artifact = Projector.call(key, bluebook: bluebook, options: options)
|
|
45
|
+
return artifact unless out
|
|
46
|
+
|
|
47
|
+
Projector.write(artifact, out, as: Projector.emits_for(key))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
bluebook.aggregates.each do |aggregate|
|
|
51
|
+
chapter.const_set(aggregate.hecks_name, aggregate_module(dispatcher, bluebook.name, aggregate))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Inside a hecksagon a name is a declaration: with a collector open it becomes
|
|
55
|
+
# a `BindingProxy`. Otherwise a scoped reference from a bluebook mid-declaration
|
|
56
|
+
# goes to the `ConstShim` resolver, so it resolves whether or not a facade exists.
|
|
57
|
+
chapter.define_singleton_method(:const_missing) do |name|
|
|
58
|
+
collector = Bluebook::DSL::HecksagonBuilder.collector
|
|
59
|
+
return Bluebook::DSL::BindingProxy.new("#{bluebook.name}::#{name}", collector) if collector
|
|
60
|
+
|
|
61
|
+
resolver = Bluebook::DSL::ConstShim.resolver
|
|
62
|
+
return resolver.call("#{bluebook.name}::#{name}") if resolver
|
|
63
|
+
|
|
64
|
+
super(name)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
chapter
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require_relative "../chapters"
|
|
2
|
+
require_relative "ruby_door/chapter"
|
|
3
|
+
require_relative "ruby_door/aggregate_door"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Doors
|
|
7
|
+
# The door without classes: anonymous per-boot modules whose singleton methods
|
|
8
|
+
# dispatch by FQN, installed by `Loader.bind_runtime` and replaced whole on the next boot.
|
|
9
|
+
#
|
|
10
|
+
# `persisted_by("Heki")` in a `.hecksagon` file lands on the module's `method_missing`,
|
|
11
|
+
# which records a `Bind` into the open `HecksagonBuilder.collector`.
|
|
12
|
+
module RubyDoor
|
|
13
|
+
# Names that would shadow the machinery a Handle runs on; a field with one gets no reader.
|
|
14
|
+
RESERVED = %i[id state events reload inspect to_h hash class].freeze
|
|
15
|
+
|
|
16
|
+
extend Chapter
|
|
17
|
+
extend AggregateDoor
|
|
18
|
+
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
# Installs one top-level module per booted chapter, and one per aggregate, each
|
|
22
|
+
# closing over `dispatcher`, so `Pizzas::Pizza` and the bare `Pizza` both open the
|
|
23
|
+
# door of the boot that ran last.
|
|
24
|
+
#
|
|
25
|
+
# A gem chapter a hecksagon `attaches` installs nothing (`Query`, `Port` stay free).
|
|
26
|
+
# An aggregate sharing its chapter's name gets no second constant. A name that user
|
|
27
|
+
# code or the stdlib already owns is left alone with a warning (see `Namespace.install`).
|
|
28
|
+
#
|
|
29
|
+
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
30
|
+
# dispatcher every installed door dispatches and queries through
|
|
31
|
+
# @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the same `dispatcher`
|
|
32
|
+
# @raise [NameError] if a chapter or aggregate name is not a valid constant name
|
|
33
|
+
def install(dispatcher)
|
|
34
|
+
dispatcher.registry.bluebooks.each_value do |bluebook|
|
|
35
|
+
next if attached_chapter?(dispatcher.registry, bluebook)
|
|
36
|
+
|
|
37
|
+
chapter = chapter_module(dispatcher, bluebook)
|
|
38
|
+
Namespace.install(*placement(bluebook), chapter)
|
|
39
|
+
# A namespaced chapter keeps its aggregates inside its namespace: top-level
|
|
40
|
+
# shortcuts would bring back the collisions the namespace exists to avoid.
|
|
41
|
+
next if bluebook.namespace
|
|
42
|
+
|
|
43
|
+
bluebook.aggregates.each do |aggregate|
|
|
44
|
+
next if aggregate.hecks_name == bluebook.name
|
|
45
|
+
|
|
46
|
+
Namespace.install(Object, aggregate.hecks_name, chapter.const_get(aggregate.hecks_name, false))
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
dispatcher
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Whether `bluebook` is a gem chapter that a hecksagon attached rather than a domain's own.
|
|
53
|
+
#
|
|
54
|
+
# @param registry [Runtime::Registry] the booted registry
|
|
55
|
+
# @param bluebook [Bluebook::Chapter] the chapter under test
|
|
56
|
+
# @return [Boolean]
|
|
57
|
+
def attached_chapter?(registry, bluebook)
|
|
58
|
+
registry.bounded?(bluebook.name) && Hecks::Chapters.index.key?(bluebook.name)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Where a chapter's module installs: `Object::<name>`, or the constant path its
|
|
62
|
+
# `namespace` names, creating any missing parent modules along the way.
|
|
63
|
+
#
|
|
64
|
+
# @param bluebook [Bluebook::Chapter] the chapter being installed
|
|
65
|
+
# @return [Array(Module, String)] the parent module and the constant name within it
|
|
66
|
+
def placement(bluebook)
|
|
67
|
+
return [Object, bluebook.name] unless bluebook.namespace
|
|
68
|
+
|
|
69
|
+
*parents, leaf = bluebook.namespace.split("::")
|
|
70
|
+
parent = parents.reduce(Object) do |outer, name|
|
|
71
|
+
outer.const_defined?(name, false) ? outer.const_get(name, false) : outer.const_set(name, Module.new)
|
|
72
|
+
end
|
|
73
|
+
[parent, leaf]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|