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
|
@@ -3,15 +3,8 @@ require_relative "../../../runtime/value"
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Adapters
|
|
5
5
|
class Postgres
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# shape as Sqlite::Codec (one column per attribute, JSON for
|
|
9
|
-
# nested/list) — not its mechanics. Sqlite's own columns carry no
|
|
10
|
-
# type affinity worth trusting on the way back out (SQLite gives it
|
|
11
|
-
# back typed anyway via the driver), but `pg` hands every column
|
|
12
|
-
# back as text unless a type map says otherwise, so a real `bigint`/
|
|
13
|
-
# `double precision` column needs its own coercion on decode that
|
|
14
|
-
# Sqlite never had to write.
|
|
6
|
+
# Encodes and decodes a state to and from its columns, coercing `pg`'s text back to
|
|
7
|
+
# numbers.
|
|
15
8
|
module Codec
|
|
16
9
|
private
|
|
17
10
|
|
|
@@ -23,9 +16,7 @@ module Hecks
|
|
|
23
16
|
fields << { name: lifecycle.field, attribute: nil, sql_type: "text" } if lifecycle && fields.none? do |field|
|
|
24
17
|
field[:name] == lifecycle.field
|
|
25
18
|
end
|
|
26
|
-
# `projects` fields
|
|
27
|
-
# Sqlite::Codec#persisted_fields' own comment; identical reasoning,
|
|
28
|
-
# `text` to match this file's own lowercase SQL type spelling.
|
|
19
|
+
# `projects` fields are local columns too (ADR 0025).
|
|
29
20
|
@aggregate.projected_fields.each do |field|
|
|
30
21
|
next if fields.any? { |f| f[:name] == field.name }
|
|
31
22
|
|
|
@@ -35,10 +26,7 @@ module Hecks
|
|
|
35
26
|
end
|
|
36
27
|
|
|
37
28
|
def encode(attr, value)
|
|
38
|
-
#
|
|
39
|
-
# comment: a list attribute nothing has ever appended to has to
|
|
40
|
-
# stay NULL to answer the same as Memory does, not become `[]`
|
|
41
|
-
# invented by this adapter's own storage.
|
|
29
|
+
# A never-set list stays NULL rather than becoming `[]`, matching Memory.
|
|
42
30
|
return (value.nil? ? nil : state_json(value)) if attr.list?
|
|
43
31
|
return state_json(value) if value.is_a?(Hash) || value.is_a?(Runtime::Value)
|
|
44
32
|
|
|
@@ -51,13 +39,9 @@ module Hecks
|
|
|
51
39
|
encode(field[:attribute], value)
|
|
52
40
|
end
|
|
53
41
|
|
|
54
|
-
# Every jsonb column's text goes through the state codec's `encode`
|
|
55
|
-
# (PR A3) — see Sqlite::Codec#state_json.
|
|
56
42
|
def state_json(value) = JSON.generate(Ports::Persistence::StateCodec.encode(@aggregate, value))
|
|
57
43
|
|
|
58
|
-
#
|
|
59
|
-
# (PR A3) — see Sqlite::Codec#decode, including why a NULL
|
|
60
|
-
# projected-only column reads back absent.
|
|
44
|
+
# A NULL projected-only column reads back absent.
|
|
61
45
|
def decode(row)
|
|
62
46
|
state = persisted_fields.each_with_object({}) do |field, raw_state|
|
|
63
47
|
attr = field[:attribute]
|
|
@@ -84,13 +68,7 @@ module Hecks
|
|
|
84
68
|
@aggregate.projected_fields.any? { |projected| projected.name.to_sym == field[:name].to_sym }
|
|
85
69
|
end
|
|
86
70
|
|
|
87
|
-
# `pg` returns every column as a
|
|
88
|
-
# map installed) — a `bigint`/`double precision` column has to be
|
|
89
|
-
# coerced back on the way out, unlike Sqlite3's own driver, which
|
|
90
|
-
# already types a row by the column's declared affinity. Mirrors
|
|
91
|
-
# SQL_TYPES' own mapping: whatever gets a real numeric column here
|
|
92
|
-
# gets converted back here, everything else (String, references,
|
|
93
|
-
# enums, ...) passes through as the text it already is.
|
|
71
|
+
# `pg` returns every column as a String, so numeric columns are coerced back.
|
|
94
72
|
def coerce_scalar(attr, raw)
|
|
95
73
|
return nil if raw.nil?
|
|
96
74
|
|
|
@@ -3,21 +3,12 @@ require_relative "../../../runtime/outbox"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Adapters
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# `hecks_saga_instances` DDL is copied between them: nothing here is
|
|
9
|
-
# lineage-specific. Needs `@db` (a `PG::Connection`) and `table`
|
|
10
|
-
# (the aggregate's storage name) from the including class. See
|
|
11
|
-
# `Runtime::Outbox` for what the four verbs mean, and Sqlite's copy
|
|
12
|
-
# for the SQL idioms (`ON CONFLICT DO NOTHING` = idempotent enqueue,
|
|
13
|
-
# `WHERE status = 'pending'` = the compare-and-set claim).
|
|
6
|
+
# Outbox storage shared by `Postgres` and `PostgresEra`; needs `@db` and `table`.
|
|
7
|
+
# See `Runtime::Outbox` for the four verbs.
|
|
14
8
|
module PostgresOutbox
|
|
15
9
|
# Runs the block inside one Postgres transaction, joining an already-open one.
|
|
16
10
|
#
|
|
17
|
-
#
|
|
18
|
-
# transaction around save+emit+outbox and the adapter's own
|
|
19
|
-
# `append`/`atomic_put`/`delete` each open theirs; PG refuses
|
|
20
|
-
# BEGIN inside BEGIN, so an inner call joins the open one.
|
|
11
|
+
# Re-entrant: PG refuses BEGIN inside BEGIN, so an inner call joins the open one.
|
|
21
12
|
#
|
|
22
13
|
# @yield the writes to commit together; an exception raised inside rolls the
|
|
23
14
|
# outermost transaction back
|
|
@@ -1,28 +1,7 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Adapters
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# nothing here is lineage-specific, and `PostgresOutbox`'s own
|
|
6
|
-
# `@db.exec*` calls route through this module's `pg_exec`/
|
|
7
|
-
# `pg_exec_params` too, since both classes mix it in. Needs `@db` (a
|
|
8
|
-
# `PG::Connection`), `@aggregate`, and `@settings` from the including
|
|
9
|
-
# class — the same three `self.class.connect_for(@aggregate.name,
|
|
10
|
-
# @settings)` already needs to build one in the first place.
|
|
11
|
-
#
|
|
12
|
-
# A backend killed out from under an adapter (a DBA's own
|
|
13
|
-
# `pg_terminate_backend`, a load balancer's failover, a restart) —
|
|
14
|
-
# chaos-tested against the plain `Postgres` adapter: `PG::ConnectionBad`
|
|
15
|
-
# on the query that hit it, and permanently on every query after,
|
|
16
|
-
# since nothing ever replaced `@db` with a live connection.
|
|
17
|
-
# `pg_exec`/`pg_exec_params` are the two primitives every other method
|
|
18
|
-
# in either class funnels through — wrapping them here, once,
|
|
19
|
-
# self-heals `@db` for the next caller. The current call still
|
|
20
|
-
# raises — reconnecting cannot tell a caller whether its own write
|
|
21
|
-
# reached the server before the connection died, so silently
|
|
22
|
-
# retrying it here could silently double it; that ambiguity is
|
|
23
|
-
# exactly why `Runtime::SagaInterpreter`'s own defect-retry exists
|
|
24
|
-
# one layer up, where a dispatch is retried as a whole (fresh
|
|
25
|
-
# hydrate, fresh `given`s), not as a lone SQL statement.
|
|
3
|
+
# Replaces a dead `@db` after `PG::ConnectionBad`; shared by `Postgres` and `PostgresEra`.
|
|
4
|
+
# Needs `@db`, `@aggregate` and `@settings`.
|
|
26
5
|
module PostgresReconnect
|
|
27
6
|
# Runs one parameterless statement, replacing a dead connection before re-raising.
|
|
28
7
|
#
|
|
@@ -56,16 +35,15 @@ module Hecks
|
|
|
56
35
|
|
|
57
36
|
private
|
|
58
37
|
|
|
59
|
-
#
|
|
60
|
-
# is
|
|
61
|
-
# unchanged; the `PG::ConnectionBad` already being re-raised by
|
|
62
|
-
# `pg_exec`/`pg_exec_params` above still reaches the caller either
|
|
63
|
-
# way, so swallowing a failed reconnect attempt here loses no
|
|
64
|
-
# information — it only avoids masking the original error with a
|
|
65
|
-
# second one.
|
|
38
|
+
# The failing call still raises and is never retried: it may have reached the server.
|
|
39
|
+
# A failed reconnect is swallowed so it does not mask the original error.
|
|
66
40
|
def reconnect!
|
|
67
|
-
@db
|
|
68
|
-
|
|
41
|
+
if @db.respond_to?(:reconnect!)
|
|
42
|
+
@db.reconnect!
|
|
43
|
+
else
|
|
44
|
+
@db = self.class.connect_for(@aggregate.name, @settings)
|
|
45
|
+
end
|
|
46
|
+
rescue PG::Error, Runtime::WiringError
|
|
69
47
|
nil
|
|
70
48
|
end
|
|
71
49
|
end
|
|
@@ -3,14 +3,8 @@ require "digest"
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Adapters
|
|
5
5
|
class Postgres
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# table beside it, the shared events/saga tables — and the automatic
|
|
9
|
-
# indexing this adapter carries that `PostgresEra` does not (see
|
|
10
|
-
# docs/implemented/postgres-era-adapter-split-plan.md, governing principle 3:
|
|
11
|
-
# every field a declared query filters or sorts on is safe to index
|
|
12
|
-
# directly here, since there is no `head_view` reduction to route
|
|
13
|
-
# around the way `PostgresEra`'s own cache-table story exists for).
|
|
6
|
+
# DDL for the aggregate, entry, event and saga tables, plus the automatic
|
|
7
|
+
# indexes derived from declared queries.
|
|
14
8
|
module SchemaBuilder
|
|
15
9
|
private
|
|
16
10
|
|
|
@@ -19,40 +13,15 @@ module Hecks
|
|
|
19
13
|
@db.exec(
|
|
20
14
|
"CREATE TABLE IF NOT EXISTS #{quoted_table} (id text PRIMARY KEY#{', ' unless columns.empty?}#{columns.join(', ')})"
|
|
21
15
|
)
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
# column to an already-existing table (a committed database from
|
|
25
|
-
# before optimistic-concurrency CAS existed), so this runs
|
|
26
|
-
# unconditionally on every boot and no-ops once the column is
|
|
27
|
-
# there. Adapter bookkeeping only — never listed in
|
|
28
|
-
# `persisted_fields` (Codec), so it never appears in `decode`'s
|
|
29
|
-
# domain-state hash or `Instance#to_h`.
|
|
16
|
+
# CREATE TABLE IF NOT EXISTS never adds a column to an existing table, so
|
|
17
|
+
# the bookkeeping column is healed on every boot.
|
|
30
18
|
@db.exec("ALTER TABLE #{quoted_table} ADD COLUMN IF NOT EXISTS hecks_version bigint NOT NULL DEFAULT 1")
|
|
31
|
-
# Same
|
|
32
|
-
#
|
|
33
|
-
# column; a bluebook attribute added (or, via `translations/`,
|
|
34
|
-
# renamed) after this table already exists is not bookkeeping,
|
|
35
|
-
# but the identical gap applies: `CREATE TABLE IF NOT EXISTS`
|
|
36
|
-
# is a no-op against the existing table, so without this a new
|
|
37
|
-
# attribute boots clean and then dies `PG::UndefinedColumn` on
|
|
38
|
-
# the first `project` — discovered chaos-testing a live rename
|
|
39
|
-
# against this adapter (no era, no translation prompt; those
|
|
40
|
-
# live in `PostgresEra` — this is the plain adapter's own,
|
|
41
|
-
# simpler contract: "the table always has every column the
|
|
42
|
-
# bluebook currently declares"). No `NOT NULL`, no `DEFAULT` —
|
|
43
|
-
# existing rows get SQL NULL for a column they never had a
|
|
44
|
-
# value for, exactly what a fresh row would get for an unset
|
|
45
|
-
# optional attribute (`encode_field`'s own nil handling).
|
|
19
|
+
# Same healing for declared attributes: existing rows get NULL, as an unset
|
|
20
|
+
# optional attribute would.
|
|
46
21
|
persisted_fields.each do |field|
|
|
47
22
|
@db.exec("ALTER TABLE #{quoted_table} ADD COLUMN IF NOT EXISTS " \
|
|
48
23
|
"#{quote_ident(field[:name])} #{field[:sql_type]}")
|
|
49
24
|
end
|
|
50
|
-
# Right here, not a separate step in `Postgres#initialize` —
|
|
51
|
-
# same idiom Sqlite::SchemaBuilder's own `create_aggregate_table!`
|
|
52
|
-
# uses: index creation runs unconditionally, right after the
|
|
53
|
-
# table it indexes exists, the same self-healing shape
|
|
54
|
-
# `ensure_head_snapshot!`/`ensure_first_head!` already use on
|
|
55
|
-
# `PostgresEra`'s side.
|
|
56
25
|
ensure_indexes!
|
|
57
26
|
end
|
|
58
27
|
|
|
@@ -68,8 +37,6 @@ module Hecks
|
|
|
68
37
|
SQL
|
|
69
38
|
end
|
|
70
39
|
|
|
71
|
-
# Same DDL as `PostgresEra`'s own — not lineage-specific, copied
|
|
72
|
-
# verbatim (see docs/implemented/postgres-era-adapter-split-plan.md).
|
|
73
40
|
def create_event_table!
|
|
74
41
|
@db.exec(<<~SQL)
|
|
75
42
|
CREATE TABLE IF NOT EXISTS events (
|
|
@@ -81,10 +48,27 @@ module Hecks
|
|
|
81
48
|
occurred_at text
|
|
82
49
|
)
|
|
83
50
|
SQL
|
|
51
|
+
# Backs #events_for's per-record lookup (a `corrects` command's history read).
|
|
52
|
+
@db.exec(
|
|
53
|
+
"CREATE INDEX IF NOT EXISTS hecks_events_aggregate_id_idx ON events (aggregate, aggregate_id)"
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# One row per aggregate table, naming the highest entry `sequence` this table has
|
|
58
|
+
# already had projected into it — shared across every aggregate, since it is keyed
|
|
59
|
+
# by table name rather than declared per aggregate.
|
|
60
|
+
def create_checkpoint_table!
|
|
61
|
+
@db.exec(<<~SQL)
|
|
62
|
+
CREATE TABLE IF NOT EXISTS hecks_checkpoints (
|
|
63
|
+
aggregate_table text PRIMARY KEY,
|
|
64
|
+
last_sequence bigint NOT NULL DEFAULT 0
|
|
65
|
+
)
|
|
66
|
+
SQL
|
|
67
|
+
# CREATE TABLE IF NOT EXISTS never adds a column to an existing table, so
|
|
68
|
+
# the bookkeeping column is healed on every boot, same as create_aggregate_table!.
|
|
69
|
+
@db.exec("ALTER TABLE hecks_checkpoints ADD COLUMN IF NOT EXISTS compacted_through bigint NOT NULL DEFAULT 0")
|
|
84
70
|
end
|
|
85
71
|
|
|
86
|
-
# Same DDL as `PostgresEra`'s own — not lineage-specific, copied
|
|
87
|
-
# verbatim (see docs/implemented/postgres-era-adapter-split-plan.md).
|
|
88
72
|
def create_saga_table!
|
|
89
73
|
@db.exec(<<~SQL)
|
|
90
74
|
CREATE TABLE IF NOT EXISTS hecks_saga_instances (
|
|
@@ -98,11 +82,7 @@ module Hecks
|
|
|
98
82
|
PRIMARY KEY (domain, process_manager, correlation)
|
|
99
83
|
)
|
|
100
84
|
SQL
|
|
101
|
-
#
|
|
102
|
-
# this same domain already created before this column existed
|
|
103
|
-
# — the same idiom `rust/host/src/journal.rs`'s own
|
|
104
|
-
# `sagas_backfilled` column addition already uses, for the
|
|
105
|
-
# identical reason.
|
|
85
|
+
# Heals a table created before this column existed.
|
|
106
86
|
@db.exec("ALTER TABLE hecks_saga_instances ADD COLUMN IF NOT EXISTS completed_compensations jsonb " \
|
|
107
87
|
"NOT NULL DEFAULT '[]'::jsonb")
|
|
108
88
|
end
|
|
@@ -113,24 +93,8 @@ module Hecks
|
|
|
113
93
|
SQL_TYPES.fetch(attr.type, "text")
|
|
114
94
|
end
|
|
115
95
|
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
# Derived from every declared query's `where`/`order_by` fields —
|
|
119
|
-
# no bluebook author opts in, matching every other self-healing
|
|
120
|
-
# schema move this adapter makes. Walks the aggregate's own
|
|
121
|
-
# queries and each entity's own queries — the same enumeration
|
|
122
|
-
# `dsl/aggregate_builder.rb`'s own `query_surfaces` walks at
|
|
123
|
-
# declaration-seal time — but an entity's own fields never
|
|
124
|
-
# produce an index below: an entity has no table of its own, its
|
|
125
|
-
# rows live inside a list-typed attribute on the aggregate's own
|
|
126
|
-
# table (`QueryInterpreter#entity_rows` resolves it that way, and
|
|
127
|
-
# answers an entity query entirely in memory over `repository.all`
|
|
128
|
-
# — it never reaches this adapter's own `query` method at all).
|
|
129
|
-
# Every list-typed attribute is excluded below regardless (see
|
|
130
|
-
# `index_field!`), so an entity's own field would always resolve
|
|
131
|
-
# to "skip" anyway. Walked explicitly rather than silently
|
|
132
|
-
# dropped, so a reader can see entities were considered here, not
|
|
133
|
-
# forgotten.
|
|
96
|
+
# Indexes every field a declared query filters or sorts on. Entity queries are
|
|
97
|
+
# skipped: entities have no table, and their queries run in memory.
|
|
134
98
|
def ensure_indexes!
|
|
135
99
|
query_surfaces.each do |owner, queries|
|
|
136
100
|
next unless owner.equal?(@aggregate)
|
|
@@ -149,50 +113,18 @@ module Hecks
|
|
|
149
113
|
index_field!(query.order_by.field) if query.order_by
|
|
150
114
|
end
|
|
151
115
|
|
|
152
|
-
# A
|
|
153
|
-
#
|
|
154
|
-
# FROM jsonb_array_elements(...) ...)` (see `list_contains_clause`
|
|
155
|
-
# below), a SQL shape neither a plain btree on the raw jsonb
|
|
156
|
-
# column nor even a GIN jsonb index (`@>`, `?`) accelerates —
|
|
157
|
-
# Postgres's own GIN jsonb operators match a different SQL shape
|
|
158
|
-
# than the `EXISTS` + `jsonb_array_elements` this codebase always
|
|
159
|
-
# compiles a list `contains` to. An index here would be dead
|
|
160
|
-
# weight, not free correctness, so none is attempted.
|
|
116
|
+
# A list attribute is never indexed: `contains` compiles to EXISTS over
|
|
117
|
+
# jsonb_array_elements, which neither a btree nor a GIN jsonb index accelerates.
|
|
161
118
|
def index_field!(field)
|
|
162
|
-
# A hop path ("owner/field"
|
|
163
|
-
#
|
|
164
|
-
# `aggregate_builder.rb`'s own `field.to_s.include?("/")`
|
|
165
|
-
# checks) is never indexed here — same reasoning as `list_of`
|
|
166
|
-
# below: `query_expression`/`nested_expression` below have no
|
|
167
|
-
# dialect for this shape at all (they'd compile the whole
|
|
168
|
-
# "owner/field" string as one bare column/jsonb-path segment,
|
|
169
|
-
# which is not a real column and errors PG::UndefinedColumn on
|
|
170
|
-
# `CREATE INDEX`, discovered fuzzing a real Postgres boot of
|
|
171
|
-
# `examples/banking` — Account's own `projects :customer_status,
|
|
172
|
-
# from: :"customer.status"` compiles to exactly this shape).
|
|
173
|
-
# Skipping the index is always safe, the same way skipping a
|
|
174
|
-
# `list_of` index is: an index is a perf optimization, not
|
|
175
|
-
# correctness, so "never built" beats "built wrong." Whether a
|
|
176
|
-
# hop-path field can be queried at all against this adapter is
|
|
177
|
-
# a separate, still-open question this skip does not answer —
|
|
178
|
-
# see docs/future-features.md's fuzzer-adapter entry, and
|
|
179
|
-
# docs/1.0-readiness.md item 2 for this gap's other two
|
|
180
|
-
# independent failure points (Postgres querying, Rust codegen's
|
|
181
|
-
# `OpenForSuspendedCustomers` — bin/rust_coverage's own
|
|
182
|
-
# allowlist) — tracked together, not as three unrelated bugs.
|
|
119
|
+
# A hop path ("owner/field") has no column or jsonb path to index; it would
|
|
120
|
+
# fail CREATE INDEX with PG::UndefinedColumn.
|
|
183
121
|
return if field.to_s.include?("/")
|
|
184
122
|
|
|
185
123
|
name, *_path = field.to_s.split(".")
|
|
186
124
|
attribute = @aggregate.attribute(name)
|
|
187
125
|
return if attribute&.list?
|
|
188
126
|
|
|
189
|
-
#
|
|
190
|
-
# `query_expression`/`plain_column`, the real dialect methods,
|
|
191
|
-
# rather than a second, hand-rolled derivation of the same
|
|
192
|
-
# path that could silently drift from it. An index whose
|
|
193
|
-
# expression doesn't match the planner's own candidate
|
|
194
|
-
# expression byte-for-byte is invisible to the planner,
|
|
195
|
-
# created or not.
|
|
127
|
+
# Built from the query's own expression so the planner can match it byte for byte.
|
|
196
128
|
expression = query_expression(field.to_s)
|
|
197
129
|
if expression == plain_column(name)
|
|
198
130
|
create_plain_index!(name)
|
|
@@ -211,13 +143,7 @@ module Hecks
|
|
|
211
143
|
@db.exec("CREATE INDEX IF NOT EXISTS #{quote_ident(name)} ON #{quoted_table} ((#{expression}))")
|
|
212
144
|
end
|
|
213
145
|
|
|
214
|
-
#
|
|
215
|
-
# together keeps every generated index name well under that no
|
|
216
|
-
# matter how long an aggregate or attribute name gets, and keeps
|
|
217
|
-
# two distinct fields — on the same table or different ones —
|
|
218
|
-
# from ever colliding, or truncating into the same name the way
|
|
219
|
-
# a naive `"idx_#{table}_#{field}"` could once either got long
|
|
220
|
-
# enough.
|
|
146
|
+
# Hashed so the name stays under Postgres's 63-byte identifier limit and never collides.
|
|
221
147
|
def index_name(field)
|
|
222
148
|
"hecks_idx_#{Digest::SHA256.hexdigest("#{table}:#{field}")[0, 40]}"
|
|
223
149
|
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
require "monitor"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
# One Postgres connection shared by every `Postgres` or `PostgresEra` adapter of a process
|
|
6
|
+
# that targets the same database and schema, so a domain's connection count does not grow
|
|
7
|
+
# with its aggregates. Each adapter class shares only with its own kind, because each opens
|
|
8
|
+
# its connection its own way.
|
|
9
|
+
#
|
|
10
|
+
# Every call runs under one re-entrant monitor, and a transaction holds it from BEGIN to
|
|
11
|
+
# COMMIT, so a second thread's statements never interleave into another thread's
|
|
12
|
+
# transaction. The owning thread re-enters freely, so a nested `transaction` joins the open
|
|
13
|
+
# one, whichever aggregate's adapter opened it.
|
|
14
|
+
class PostgresSharedConnection
|
|
15
|
+
REGISTRY = {} # rubocop:disable Style/MutableConstant
|
|
16
|
+
REGISTRY_LOCK = Mutex.new
|
|
17
|
+
private_constant :REGISTRY, :REGISTRY_LOCK
|
|
18
|
+
|
|
19
|
+
# Runs in a forked child right after the fork, before any of its code.
|
|
20
|
+
#
|
|
21
|
+
# A child inherits its parent's sockets, and libpq sends a Terminate on the socket when
|
|
22
|
+
# the child's copy of the connection is finalized at exit, which would end the parent's
|
|
23
|
+
# session. The child's copy of each socket fd is pointed at the null device, so that
|
|
24
|
+
# Terminate goes nowhere, and the child forgets the handles without `finish`.
|
|
25
|
+
#
|
|
26
|
+
# @return [void]
|
|
27
|
+
def self.disown_inherited!
|
|
28
|
+
REGISTRY.each_value(&:disown!)
|
|
29
|
+
REGISTRY.clear
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Prepended to `Process` so every `fork`, `Process.fork` and `Kernel#fork` disowns the
|
|
33
|
+
# shared connections in the child.
|
|
34
|
+
module ForkGuard
|
|
35
|
+
# @return [Integer, nil] the child's pid in the parent, nil in the child
|
|
36
|
+
def _fork
|
|
37
|
+
pid = super
|
|
38
|
+
PostgresSharedConnection.disown_inherited! if pid.zero?
|
|
39
|
+
pid
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
Process.singleton_class.prepend(ForkGuard)
|
|
43
|
+
|
|
44
|
+
# Returns the process's shared connection for a database and schema, opening it on first use.
|
|
45
|
+
#
|
|
46
|
+
# The key includes the pid, so a forked child opens its own instead of sharing its
|
|
47
|
+
# parent's socket.
|
|
48
|
+
#
|
|
49
|
+
# @param name [String] the domain or aggregate name, used only in refusal messages
|
|
50
|
+
# @param settings [Hash{Symbol, String => Object}] `database` and optional `schema`
|
|
51
|
+
# @param connector [#connect_for] the adapter class that opens the connection
|
|
52
|
+
# @return [PostgresSharedConnection] the shared handle, connected
|
|
53
|
+
# @raise [Runtime::WiringError] if `database` is missing or the connection is refused
|
|
54
|
+
def self.for(name, settings, connector:)
|
|
55
|
+
key = [Process.pid, connector, setting(settings, :database), setting(settings, :schema)]
|
|
56
|
+
REGISTRY_LOCK.synchronize do
|
|
57
|
+
handle = REGISTRY[key] ||= new(name, settings, connector: connector)
|
|
58
|
+
handle.reconnect! if handle.dead?
|
|
59
|
+
handle
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Reads one setting under its Symbol or String spelling as a string.
|
|
64
|
+
#
|
|
65
|
+
# @param settings [Hash{Symbol, String => Object}] the binding's settings
|
|
66
|
+
# @param key [Symbol] the setting's name
|
|
67
|
+
# @return [String] the value, empty when absent
|
|
68
|
+
def self.setting(settings, key)
|
|
69
|
+
(settings.key?(key) ? settings[key] : settings[key.to_s]).to_s
|
|
70
|
+
end
|
|
71
|
+
private_class_method :setting
|
|
72
|
+
|
|
73
|
+
# Counts the shared connections this process holds open.
|
|
74
|
+
#
|
|
75
|
+
# @return [Integer] how many database and schema pairs have a live shared connection
|
|
76
|
+
def self.open_count = REGISTRY_LOCK.synchronize { REGISTRY.values.count { |handle| !handle.dead? } }
|
|
77
|
+
|
|
78
|
+
# Closes every shared connection and forgets it; the next `for` opens a fresh one.
|
|
79
|
+
#
|
|
80
|
+
# @return [void]
|
|
81
|
+
def self.close_all!
|
|
82
|
+
REGISTRY_LOCK.synchronize do
|
|
83
|
+
REGISTRY.each_value(&:close)
|
|
84
|
+
REGISTRY.clear
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @param name [String] the domain or aggregate name, used only in refusal messages
|
|
89
|
+
# @param settings [Hash{Symbol, String => Object}] `database` and optional `schema`
|
|
90
|
+
# @param connector [#connect_for] the adapter class that opens the connection
|
|
91
|
+
# @raise [Runtime::WiringError] if `database` is missing or the connection is refused
|
|
92
|
+
def initialize(name, settings, connector:)
|
|
93
|
+
@name = name
|
|
94
|
+
@settings = settings
|
|
95
|
+
@connector = connector
|
|
96
|
+
@monitor = Monitor.new
|
|
97
|
+
@conn = connector.connect_for(name, settings)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Runs one parameterless statement under the connection's monitor.
|
|
101
|
+
#
|
|
102
|
+
# @param sql [String] the statement
|
|
103
|
+
# @return [PG::Result] the statement's result
|
|
104
|
+
def exec(sql, &) = @monitor.synchronize { @conn.exec(sql, &) }
|
|
105
|
+
|
|
106
|
+
# Runs one statement with bind parameters under the connection's monitor.
|
|
107
|
+
#
|
|
108
|
+
# @param sql [String] the statement, with `$1`-style placeholders
|
|
109
|
+
# @param binds [Array<Object>] one value per placeholder
|
|
110
|
+
# @return [PG::Result] the statement's result
|
|
111
|
+
def exec_params(sql, binds = [], *rest, &) = @monitor.synchronize { @conn.exec_params(sql, binds, *rest, &) }
|
|
112
|
+
|
|
113
|
+
# Reports the server-side transaction state; blocks while another thread's transaction
|
|
114
|
+
# holds the connection, so a caller never mistakes it for its own.
|
|
115
|
+
#
|
|
116
|
+
# @return [Integer] a `PG::PQTRANS_*` constant
|
|
117
|
+
def transaction_status = @monitor.synchronize { @conn.transaction_status }
|
|
118
|
+
|
|
119
|
+
# Runs the block in one transaction, joining one the calling thread already holds.
|
|
120
|
+
#
|
|
121
|
+
# @yield the writes to commit together; an exception rolls the outermost one back
|
|
122
|
+
# @return [Object] the block's own value
|
|
123
|
+
def transaction(&block)
|
|
124
|
+
@monitor.synchronize do
|
|
125
|
+
next yield if @conn.transaction_status != PG::PQTRANS_IDLE
|
|
126
|
+
|
|
127
|
+
@conn.transaction(&block)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Reports the server process id serving the connection.
|
|
132
|
+
#
|
|
133
|
+
# @return [Integer] the backend pid
|
|
134
|
+
def backend_pid = @monitor.synchronize { @conn.backend_pid }
|
|
135
|
+
|
|
136
|
+
# Quotes an identifier; needs no connection round trip.
|
|
137
|
+
#
|
|
138
|
+
# @param name [String, Symbol] the identifier
|
|
139
|
+
# @return [String] the double-quoted identifier
|
|
140
|
+
def quote_ident(name) = PG::Connection.quote_ident(name.to_s)
|
|
141
|
+
|
|
142
|
+
# Reports whether the underlying socket is closed or broken.
|
|
143
|
+
#
|
|
144
|
+
# @return [Boolean] true when the connection cannot run statements
|
|
145
|
+
def dead? = @monitor.synchronize { @conn.finished? || @conn.status != PG::CONNECTION_OK }
|
|
146
|
+
|
|
147
|
+
# Replaces the connection when it is dead; a no-op when another caller already did.
|
|
148
|
+
#
|
|
149
|
+
# @return [void]
|
|
150
|
+
# @raise [Runtime::WiringError] if the new connection is refused
|
|
151
|
+
def reconnect!
|
|
152
|
+
@monitor.synchronize do
|
|
153
|
+
next unless dead?
|
|
154
|
+
|
|
155
|
+
@conn.close unless @conn.finished?
|
|
156
|
+
@conn = @connector.connect_for(@name, @settings)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Detaches this handle's socket from the parent's session in a forked child: the child's
|
|
161
|
+
# fd is repointed at the null device, so nothing the child's copy of the connection writes
|
|
162
|
+
# (statements, Terminate) reaches the parent's server session. Takes no lock, since the
|
|
163
|
+
# child holds none of the parent's monitors.
|
|
164
|
+
#
|
|
165
|
+
# @return [void]
|
|
166
|
+
def disown!
|
|
167
|
+
return if @conn.finished?
|
|
168
|
+
|
|
169
|
+
IO.for_fd(@conn.socket, autoclose: false).reopen(File::NULL, "r+")
|
|
170
|
+
rescue StandardError
|
|
171
|
+
nil
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Closes the underlying connection.
|
|
175
|
+
#
|
|
176
|
+
# @return [void]
|
|
177
|
+
def close = @monitor.synchronize { @conn.close unless @conn.finished? }
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|