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
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
require_relative "console_capture"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
# The `PgAdmin` port's adapter: the Postgres administration that happens outside the
|
|
9
|
+
# persistence adapters, namely roles and scratch databases.
|
|
10
|
+
#
|
|
11
|
+
# Connections are made to the maintenance database (`postgres`) or to the database being
|
|
12
|
+
# administered, as the current operating-system user, exactly as `psql` would. Nothing here
|
|
13
|
+
# creates the ledger database itself: PostgresEra provisions the tables it needs on first
|
|
14
|
+
# connect, and an operator makes the database with `createdb`.
|
|
15
|
+
class PgAdmin
|
|
16
|
+
# The role the QA ledger connects as when none is named.
|
|
17
|
+
DEFAULT_ROLE = "hecks_qa"
|
|
18
|
+
|
|
19
|
+
# What every database this adapter drops must start with, and be followed by a name.
|
|
20
|
+
SCRATCH = /\Ascratch_\w+\z/
|
|
21
|
+
|
|
22
|
+
# Databases that are never dropped, whatever their name: the maintenance and template
|
|
23
|
+
# databases.
|
|
24
|
+
SYSTEM_DATABASES = %w[postgres template0 template1].freeze
|
|
25
|
+
|
|
26
|
+
# The environment variables that name the ledger or production database in use.
|
|
27
|
+
CONFIGURED_DATABASES = %w[PGDATABASE HECKS_LEDGER_DATABASE HECKS_DATABASE].freeze
|
|
28
|
+
|
|
29
|
+
# Relation kinds in `pg_class` mapped to the `ALTER` keyword that changes their owner.
|
|
30
|
+
# Partitions are their own rows, so `ALTER TABLE ... OWNER` on a parent does not reach them.
|
|
31
|
+
KINDS = { "r" => "TABLE", "p" => "TABLE", "S" => "SEQUENCE", "v" => "VIEW",
|
|
32
|
+
"m" => "MATERIALIZED VIEW" }.freeze
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
# @return [#call, nil] opens a connection given `dbname:` and answers an object with
|
|
36
|
+
# `exec`, `exec_params`, `quote_ident` and `close`; a spec replaces it so no server is
|
|
37
|
+
# reached. The `pg` gem is required only when this is nil.
|
|
38
|
+
attr_accessor :connector
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
42
|
+
#
|
|
43
|
+
# @param aggregate [Object, nil] unused
|
|
44
|
+
# @param settings [Hash] unused
|
|
45
|
+
# @param root [String, nil] unused
|
|
46
|
+
def initialize(aggregate: nil, settings: {}, root: nil); end
|
|
47
|
+
|
|
48
|
+
# Creates the ordinary role the QA ledger connects as and makes it own the database, its
|
|
49
|
+
# schema, and everything in it. Safe to repeat: what is already right is reported, not redone.
|
|
50
|
+
#
|
|
51
|
+
# A superuser or BYPASSRLS role is refused, because the era write-fence cannot bind it.
|
|
52
|
+
#
|
|
53
|
+
# @param held [Hash] `database` (required) and `role` (`hecks_qa` when absent)
|
|
54
|
+
# @return [Hash{Symbol => Hash}] `report:` what was done and what already held
|
|
55
|
+
# @raise [ConsoleCapture::Failure] if no database is named or it does not exist, or the role
|
|
56
|
+
# exists with privileges the fence cannot bind
|
|
57
|
+
def create_ledger_role(**held)
|
|
58
|
+
database = named(held)
|
|
59
|
+
role = plain(held[:role]) || DEFAULT_ROLE
|
|
60
|
+
|
|
61
|
+
done = []
|
|
62
|
+
skipped = []
|
|
63
|
+
with(dbname: "postgres") do |admin|
|
|
64
|
+
ensure_role(admin, role, done, skipped)
|
|
65
|
+
hand_over_database(admin, database, role, done, skipped)
|
|
66
|
+
end
|
|
67
|
+
with(dbname: database) { |db| hand_over_contents(db, role, done) }
|
|
68
|
+
|
|
69
|
+
{ report: { value: ledger_report(database, role, done, skipped) } }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Creates an empty database, for a scratch run that needs one. Repeating it reports that the
|
|
73
|
+
# database exists.
|
|
74
|
+
#
|
|
75
|
+
# @param held [Hash] `database` (required)
|
|
76
|
+
# @return [Hash{Symbol => Hash}] `report:` what happened
|
|
77
|
+
# @raise [ConsoleCapture::Failure] if no database is named
|
|
78
|
+
def create_database(**held)
|
|
79
|
+
database = named(held)
|
|
80
|
+
with(dbname: "postgres") do |admin|
|
|
81
|
+
if exists?(admin, database)
|
|
82
|
+
{ report: { value: "database #{database} already exists" } }
|
|
83
|
+
else
|
|
84
|
+
admin.exec("CREATE DATABASE #{admin.quote_ident(database)}")
|
|
85
|
+
{ report: { value: "created database #{database}" } }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Drops a scratch database if it is there, ending other sessions on it first so one left
|
|
91
|
+
# open by a crashed run does not block the drop. Ending every session on a database is
|
|
92
|
+
# only safe for a throwaway one, so a name must start with `scratch_` and must not be the
|
|
93
|
+
# ledger or production database the environment names.
|
|
94
|
+
#
|
|
95
|
+
# @param held [Hash] `database` (required)
|
|
96
|
+
# @return [Hash{Symbol => Hash}] `report:` what happened
|
|
97
|
+
# @raise [ConsoleCapture::Failure] if no database is named, it is not a scratch name, or it
|
|
98
|
+
# is a configured ledger or production database
|
|
99
|
+
def drop_database(**held)
|
|
100
|
+
database = named(held)
|
|
101
|
+
refuse_to_drop!(database)
|
|
102
|
+
with(dbname: "postgres") do |admin|
|
|
103
|
+
if exists?(admin, database)
|
|
104
|
+
admin.exec_params("SELECT pg_terminate_backend(pid) FROM pg_stat_activity " \
|
|
105
|
+
"WHERE datname = $1 AND pid <> pg_backend_pid()", [database])
|
|
106
|
+
admin.exec("DROP DATABASE #{admin.quote_ident(database)}")
|
|
107
|
+
{ report: { value: "dropped database #{database}" } }
|
|
108
|
+
else
|
|
109
|
+
{ report: { value: "no database #{database}" } }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def refuse_to_drop!(database)
|
|
117
|
+
if SYSTEM_DATABASES.include?(database.downcase) || configured_databases.include?(database)
|
|
118
|
+
raise ConsoleCapture::Failure, "refusing to drop #{database}: it is the ledger, production or " \
|
|
119
|
+
"a system database"
|
|
120
|
+
end
|
|
121
|
+
return if database.match?(SCRATCH)
|
|
122
|
+
|
|
123
|
+
raise ConsoleCapture::Failure, "refusing to drop #{database}: only databases named scratch_<name> " \
|
|
124
|
+
"are dropped"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def configured_databases
|
|
128
|
+
named = CONFIGURED_DATABASES.filter_map { |variable| ENV.fetch(variable, nil) }
|
|
129
|
+
url = ENV.fetch("DATABASE_URL", nil)
|
|
130
|
+
named << URI.parse(url).path.to_s.delete_prefix("/") if url && !url.empty?
|
|
131
|
+
named.reject(&:empty?)
|
|
132
|
+
rescue URI::InvalidURIError
|
|
133
|
+
named
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def named(held)
|
|
137
|
+
database = plain(held[:database])
|
|
138
|
+
raise ConsoleCapture::Failure, "no database named" if database.to_s.empty?
|
|
139
|
+
|
|
140
|
+
database
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def ensure_role(admin, role, done, skipped)
|
|
144
|
+
found = admin.exec_params("SELECT rolsuper, rolbypassrls FROM pg_roles WHERE rolname = $1", [role])
|
|
145
|
+
if found.ntuples.zero?
|
|
146
|
+
# CREATE ROLE has no IF NOT EXISTS, and concurrent creates can lose on the catalog
|
|
147
|
+
# index (unique_violation) as well as on duplicate_object, so the block rescues both.
|
|
148
|
+
admin.exec(<<~SQL)
|
|
149
|
+
DO $$ BEGIN
|
|
150
|
+
CREATE ROLE #{admin.quote_ident(role)} LOGIN NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE;
|
|
151
|
+
EXCEPTION WHEN duplicate_object OR unique_violation THEN NULL;
|
|
152
|
+
END $$
|
|
153
|
+
SQL
|
|
154
|
+
done << "created role #{role} (LOGIN, no SUPERUSER, no BYPASSRLS)"
|
|
155
|
+
elsif found[0]["rolsuper"] == "t" || found[0]["rolbypassrls"] == "t"
|
|
156
|
+
kind = found[0]["rolsuper"] == "t" ? "a superuser" : "a BYPASSRLS role"
|
|
157
|
+
raise ConsoleCapture::Failure,
|
|
158
|
+
"role #{role} already exists as #{kind}: the era write-fence cannot bind it. " \
|
|
159
|
+
"Pick another role, or ALTER ROLE #{role} NOSUPERUSER NOBYPASSRLS first."
|
|
160
|
+
else
|
|
161
|
+
skipped << "role #{role} exists, ordinary"
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def hand_over_database(admin, database, role, done, skipped)
|
|
166
|
+
owner = admin.exec_params(
|
|
167
|
+
"SELECT pg_get_userbyid(datdba) AS owner FROM pg_database WHERE datname = $1", [database]
|
|
168
|
+
)
|
|
169
|
+
if owner.ntuples.zero?
|
|
170
|
+
raise ConsoleCapture::Failure,
|
|
171
|
+
"no database #{database}: createdb it first (PostgresEra provisions every table it " \
|
|
172
|
+
"needs on first connect, never the database itself)"
|
|
173
|
+
elsif owner[0]["owner"] == role
|
|
174
|
+
skipped << "database #{database} already owned by #{role}"
|
|
175
|
+
else
|
|
176
|
+
admin.exec("ALTER DATABASE #{admin.quote_ident(database)} OWNER TO #{admin.quote_ident(role)}")
|
|
177
|
+
done << "database #{database}: owner #{owner[0]['owner']} -> #{role}"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def hand_over_contents(db, role, done)
|
|
182
|
+
quoted = db.quote_ident(role)
|
|
183
|
+
schema = db.exec("SELECT pg_get_userbyid(nspowner) AS owner FROM pg_namespace WHERE nspname = 'public'")
|
|
184
|
+
if schema.ntuples.positive? && schema[0]["owner"] != role
|
|
185
|
+
db.exec("ALTER SCHEMA public OWNER TO #{quoted}")
|
|
186
|
+
done << "schema public: owner #{schema[0]['owner']} -> #{role}"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
relations = db.exec_params(<<~SQL, [role])
|
|
190
|
+
SELECT c.relname, c.relkind, pg_get_userbyid(c.relowner) AS owner
|
|
191
|
+
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
192
|
+
WHERE n.nspname = 'public' AND c.relkind IN ('r', 'p', 'S', 'v', 'm') AND pg_get_userbyid(c.relowner) <> $1
|
|
193
|
+
ORDER BY c.relkind, c.relname
|
|
194
|
+
SQL
|
|
195
|
+
relations.each do |row|
|
|
196
|
+
db.exec("ALTER #{KINDS.fetch(row['relkind'])} #{db.quote_ident(row['relname'])} OWNER TO #{quoted}")
|
|
197
|
+
end
|
|
198
|
+
done << "#{relations.ntuples} relation(s) in public -> #{role}" if relations.ntuples.positive?
|
|
199
|
+
|
|
200
|
+
functions = db.exec_params(<<~SQL, [role])
|
|
201
|
+
SELECT p.proname, pg_get_function_identity_arguments(p.oid) AS args
|
|
202
|
+
FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
203
|
+
WHERE n.nspname = 'public' AND pg_get_userbyid(p.proowner) <> $1
|
|
204
|
+
ORDER BY p.proname
|
|
205
|
+
SQL
|
|
206
|
+
functions.each do |row|
|
|
207
|
+
db.exec("ALTER FUNCTION #{db.quote_ident(row['proname'])}(#{row['args']}) OWNER TO #{quoted}")
|
|
208
|
+
end
|
|
209
|
+
done << "#{functions.ntuples} function(s) in public -> #{role}" if functions.ntuples.positive?
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def ledger_report(database, role, done, skipped)
|
|
213
|
+
lines = ["#{database} is #{role}'s"]
|
|
214
|
+
done.each { |line| lines << " did: #{line}" }
|
|
215
|
+
skipped.each { |line| lines << " already: #{line}" }
|
|
216
|
+
lines << " bind it: database \"postgres://#{role}@localhost/#{database}\"" if done.any?
|
|
217
|
+
lines.join("\n")
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def exists?(admin, database)
|
|
221
|
+
admin.exec_params("SELECT 1 FROM pg_database WHERE datname = $1", [database]).ntuples.positive?
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def with(dbname:)
|
|
225
|
+
connection = connect(dbname)
|
|
226
|
+
yield connection
|
|
227
|
+
rescue ConsoleCapture::Failure
|
|
228
|
+
raise
|
|
229
|
+
rescue StandardError => e
|
|
230
|
+
raise ConsoleCapture::Failure, "postgres: #{e.message.strip}"
|
|
231
|
+
ensure
|
|
232
|
+
connection&.close
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def connect(dbname)
|
|
236
|
+
return self.class.connector.call(dbname: dbname) if self.class.connector
|
|
237
|
+
|
|
238
|
+
require "pg"
|
|
239
|
+
PG.connect(dbname: dbname)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Required by name, not relative to this file: a fuzz or model check boots a copy of this directory,
|
|
2
|
+
# and the implementation must load once, from `lib/`, not from the copy.
|
|
3
|
+
require "hecks/hecks/adapters/process_pool"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "ProcessPool" do
|
|
6
|
+
port "ProcessPool"
|
|
7
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
require "tempfile"
|
|
5
|
+
require_relative "console_capture"
|
|
6
|
+
require_relative "rust_workspace"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
# The `ProcessPool` port's adapter: starts a long-running child (a fuzz sweep forks its own
|
|
11
|
+
# workers) and stays with it until it ends.
|
|
12
|
+
#
|
|
13
|
+
# The child runs in its own process group, and an interrupt or termination sent to this
|
|
14
|
+
# process is passed on to the whole group, so stopping a launcher stops the workers it
|
|
15
|
+
# started instead of leaving them running. Output goes to a temporary file, not a pipe, so a
|
|
16
|
+
# child that writes a lot never blocks on a reader that is waiting for it to exit.
|
|
17
|
+
class ProcessPool
|
|
18
|
+
# What a child said and how it ended.
|
|
19
|
+
#
|
|
20
|
+
# @!attribute [r] output
|
|
21
|
+
# @return [String] what it wrote to stdout and stderr, in order
|
|
22
|
+
# @!attribute [r] status
|
|
23
|
+
# @return [Process::Status] how it ended
|
|
24
|
+
Finished = Struct.new(:output, :status) do
|
|
25
|
+
# @return [Boolean] whether the child ended with status 0
|
|
26
|
+
def ok? = status.success?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The library the sweep child loads `Hecks::Tools` from.
|
|
30
|
+
LIB = File.expand_path("../../..", __dir__)
|
|
31
|
+
|
|
32
|
+
# What the sweep child runs: the `fuzz` tool, which takes the flags that follow.
|
|
33
|
+
ENTRY = 'require "hecks/tools"; Hecks::Tools.script("fuzz", ARGV)'
|
|
34
|
+
|
|
35
|
+
# Signals passed on to a running child's process group.
|
|
36
|
+
FORWARDED = %w[INT TERM HUP QUIT].freeze
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
# @return [#call, nil] runs a child given `(command, env, chdir)` and answers a `Finished`;
|
|
40
|
+
# a spec replaces it so nothing is started
|
|
41
|
+
attr_accessor :starter
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
45
|
+
#
|
|
46
|
+
# @param aggregate [Object, nil] unused
|
|
47
|
+
# @param settings [Hash] unused
|
|
48
|
+
# @param root [String, nil] unused
|
|
49
|
+
def initialize(aggregate: nil, settings: {}, root: nil); end
|
|
50
|
+
|
|
51
|
+
# Runs a fuzz sweep over one domain, or over every domain of the checkout when none is named.
|
|
52
|
+
#
|
|
53
|
+
# @param held [Hash] the `Fuzzing` record: `domain`, `seeds`, `steps`, `workers`, `adapter`
|
|
54
|
+
# @return [Hash{Symbol => Hash}] `report:` what the sweep printed
|
|
55
|
+
# @raise [ConsoleCapture::Failure] when the sweep found something, or could not run
|
|
56
|
+
def sweep(**held)
|
|
57
|
+
if plain(held[:domain]).nil? && !RustWorkspace.new.checkout?
|
|
58
|
+
raise ConsoleCapture::Failure, "name a domain (hecks fuzz <domain>): sweeping every domain " \
|
|
59
|
+
"needs a hecks checkout"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
command = [RbConfig.ruby, "-I", LIB, "-e", ENTRY, "--"]
|
|
63
|
+
command << plain(held[:domain]) if plain(held[:domain])
|
|
64
|
+
{ "--seeds" => :seeds, "--steps" => :steps, "--workers" => :workers, "--adapter" => :adapter }.each do |flag, key|
|
|
65
|
+
command.push(flag, plain(held[key]).to_s) unless plain(held[key]).nil?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
answer(run(command))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Starts a child, forwards interrupts to it, and waits for it to end.
|
|
72
|
+
#
|
|
73
|
+
# @param command [Array<String>] the program, then its arguments
|
|
74
|
+
# @param env [Hash{String => String}] variables to set for it
|
|
75
|
+
# @param chdir [String, nil] the directory to run it in
|
|
76
|
+
# @return [Finished] what it said and how it ended
|
|
77
|
+
def run(command, env: {}, chdir: nil)
|
|
78
|
+
starter = self.class.starter
|
|
79
|
+
return starter.call(command, env, chdir) if starter
|
|
80
|
+
|
|
81
|
+
output = Tempfile.new("process-pool")
|
|
82
|
+
options = { pgroup: true, out: output, err: output }
|
|
83
|
+
options[:chdir] = chdir if chdir
|
|
84
|
+
# Traps go in before the spawn, so a signal that lands while the child is starting is held
|
|
85
|
+
# and passed on the moment its pid is known, instead of orphaning it.
|
|
86
|
+
pid = nil
|
|
87
|
+
held = []
|
|
88
|
+
previous = FORWARDED.to_h do |name|
|
|
89
|
+
[name, trap(name) { pid ? forward(name, pid) : held << name }]
|
|
90
|
+
end
|
|
91
|
+
pid = spawn(env, *command, **options)
|
|
92
|
+
held.each { |name| forward(name, pid) }
|
|
93
|
+
_, status = Process.wait2(pid)
|
|
94
|
+
Finished.new(File.read(output.path), status)
|
|
95
|
+
rescue Errno::ENOENT => e
|
|
96
|
+
Finished.new(e.message, Struct.new(:success?, :exitstatus).new(false, 127))
|
|
97
|
+
ensure
|
|
98
|
+
previous&.each { |name, handler| trap(name, handler) }
|
|
99
|
+
output&.close!
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def forward(name, pid)
|
|
105
|
+
Process.kill(name, -pid)
|
|
106
|
+
rescue Errno::ESRCH
|
|
107
|
+
nil
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def answer(finished)
|
|
111
|
+
raise ConsoleCapture::Failure, finished.output.strip unless finished.ok?
|
|
112
|
+
|
|
113
|
+
{ report: { value: finished.output } }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Required by name, not relative to this file: a fuzz or model check boots a copy of this directory,
|
|
2
|
+
# and the implementation must load once, from `lib/`, not from the copy.
|
|
3
|
+
require "hecks/hecks/adapters/rust_toolchain"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "RustToolchain" do
|
|
6
|
+
port "RustToolchain"
|
|
7
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
require_relative "console_capture"
|
|
5
|
+
require_relative "rust_workspace"
|
|
6
|
+
require_relative "process_pool"
|
|
7
|
+
require "hecks/rust_build"
|
|
8
|
+
|
|
9
|
+
module Hecks
|
|
10
|
+
module Adapters
|
|
11
|
+
# The `RustToolchain` port's adapter: generates a domain's Rust source, compiles it (native,
|
|
12
|
+
# WASI, browser) and checks the build against the Ruby engine.
|
|
13
|
+
#
|
|
14
|
+
# Each ask runs one of the `Hecks::RustBuild` tools in this process, in the workspace
|
|
15
|
+
# `RustWorkspace` names: the checkout's own `rust/`, or a copy of the packaged workspace under
|
|
16
|
+
# the client's `.hecks/rust/<version>/`. The tool is told that workspace and a `target/`
|
|
17
|
+
# beside it, so a build never writes into the installed gem. A tool that ends non-zero is a
|
|
18
|
+
# refusal whose reason is what it printed. The benchmark is the exception: it can run for
|
|
19
|
+
# minutes, so it starts as a child through `ProcessPool`.
|
|
20
|
+
class RustToolchain
|
|
21
|
+
# The `Hecks::RustBuild` tool each ask runs.
|
|
22
|
+
TOOLS = { generate: "project_rust", wasm: "project_wasm", browser_wasm: "project_wasm_browser",
|
|
23
|
+
conform: "rust_conformance", replay: "rust_conformance_fuzz",
|
|
24
|
+
coverage: "rust_coverage" }.freeze
|
|
25
|
+
|
|
26
|
+
# The load path the benchmark child runs with: this checkout's or gem's `lib/`.
|
|
27
|
+
LIB = File.expand_path("../../..", __dir__)
|
|
28
|
+
|
|
29
|
+
# The program the benchmark child runs: `hecks bench`'s command line.
|
|
30
|
+
BENCH = 'require "hecks"; require "hecks/bench"; exit Hecks::Bench::CLI.run(ARGV)'
|
|
31
|
+
|
|
32
|
+
# `Hecks::Bench::CLI`'s flag for each `FuzzRun` field a benchmark takes.
|
|
33
|
+
BENCH_FLAGS = { "--domain" => :domains, "--targets" => :targets, "--iterations" => :iterations,
|
|
34
|
+
"--warmup" => :warmup, "--runs" => :runs, "--rust-binary" => :rust_binary,
|
|
35
|
+
"--format" => :format, "--output" => :output }.freeze
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
# @return [#run, nil] starts the long-running benchmark; a `ProcessPool` when nil
|
|
39
|
+
attr_accessor :pool
|
|
40
|
+
|
|
41
|
+
# @return [#capture, nil] runs each tool, as `capture(tool, argv, env:)` answering an
|
|
42
|
+
# object with `out`, `err`, `status` and `ok?`; `Hecks::RustBuild` when nil. A spec
|
|
43
|
+
# replaces it, so no toolchain is needed to test what is asked of it.
|
|
44
|
+
attr_accessor :runner
|
|
45
|
+
|
|
46
|
+
# @return [RustWorkspace, nil] the workspace to build in; `RustWorkspace.new` when nil
|
|
47
|
+
attr_accessor :workspace
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
51
|
+
#
|
|
52
|
+
# @param aggregate [Object, nil] unused
|
|
53
|
+
# @param settings [Hash] unused
|
|
54
|
+
# @param root [String, nil] unused
|
|
55
|
+
def initialize(aggregate: nil, settings: {}, root: nil); end
|
|
56
|
+
|
|
57
|
+
# Generates the domain's Rust source into the workspace, with a Cargo feature for it.
|
|
58
|
+
#
|
|
59
|
+
# @param held [Hash] the `Build` record: `domain` (its directory)
|
|
60
|
+
# @return [Hash{Symbol => Hash}] `output:` what the generator reported
|
|
61
|
+
# @raise [ConsoleCapture::Failure] when the domain cannot be generated, or the install has no
|
|
62
|
+
# Rust workspace to build in
|
|
63
|
+
def generate(**held)
|
|
64
|
+
child(:generate, [plain(held[:domain])])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Generates the domain, then compiles it to a `wasm32-wasip1` module.
|
|
68
|
+
#
|
|
69
|
+
# @param held [Hash] the `Build` record: `domain`
|
|
70
|
+
# @return [Hash{Symbol => Hash}] `output:` where the module was written
|
|
71
|
+
# @raise [ConsoleCapture::Failure] when the wasm target or the build is missing
|
|
72
|
+
def wasm(**held)
|
|
73
|
+
child(:wasm, [plain(held[:domain])])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Generates the domain, then compiles it to an ES module for a browser through wasm-bindgen.
|
|
77
|
+
#
|
|
78
|
+
# @param held [Hash] the `Build` record: `domain`
|
|
79
|
+
# @return [Hash{Symbol => Hash}] `output:` where the module was written
|
|
80
|
+
# @raise [ConsoleCapture::Failure] when the target, the wasm-bindgen version or the build is
|
|
81
|
+
# missing
|
|
82
|
+
def browser_wasm(**held)
|
|
83
|
+
child(:browser_wasm, [plain(held[:domain])])
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Replays a step script through the Ruby engine and, when an artifact is named, through that
|
|
87
|
+
# artifact too, and compares what each did.
|
|
88
|
+
#
|
|
89
|
+
# @param held [Hash] the `Build` record: `domain`, `script` (a JSON file of steps) and
|
|
90
|
+
# `artifact` (`native`, `build`, a `.wasm` file or a binary; Ruby's own result when absent)
|
|
91
|
+
# @return [Hash{Symbol => Hash}] `output:` the comparison, or Ruby's result as JSON
|
|
92
|
+
# @raise [ConsoleCapture::Failure] when the two disagree, or the artifact cannot be run
|
|
93
|
+
def conform(**held)
|
|
94
|
+
child(:conform, [plain(held[:domain]), plain(held[:script]), plain(held[:artifact])].compact)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Replays generated step sequences through the Ruby engine and an artifact.
|
|
98
|
+
#
|
|
99
|
+
# @param held [Hash] the `Build` record: `domain`, `artifact`, `seeds` (10 when absent) and
|
|
100
|
+
# `steps` (25 when absent)
|
|
101
|
+
# @return [Hash{Symbol => Hash}] `output:` how many sequences matched
|
|
102
|
+
# @raise [ConsoleCapture::Failure] at the first seed that diverges, naming how to reproduce it
|
|
103
|
+
def replay(**held)
|
|
104
|
+
argv = [plain(held[:domain]), plain(held[:artifact]), (plain(held[:seeds]) || 10).to_s,
|
|
105
|
+
(plain(held[:steps]) || 25).to_s]
|
|
106
|
+
child(:replay, argv)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Checks that every rule of the coverage allowlist still excuses a real gap.
|
|
110
|
+
#
|
|
111
|
+
# @param _held [Hash] the `Build` record, which holds nothing this needs
|
|
112
|
+
# @return [Hash{Symbol => Hash}] `output:` the check's verdict
|
|
113
|
+
# @raise [ConsoleCapture::Failure] when a rule excuses nothing
|
|
114
|
+
def audit(**_held)
|
|
115
|
+
child(:coverage, ["--check-allowlist"])
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Measures command throughput and latency for each target, building the Rust binary in the
|
|
119
|
+
# workspace when it is a target and none was named. The benchmark can run for minutes, so it
|
|
120
|
+
# starts through `ProcessPool`, which passes an interrupt on to it.
|
|
121
|
+
#
|
|
122
|
+
# @param held [Hash] the `FuzzRun` record: `domains`, `targets`, `iterations`, `warmup`,
|
|
123
|
+
# `runs`, `rust_binary`, `format` and `output` (a file the full JSON is also written to)
|
|
124
|
+
# @return [Hash{Symbol => Hash}] `report:` what the benchmark printed
|
|
125
|
+
# @raise [ConsoleCapture::Failure] when it could not run, or the install has no Rust workspace
|
|
126
|
+
def measure(**held)
|
|
127
|
+
flags = BENCH_FLAGS.filter_map { |flag, key| [flag, plain(held[key]).to_s] unless plain(held[key]).nil? }
|
|
128
|
+
env = (self.class.workspace || RustWorkspace.new).environment.merge("HECKS_NO_3_0_NOTICE" => "1")
|
|
129
|
+
command = [RbConfig.ruby, "-I", LIB, "-e", BENCH, "--", *flags.flatten]
|
|
130
|
+
finished = (self.class.pool || ProcessPool.new).run(command, env: env)
|
|
131
|
+
raise ConsoleCapture::Failure, finished.output.strip unless finished.ok?
|
|
132
|
+
|
|
133
|
+
{ report: { value: finished.output } }
|
|
134
|
+
rescue RustWorkspace::Unavailable => e
|
|
135
|
+
raise ConsoleCapture::Failure, e.message
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Reports whether each construct of a generated module has a routed implementation.
|
|
139
|
+
#
|
|
140
|
+
# @param module_name [Hash, String] the generated module (a domain's directory name)
|
|
141
|
+
# @param codegen [Hash, String, nil] `ruby` (the default) or `rust`: which generator's
|
|
142
|
+
# manifest to read
|
|
143
|
+
# @return [Hash] `text:` the report, gaps included: a gap is what it says, not a refusal
|
|
144
|
+
# @raise [ConsoleCapture::Failure] when there is no such module, or no report could be made
|
|
145
|
+
def rust_coverage(module_name:, codegen: nil)
|
|
146
|
+
argv = [plain(module_name)]
|
|
147
|
+
argv << "--codegen=#{plain(codegen)}" if plain(codegen)
|
|
148
|
+
result = run(:coverage, argv)
|
|
149
|
+
return { text: result.out } if result.ok? || result.out.start_with?("=" * 8)
|
|
150
|
+
|
|
151
|
+
raise ConsoleCapture::Failure, message_of(result)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def child(ask, argv)
|
|
157
|
+
result = run(ask, argv)
|
|
158
|
+
raise ConsoleCapture::Failure, message_of(result) unless result.ok?
|
|
159
|
+
|
|
160
|
+
{ output: { value: result.out } }
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def run(ask, argv)
|
|
164
|
+
space = self.class.workspace || RustWorkspace.new
|
|
165
|
+
env = space.environment
|
|
166
|
+
(self.class.runner || RustBuild).capture(TOOLS.fetch(ask), argv, env: env)
|
|
167
|
+
rescue RustWorkspace::Unavailable => e
|
|
168
|
+
raise ConsoleCapture::Failure, e.message
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def message_of(result)
|
|
172
|
+
text = [result.err, result.out].map(&:strip).reject(&:empty?).join("\n")
|
|
173
|
+
text.empty? ? "the build ended with status #{result.status}" : text
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|