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,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "open3"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module RustBuild
|
|
9
|
+
# Builds the native binary for one generated domain's Cargo feature, once per workspace.
|
|
10
|
+
#
|
|
11
|
+
# Examples interleave, and alternating `--features` builds forces a full recompile each time,
|
|
12
|
+
# so a built binary is cached per `[rust_dir, feature, sources]`, where `sources` is a digest of
|
|
13
|
+
# the workspace's Rust sources and manifests. Regenerating the domain changes the digest, so the
|
|
14
|
+
# next call rebuilds instead of answering with a stale binary or a stale failure.
|
|
15
|
+
module NativeBuild
|
|
16
|
+
# Raised when a declared feature fails to build; nil is reserved for "feature not declared".
|
|
17
|
+
class BuildFailed < StandardError; end
|
|
18
|
+
|
|
19
|
+
@cache = {}
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
# @return [Hash{Array => String, BuildFailed, nil}] each build's answer, keyed by
|
|
23
|
+
# `[rust_dir, feature, sources_digest]`
|
|
24
|
+
attr_reader :cache
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# Builds the binary for `domain_feature` once per (rust_dir, feature, sources) and
|
|
30
|
+
# memoizes the result.
|
|
31
|
+
#
|
|
32
|
+
# @param domain_feature [String] the Cargo feature, a domain's directory basename
|
|
33
|
+
# @param rust_dir [String] the workspace to build in
|
|
34
|
+
# @return [String, nil] the pinned binary, or nil when Cargo.toml declares no such feature
|
|
35
|
+
# @raise [BuildFailed] when the build fails (memoized too)
|
|
36
|
+
def build_rust_for(domain_feature, rust_dir)
|
|
37
|
+
cache = NativeBuild.cache
|
|
38
|
+
key = [rust_dir, domain_feature, sources_digest(rust_dir)]
|
|
39
|
+
if cache.key?(key)
|
|
40
|
+
raise cache[key] if cache[key].is_a?(BuildFailed)
|
|
41
|
+
|
|
42
|
+
return cache[key]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
manifest = File.read(File.join(rust_dir, "Cargo.toml"))
|
|
46
|
+
return cache[key] = nil unless manifest =~ /^#{Regexp.escape(domain_feature)}\s*=\s*\[\]/
|
|
47
|
+
|
|
48
|
+
begin
|
|
49
|
+
cache[key] = build_and_pin(domain_feature, rust_dir)
|
|
50
|
+
rescue BuildFailed => e
|
|
51
|
+
cache[key] = e
|
|
52
|
+
raise
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Fingerprints what a build reads: every `.rs`, `.toml` and `Cargo.lock` file under the
|
|
57
|
+
# workspace outside `target/`, by path, size and modification time.
|
|
58
|
+
#
|
|
59
|
+
# @param rust_dir [String] the workspace
|
|
60
|
+
# @return [String] a hex digest that changes when any of those files does
|
|
61
|
+
def sources_digest(rust_dir)
|
|
62
|
+
digest = Digest::SHA256.new
|
|
63
|
+
Dir.glob(File.join(rust_dir, "**", "*.{rs,toml}"), File::FNM_DOTMATCH).sort.each do |path|
|
|
64
|
+
digest_file(digest, path, rust_dir)
|
|
65
|
+
end
|
|
66
|
+
lock = File.join(rust_dir, "Cargo.lock")
|
|
67
|
+
digest_file(digest, lock, rust_dir) if File.file?(lock)
|
|
68
|
+
digest.hexdigest
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def digest_file(digest, path, rust_dir)
|
|
72
|
+
relative = path.delete_prefix("#{rust_dir}/")
|
|
73
|
+
return if relative.start_with?("target/") || !File.file?(path)
|
|
74
|
+
|
|
75
|
+
stat = File.stat(path)
|
|
76
|
+
digest << "#{relative}\0#{stat.size}\0#{stat.mtime.to_i}.#{stat.mtime.nsec}\n"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Holds an exclusive flock from `cargo build` through the copy-out: parallel sweeps share
|
|
80
|
+
# `target/debug/rust`, and another build could overwrite it before it is pinned. The lock
|
|
81
|
+
# file is left on disk.
|
|
82
|
+
#
|
|
83
|
+
# @param domain_feature [String] the Cargo feature
|
|
84
|
+
# @param rust_dir [String] the workspace to build in
|
|
85
|
+
# @return [String] the binary, pinned to `target/debug/rust-<feature>`
|
|
86
|
+
# @raise [BuildFailed] when the build fails or leaves no binary
|
|
87
|
+
def build_and_pin(domain_feature, rust_dir)
|
|
88
|
+
lock_path = File.join(rust_dir, "target", ".build_rust_for.lock")
|
|
89
|
+
FileUtils.mkdir_p(File.dirname(lock_path))
|
|
90
|
+
|
|
91
|
+
File.open(lock_path, File::CREAT | File::RDWR) do |lock|
|
|
92
|
+
lock.flock(File::LOCK_EX)
|
|
93
|
+
command = ["cargo", "build", "--no-default-features", "--features", domain_feature]
|
|
94
|
+
cargo(command, rust_dir, domain_feature)
|
|
95
|
+
pin(rust_dir, domain_feature, command)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def cargo(command, rust_dir, domain_feature)
|
|
100
|
+
_stdout, stderr, status = Open3.capture3(*command, chdir: rust_dir)
|
|
101
|
+
return if status.success?
|
|
102
|
+
|
|
103
|
+
raise BuildFailed, "`#{command.join(' ')}` failed in #{rust_dir} (exit #{status.exitstatus}) — " \
|
|
104
|
+
"#{domain_feature} is declared in Cargo.toml, so this is a build failure, " \
|
|
105
|
+
"not a missing feature:\n#{stderr}"
|
|
106
|
+
rescue SystemCallError => e
|
|
107
|
+
raise BuildFailed, "`#{command.join(' ')}` could not run in #{rust_dir}: #{e.message}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# `cargo build` always writes the same path; it is pinned per feature while the lock is held.
|
|
111
|
+
def pin(rust_dir, domain_feature, command)
|
|
112
|
+
binary = File.join(rust_dir, "target", "debug", "rust")
|
|
113
|
+
unless File.executable?(binary)
|
|
114
|
+
raise BuildFailed, "`#{command.join(' ')}` succeeded in #{rust_dir} but left no executable at #{binary}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
pinned = File.join(rust_dir, "target", "debug", "rust-#{domain_feature}")
|
|
118
|
+
FileUtils.cp(binary, pinned)
|
|
119
|
+
File.chmod(0o755, pinned)
|
|
120
|
+
pinned
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module RustBuild
|
|
5
|
+
class ProjectRust
|
|
6
|
+
# Writes `src/generated/mod.rs`: a `pub mod` per generated directory, the feature-gated
|
|
7
|
+
# `active` re-export of the selected domain, and a `compile_error!` for each pair of
|
|
8
|
+
# non-default domain features enabled together.
|
|
9
|
+
class RootMod
|
|
10
|
+
# @param file [IO] where the module is written
|
|
11
|
+
# @param directories [Array<String>] every directory under `src/generated`
|
|
12
|
+
# @param domains [Array<String>] the directories that carry their own `merged.rs`
|
|
13
|
+
# @param default [String] the domain this run generated, whose feature is the default
|
|
14
|
+
def initialize(file, directories, domains, default)
|
|
15
|
+
@file = file
|
|
16
|
+
@directories = directories
|
|
17
|
+
@domains = domains
|
|
18
|
+
@default = default
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [void]
|
|
22
|
+
def write
|
|
23
|
+
banner
|
|
24
|
+
modules
|
|
25
|
+
active_notes
|
|
26
|
+
reexports
|
|
27
|
+
conflict_guards
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def banner
|
|
33
|
+
@file.puts "// GENERATED by hecks project_rust — re-run it to refresh this list."
|
|
34
|
+
@file.puts "//"
|
|
35
|
+
@file.puts "// BUG#25 — every DOMAIN (an entry in `domains`, below: a directory"
|
|
36
|
+
@file.puts "// carrying its own merged.rs and therefore its own Cargo feature) is"
|
|
37
|
+
@file.puts "// declared behind that SAME feature, so a broken or absent domain's"
|
|
38
|
+
@file.puts "// generated code is never even compiled into a build that selects a"
|
|
39
|
+
@file.puts "// DIFFERENT domain — `cargo build --features waybill` used to pull in"
|
|
40
|
+
@file.puts "// every OTHER domain's `pub mod` unconditionally, so one domain's own"
|
|
41
|
+
@file.puts "// non-compiling generated code (a `has_many` field, before this fix)"
|
|
42
|
+
@file.puts "// broke every feature's build, not just its own. A shared FRAMEWORK"
|
|
43
|
+
@file.puts "// chapter (governance/identity — no merged.rs of its own, so absent"
|
|
44
|
+
@file.puts "// from `domains`) stays unconditional: it has no single feature of its"
|
|
45
|
+
@file.puts "// own to gate behind, and is compiled in by whichever domain(s) attach"
|
|
46
|
+
@file.puts "// it via `uses_framework`."
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def modules
|
|
50
|
+
@directories.each do |name|
|
|
51
|
+
@file.puts "#[cfg(feature = #{name.inspect})]" if @domains.include?(name)
|
|
52
|
+
@file.puts "pub mod #{name};"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def active_notes
|
|
57
|
+
@file.puts
|
|
58
|
+
@file.puts "// `active` is whichever ONE domain's own merged Store/dispatch table"
|
|
59
|
+
@file.puts "// is selected by Cargo feature (rust/Cargo.toml, kept in sync with this"
|
|
60
|
+
@file.puts "// list by hecks project_rust) — kernel/cli.rs imports"
|
|
61
|
+
@file.puts "// `crate::generated::active::{dispatch_by_name, Store, ...}` unchanged"
|
|
62
|
+
@file.puts "// no matter which domain that resolves to."
|
|
63
|
+
@file.puts "//"
|
|
64
|
+
@file.puts "// DOMAIN FEATURES ARE MUTUALLY EXCLUSIVE (R5) — Cargo has no native"
|
|
65
|
+
@file.puts "// concept of that, and `default = [#{@default.inspect}]` in"
|
|
66
|
+
@file.puts "// Cargo.toml stays enabled unless a build passes"
|
|
67
|
+
@file.puts "// `--no-default-features`, so a plain `cargo build --features banking`"
|
|
68
|
+
@file.puts "// used to enable BOTH the default domain's feature and banking's,"
|
|
69
|
+
@file.puts "// producing two `pub use ... as active;` imports and a hard E0252."
|
|
70
|
+
@file.puts "// Fixed two ways below, entirely mechanically from `domains`/"
|
|
71
|
+
@file.puts "// `target_mod_name` (this run's new default) — never hand-maintained:"
|
|
72
|
+
@file.puts "//"
|
|
73
|
+
@file.puts "// 1. THE DEFAULT DOMAIN'S OWN re-export backs off whenever any OTHER"
|
|
74
|
+
@file.puts "// domain feature is also enabled, so it never contends for `active`"
|
|
75
|
+
@file.puts "// by accident — `cargo build --features banking` (still implicitly"
|
|
76
|
+
@file.puts "// carrying the default feature) now resolves to banking alone,"
|
|
77
|
+
@file.puts "// same as if `--no-default-features` had been passed explicitly."
|
|
78
|
+
@file.puts "// 2. Two NON-default domain features enabled TOGETHER (a genuine,"
|
|
79
|
+
@file.puts "// not-accidental conflict — nothing makes that combination"
|
|
80
|
+
@file.puts "// meaningful) still fail the build, but with an explicit"
|
|
81
|
+
@file.puts "// `compile_error!` naming both features instead of a cryptic"
|
|
82
|
+
@file.puts "// \"defined multiple times\"."
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def reexports
|
|
86
|
+
@domains.each do |name|
|
|
87
|
+
other_domains = @domains - [name]
|
|
88
|
+
if name == @default && !other_domains.empty?
|
|
89
|
+
guard = other_domains.map { |o| "feature = #{o.inspect}" }.join(", ")
|
|
90
|
+
@file.puts "#[cfg(all(feature = #{name.inspect}, not(any(#{guard}))))]"
|
|
91
|
+
else
|
|
92
|
+
@file.puts "#[cfg(feature = #{name.inspect})]"
|
|
93
|
+
end
|
|
94
|
+
@file.puts "pub use #{name}::merged as active;"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def conflict_guards
|
|
99
|
+
non_default_domains = @domains - [@default]
|
|
100
|
+
if non_default_domains.size > 1
|
|
101
|
+
@file.puts
|
|
102
|
+
@file.puts "// Explicit conflict guard — see point 2 above. Only fires when TWO"
|
|
103
|
+
@file.puts "// non-default domain features are both turned on; the default"
|
|
104
|
+
@file.puts "// domain's own feature never reaches here (point 1 already excludes"
|
|
105
|
+
@file.puts "// it whenever any other domain feature is present)."
|
|
106
|
+
non_default_domains.combination(2).each do |a, b|
|
|
107
|
+
@file.puts "#[cfg(all(feature = #{a.inspect}, feature = #{b.inspect}))]"
|
|
108
|
+
# Plain `a`/`b`/`domains.join` here, never `.inspect` — this whole
|
|
109
|
+
# line already sits inside one Rust string literal
|
|
110
|
+
# (`compile_error!("...")`), and `.inspect`'s own quoted form
|
|
111
|
+
# would nest unescaped double quotes and produce invalid Rust.
|
|
112
|
+
@file.puts "compile_error!(\"domain features are mutually exclusive — enable only one of: #{@domains.join(', ')} " \
|
|
113
|
+
"(both #{a} and #{b} are enabled)\");"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
require_relative "../../hecks"
|
|
6
|
+
require_relative "../bluebook/meta_validator"
|
|
7
|
+
require_relative "../ports/persistence/plugins/era"
|
|
8
|
+
require_relative "../../../rust/project"
|
|
9
|
+
|
|
10
|
+
module Hecks
|
|
11
|
+
module RustBuild
|
|
12
|
+
# Generates Rust source for one domain into the workspace's `src/generated/`, and keeps the
|
|
13
|
+
# workspace's `Cargo.toml` features in step; `rust/project.rb` (`RustProjection`) holds the
|
|
14
|
+
# architecture of the generator itself.
|
|
15
|
+
#
|
|
16
|
+
# ProjectRust.call(["path/to/domain"])
|
|
17
|
+
#
|
|
18
|
+
# The era plugin is required unconditionally so the generator works for any domain, lineage
|
|
19
|
+
# capable or not; `pg` stays lazy inside it, so nothing here opens a database connection.
|
|
20
|
+
# With `HECKS_PARSER=rust` and `HECKS_CODEGEN=rust` together, the whole pipeline runs through
|
|
21
|
+
# `rust/project_rust_pipeline.rb` instead, with no Ruby load of the domain.
|
|
22
|
+
class ProjectRust
|
|
23
|
+
# The optional attachments `rust/host` reads from `ir.json`, each omitted when nothing
|
|
24
|
+
# attached provides it: exporter method, then the key it is written under.
|
|
25
|
+
SEAMS = %i[authorization membership identity newsletter newsletter_issues payments
|
|
26
|
+
registrations payment_connection].freeze
|
|
27
|
+
|
|
28
|
+
# @param argv [Array<String>] the domain's directory
|
|
29
|
+
# @return [Integer] the exit status
|
|
30
|
+
# @raise [Failure] when the domain's name cannot be a Rust module and Cargo feature name
|
|
31
|
+
def self.call(argv)
|
|
32
|
+
domain = argv.first or raise Failure, "usage: hecks project_rust <domain>"
|
|
33
|
+
new(domain).call
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param domain [String] the domain's directory
|
|
37
|
+
def initialize(domain)
|
|
38
|
+
@domain = domain
|
|
39
|
+
@mod_name = File.basename(domain)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Integer] the exit status
|
|
43
|
+
def call
|
|
44
|
+
validate_name!
|
|
45
|
+
if ENV["HECKS_PARSER"] == "rust" && ENV["HECKS_CODEGEN"] == "rust"
|
|
46
|
+
require_relative "../../../rust/project_rust_pipeline"
|
|
47
|
+
RustProjectPipeline.call(@domain)
|
|
48
|
+
else
|
|
49
|
+
generate
|
|
50
|
+
end
|
|
51
|
+
0
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# The name becomes a directory, a `pub mod` identifier and a Cargo feature, so it is checked
|
|
57
|
+
# before any side effect (the `meta/` directory is rewritten below).
|
|
58
|
+
def validate_name!
|
|
59
|
+
return if RustProjection::Projector.valid_domain_mod_name?(@mod_name)
|
|
60
|
+
|
|
61
|
+
raise Failure, "hecks project_rust: domain name #{@mod_name.inspect} (from #{@domain.inspect}) can't " \
|
|
62
|
+
"be used as-is — it has to double as a Rust module identifier and a Cargo feature " \
|
|
63
|
+
"name, and this one is either not a plain lowercase identifier, is a Rust keyword, " \
|
|
64
|
+
"or collides with a reserved Cargo.toml key " \
|
|
65
|
+
"(#{RustProjection::Projector::CARGO_RESERVED_DOMAIN_NAMES.join(', ')}). " \
|
|
66
|
+
"Rename the domain directory."
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def generate
|
|
70
|
+
load_registry
|
|
71
|
+
@rust_dir = ENV.fetch("HECKS_RUST_DIR", File.join(RustBuild::ROOT, "rust"))
|
|
72
|
+
@out_root = File.join(@rust_dir, "src/generated")
|
|
73
|
+
FileUtils.mkdir_p(@out_root)
|
|
74
|
+
build_target_ir
|
|
75
|
+
write_meta
|
|
76
|
+
write_target
|
|
77
|
+
write_root_mod
|
|
78
|
+
sync_cargo_features
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Round-trips a value through JSON so generators see the string-keyed shape a real `ir.json`
|
|
82
|
+
# carries, never live Ruby symbols.
|
|
83
|
+
def json_shaped(payload) = JSON.parse(JSON.generate(payload), symbolize_names: true)
|
|
84
|
+
|
|
85
|
+
# `root:` is the domain's own directory: a domain that declares `uses_embryonaut_bluebook`
|
|
86
|
+
# resolves its vendored chapters beneath it.
|
|
87
|
+
def load_registry
|
|
88
|
+
@registry = Hecks::Runtime::Registry.new(root: File.expand_path(@domain))
|
|
89
|
+
Hecks.with_registry(@registry) do
|
|
90
|
+
lib = File.expand_path("..", __dir__)
|
|
91
|
+
%w[ports/persistence.port ports/extraction.port adapters/driven/memory.adapter
|
|
92
|
+
adapters/driven/prism.adapter adapters/driven/postgres_era.adapter].each do |file|
|
|
93
|
+
Kernel.load(File.join(lib, file))
|
|
94
|
+
end
|
|
95
|
+
@bluebook_dir = File.join(@domain, "bluebook")
|
|
96
|
+
Hecks::Adapters::Folder.new.load_bluebooks(@bluebook_dir)
|
|
97
|
+
load_siblings
|
|
98
|
+
load_environment
|
|
99
|
+
end
|
|
100
|
+
@domain_name = @registry.bluebooks.keys.first
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Translation edges, hecksagons (whose `uses_framework` loads a framework chapter into the
|
|
104
|
+
# same registry) and worlds (whose `default_adapter` binds what a hecksagon leaves out), in
|
|
105
|
+
# the order the language loads them.
|
|
106
|
+
def load_siblings
|
|
107
|
+
Dir[File.join(@bluebook_dir, "translations", "*.bluebook")].each { |file| Kernel.load(file) }
|
|
108
|
+
Dir.glob(File.join(@bluebook_dir, "*.hecksagon")).each { |file| Kernel.load(file) }
|
|
109
|
+
Dir.glob(File.join(@bluebook_dir, "*.world")).each { |file| Kernel.load(file) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Production is the default environment when `environments/production.hecksagon` exists
|
|
113
|
+
# (`rust/host` is the production runtime); `HECKS_PROJECT_ENVIRONMENT` overrides it.
|
|
114
|
+
def load_environment
|
|
115
|
+
environment = ENV.fetch("HECKS_PROJECT_ENVIRONMENT") do
|
|
116
|
+
File.exist?(File.join(@bluebook_dir, "environments", "production.hecksagon")) ? "production" : nil
|
|
117
|
+
end
|
|
118
|
+
return if environment.nil? || environment.empty?
|
|
119
|
+
|
|
120
|
+
folder = Hecks::Adapters::Folder.new
|
|
121
|
+
folder.load_each(@bluebook_dir, [File.join("environments", "#{environment}.hecksagon")])
|
|
122
|
+
folder.load_each(@bluebook_dir, [File.join("environments", "#{environment}.world")])
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# The target's IR, with the binding facts that ride beside it (they are not shape facts, so
|
|
126
|
+
# `bluebook.to_h` never mentions them).
|
|
127
|
+
def build_target_ir
|
|
128
|
+
exporter = Hecks::Projector::Exporter
|
|
129
|
+
@ir = json_shaped(exporter.call(@registry).fetch(@domain_name))
|
|
130
|
+
@ir[:lineage] = json_shaped(exporter.lineage(@registry, @domain_name))
|
|
131
|
+
@ir[:persistence] = json_shaped(exporter.persistence(@registry, @domain_name))
|
|
132
|
+
seams = SEAMS.to_h { |seam| [seam, exporter.public_send(seam, @registry, @domain_name)] }
|
|
133
|
+
seams.each { |seam, value| @ir[seam] = json_shaped(value) unless value.empty? }
|
|
134
|
+
if !seams[:membership].empty? && seams[:identity].empty?
|
|
135
|
+
raise Failure, "#{@domain_name} provides membership but not identity — rust/host Google sign-in " \
|
|
136
|
+
"cannot register or link an identity from ir.json. Attach Identity " \
|
|
137
|
+
"(`uses_framework \"Identity\"` plus a sibling Hecks.hecksagon \"Identity\") so the " \
|
|
138
|
+
"hecksagon, not a deploy-time guess, names the identity verbs."
|
|
139
|
+
end
|
|
140
|
+
add_edges_and_source
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Edges carry their own precompiled SQL, so a boot-time mint only executes it. Committed
|
|
144
|
+
# approvals sit beside the edges. The source text is verbatim: the era's integrity digest is
|
|
145
|
+
# the SHA256 of it, not of anything re-derived from the parsed IR.
|
|
146
|
+
def add_edges_and_source
|
|
147
|
+
edges = Hecks::Projector::Exporter.translations(@registry).select { |edge| edge[:domain] == @domain_name }
|
|
148
|
+
@ir[:translations] = json_shaped(edges)
|
|
149
|
+
approvals = Hecks::Translation::ApprovalFile.read_all(@bluebook_dir)
|
|
150
|
+
@ir[:approvals] = json_shaped(approvals) unless approvals.empty?
|
|
151
|
+
@ir[:source_text] = Hecks::Runtime::EraCheck.source_text_for(
|
|
152
|
+
@registry.bluebooks.fetch(@domain_name), @bluebook_dir, registry: @registry
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# The self-hosted language goes through the same codegen as the target, read from the
|
|
157
|
+
# grammar registry `MetaValidator` boots with.
|
|
158
|
+
def write_meta
|
|
159
|
+
meta_ir = json_shaped(
|
|
160
|
+
Hecks::Projector::Exporter.call(Hecks::Bluebook::MetaValidator.grammar_registry).fetch("Bluebook")
|
|
161
|
+
)
|
|
162
|
+
dir = File.join(@out_root, "meta")
|
|
163
|
+
# Tracked per directory: several domains coexist on disk, and `pop_and_prune` deletes only
|
|
164
|
+
# the files this run never touched. `active` is a set of feature re-exports in the root
|
|
165
|
+
# `mod.rs`, never a directory.
|
|
166
|
+
RustProjection::WriteIfChanged.push_directory(dir)
|
|
167
|
+
FileUtils.rm_rf(File.join(@out_root, "active"))
|
|
168
|
+
result = RustProjection::DomainGenerator.call(
|
|
169
|
+
meta_ir, "the self-hosted language (lib/hecks/language/bluebook)", dir, "meta"
|
|
170
|
+
)
|
|
171
|
+
write_merged(File.join(dir, "merged.rs"), result[:aggregates], result[:queries], result[:read_models],
|
|
172
|
+
policies: RustProjection::Projector.emit_policy_table(meta_ir[:name], meta_ir[:policies],
|
|
173
|
+
meta_ir[:aggregates]),
|
|
174
|
+
cross: RustProjection::Projector.emit_cross_domain_policy_table(meta_ir[:name],
|
|
175
|
+
meta_ir[:policies]),
|
|
176
|
+
managers: meta_ir[:process_managers],
|
|
177
|
+
keys: [[meta_ir[:name], result[:aggregates].map { |a| a[:name] }]])
|
|
178
|
+
append_merged_mod(File.join(dir, "mod.rs"))
|
|
179
|
+
RustProjection::WriteIfChanged.pop_and_prune(dir)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def write_target
|
|
183
|
+
dir = File.join(@out_root, @mod_name)
|
|
184
|
+
RustProjection::WriteIfChanged.push_directory(dir)
|
|
185
|
+
result = RustProjection::DomainGenerator.call(@ir, @domain, dir, @mod_name)
|
|
186
|
+
chapters = write_chapters
|
|
187
|
+
aggregates = result[:aggregates] + chapters[:aggregates]
|
|
188
|
+
write_merged(File.join(dir, "merged.rs"), aggregates, result[:queries] + chapters[:queries],
|
|
189
|
+
result[:read_models] + chapters[:read_models],
|
|
190
|
+
policies: RustProjection::Projector.emit_merged_policy_table(chapters[:policy_sources]),
|
|
191
|
+
cross: RustProjection::Projector.emit_merged_cross_domain_policy_table(chapters[:policy_sources]),
|
|
192
|
+
managers: @ir[:process_managers] + chapters[:process_managers],
|
|
193
|
+
keys: reference_keys(result[:aggregates], chapters))
|
|
194
|
+
append_merged_mod(File.join(dir, "mod.rs"))
|
|
195
|
+
RustProjection::WriteIfChanged.pop_and_prune(dir)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Every other bluebook the target's `uses_framework` calls pulled into the registry, each
|
|
199
|
+
# generated into its own module. A framework chapter is a function of its bluebook alone, so
|
|
200
|
+
# regenerating one is safe whichever domain last touched it.
|
|
201
|
+
def write_chapters
|
|
202
|
+
totals = { aggregates: [], queries: [], read_models: [], process_managers: [],
|
|
203
|
+
policy_sources: [{ domain_name: @domain_name, policies: @ir[:policies],
|
|
204
|
+
aggregates: @ir[:aggregates] }],
|
|
205
|
+
mod_names: { @mod_name => @domain_name } }
|
|
206
|
+
vendored = @registry.hecksagons.values.flat_map(&:vendored_bluebooks)
|
|
207
|
+
(@registry.bluebooks.keys - [@domain_name]).each { |chapter| write_chapter(chapter, vendored, totals) }
|
|
208
|
+
totals
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def write_chapter(chapter_name, vendored, totals)
|
|
212
|
+
mod_name = chapter_name.downcase
|
|
213
|
+
totals[:mod_names][mod_name] = chapter_name
|
|
214
|
+
chapter_ir = json_shaped(Hecks::Projector::Exporter.call(@registry).fetch(chapter_name))
|
|
215
|
+
result = nil
|
|
216
|
+
RustProjection::WriteIfChanged.track_directory(File.join(@out_root, mod_name)) do
|
|
217
|
+
result = RustProjection::DomainGenerator.call(chapter_ir, "#{@domain} (#{attachment(chapter_name, vendored)})",
|
|
218
|
+
File.join(@out_root, mod_name), mod_name,
|
|
219
|
+
merged_module: false)
|
|
220
|
+
end
|
|
221
|
+
totals[:aggregates].concat(result[:aggregates])
|
|
222
|
+
totals[:queries].concat(result[:queries])
|
|
223
|
+
totals[:read_models].concat(result[:read_models])
|
|
224
|
+
totals[:process_managers].concat(chapter_ir[:process_managers])
|
|
225
|
+
totals[:policy_sources] << { domain_name: chapter_name, policies: chapter_ir[:policies],
|
|
226
|
+
aggregates: chapter_ir[:aggregates] }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# How the target attached a chapter, across every hecksagon the registry loaded: a chapter a
|
|
230
|
+
# sibling hecksagon vendors in is labelled as vendored.
|
|
231
|
+
def attachment(chapter_name, vendored)
|
|
232
|
+
name = vendored.find { |candidate| Hecks::Naming.pascal(candidate.to_s) == chapter_name }
|
|
233
|
+
name ? "uses_embryonaut_bluebook #{name.inspect}" : "uses_framework #{chapter_name.inspect}"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def reference_keys(target_aggregates, chapters)
|
|
237
|
+
chapters[:mod_names].map do |mod_name, chapter_name|
|
|
238
|
+
own = mod_name == @mod_name ? target_aggregates : chapters[:aggregates].select { |a| a[:chapter_mod] == mod_name }
|
|
239
|
+
[chapter_name, own.map { |a| a[:name] }]
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Writes a module's `merged.rs`: the registry and every dispatch table over its aggregates.
|
|
244
|
+
def write_merged(path, aggregates, queries, read_models, policies:, cross:, managers:, keys:)
|
|
245
|
+
projector = RustProjection::Projector
|
|
246
|
+
wrote = RustProjection::WriteIfChanged.block(path) do |file|
|
|
247
|
+
[projector.emit_registry(aggregates), projector.emit_reference_lookup(aggregates), policies, cross,
|
|
248
|
+
projector.emit_process_manager_table(managers), projector.emit_reference_key_table(keys),
|
|
249
|
+
projector.emit_creates_table(aggregates), projector.emit_identity_head_table(aggregates),
|
|
250
|
+
projector.emit_entity_identity_head_table(aggregates),
|
|
251
|
+
projector.emit_command_attributes_table(aggregates), projector.emit_query_table(queries),
|
|
252
|
+
projector.emit_query_arg_check_table(queries)].each do |table|
|
|
253
|
+
file.puts table
|
|
254
|
+
file.puts
|
|
255
|
+
end
|
|
256
|
+
# A read model's `group_by` function is written before the table names it.
|
|
257
|
+
read_models.each do |model|
|
|
258
|
+
next unless model[:group_by_fn_body]
|
|
259
|
+
|
|
260
|
+
file.puts model[:group_by_fn_body]
|
|
261
|
+
file.puts
|
|
262
|
+
end
|
|
263
|
+
file.puts projector.emit_read_model_table(read_models)
|
|
264
|
+
end
|
|
265
|
+
puts(wrote ? "wrote #{path}" : "#{path} unchanged")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Appends the `pub mod merged;` line once; appending it again would grow the file and bump
|
|
269
|
+
# its mtime on every run.
|
|
270
|
+
def append_merged_mod(path)
|
|
271
|
+
return if File.exist?(path) && File.read(path).include?("pub mod merged;")
|
|
272
|
+
|
|
273
|
+
File.open(path, "a") { |file| file.puts "pub mod merged;" }
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# `src/generated/mod.rs`: every domain ever generated, scanned off disk. A directory is a
|
|
277
|
+
# selectable domain exactly when it carries its own `merged.rs`; a framework chapter has
|
|
278
|
+
# none and is always compiled in.
|
|
279
|
+
def write_root_mod
|
|
280
|
+
all_dirs = Dir.children(@out_root).select { |name| File.directory?(File.join(@out_root, name)) }.sort
|
|
281
|
+
@domains = all_dirs.select { |name| File.exist?(File.join(@out_root, name, "merged.rs")) }
|
|
282
|
+
path = File.join(@out_root, "mod.rs")
|
|
283
|
+
wrote = RustProjection::WriteIfChanged.block(path) do |file|
|
|
284
|
+
RootMod.new(file, all_dirs, @domains, @mod_name).write
|
|
285
|
+
end
|
|
286
|
+
puts(wrote ? "wrote #{path}" : "#{path} unchanged")
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# One Cargo feature per domain on disk (added when missing, never removed), with `default`
|
|
290
|
+
# set to this run's domain so a bare `cargo build` builds it. A feature is inserted right
|
|
291
|
+
# after `default = [...]`, not appended: past `[[bin]]` it would parse into that table.
|
|
292
|
+
def sync_cargo_features
|
|
293
|
+
path = File.join(@rust_dir, "Cargo.toml")
|
|
294
|
+
manifest = File.read(path)
|
|
295
|
+
manifest = manifest.sub(/\A/, FEATURES_HEADER) unless manifest.include?("[features]")
|
|
296
|
+
@domains.each { |name| manifest = add_feature(manifest, name) }
|
|
297
|
+
manifest = manifest.sub(/^default\s*=.*$/, "default = [#{@mod_name.inspect}]")
|
|
298
|
+
# An unchanged manifest is not rewritten: a new mtime makes Cargo rebuild the whole crate.
|
|
299
|
+
if RustProjection::WriteIfChanged.call(path, manifest)
|
|
300
|
+
puts "wrote #{path} (default feature: #{@mod_name})"
|
|
301
|
+
else
|
|
302
|
+
puts "#{path} unchanged (default feature already #{@mod_name})"
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Checked against the `[features]` table only: `[package]`'s `name` or a `[[bin]]` path can
|
|
307
|
+
# share a word with a domain name.
|
|
308
|
+
def add_feature(manifest, name)
|
|
309
|
+
table = manifest[/^\[features\](?:\n(?!\[).*)*$/] || ""
|
|
310
|
+
return manifest if table =~ /^#{Regexp.escape(name)}\s*=/
|
|
311
|
+
|
|
312
|
+
manifest.sub(/^default\s*=.*$/) { "#{Regexp.last_match(0)}\n#{name} = []" }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
FEATURES_HEADER = <<~TOML
|
|
316
|
+
# One feature per generated domain: it selects which domain's own
|
|
317
|
+
# generated::<domain>::merged module `generated::active` re-exports
|
|
318
|
+
# (rust/src/generated/mod.rs). `hecks project_rust` adds a feature when a new domain is
|
|
319
|
+
# generated and never removes one (the domain's own generated/<name>/ directory is the
|
|
320
|
+
# source of truth for whether it exists). `default` tracks the domain generated most
|
|
321
|
+
# recently, so a bare `cargo build` keeps working; any other still-generated domain stays
|
|
322
|
+
# reachable via `--no-default-features --features <name>`.
|
|
323
|
+
[features]
|
|
324
|
+
default = []
|
|
325
|
+
|
|
326
|
+
TOML
|
|
327
|
+
private_constant :FEATURES_HEADER
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
require_relative "project_rust/root_mod"
|