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
|
@@ -5,7 +5,7 @@ require "uri"
|
|
|
5
5
|
require_relative "sql_query_builder"
|
|
6
6
|
require_relative "sqlite/schema_builder"
|
|
7
7
|
require_relative "sqlite/codec"
|
|
8
|
-
require_relative "sqlite"
|
|
8
|
+
require_relative "sqlite"
|
|
9
9
|
require_relative "../../ports/persistence/append_only"
|
|
10
10
|
require_relative "../../query_specification/common/null_policy"
|
|
11
11
|
require_relative "../../query_specification/common/order_by"
|
|
@@ -15,59 +15,23 @@ require_relative "../../runtime/instance"
|
|
|
15
15
|
|
|
16
16
|
module Hecks
|
|
17
17
|
module Adapters
|
|
18
|
-
# Cloudflare D1
|
|
19
|
-
#
|
|
20
|
-
# reuses Sqlite::SchemaBuilder and Sqlite::Codec unchanged (the DDL
|
|
21
|
-
# and the column encode/decode) and SqlQueryBuilder's dialect hooks
|
|
22
|
-
# are copied near-verbatim from sqlite.rb — the only real difference
|
|
23
|
-
# is the transport (D1::Connection, an HTTP call per query, vs a
|
|
24
|
-
# persistent local sqlite3 handle). See sqlite.rb's own header
|
|
25
|
-
# comment: "this file supplies only SQLite's dialect" — true here too.
|
|
18
|
+
# Cloudflare D1 (managed SQLite over REST): reuses Sqlite's schema and codec unchanged.
|
|
19
|
+
# Only the transport differs, one HTTP call per query.
|
|
26
20
|
class D1
|
|
27
|
-
#
|
|
28
|
-
# interface (execute/get_first_row/get_first_value, rows as
|
|
29
|
-
# column-name-keyed hashes) that Sqlite::SchemaBuilder, Sqlite::Codec,
|
|
30
|
-
# and this file's own methods already assume. One stateless HTTP call
|
|
31
|
-
# per execute, not a persistent connection — D1 has no connection to
|
|
32
|
-
# hold open.
|
|
21
|
+
# HTTP transport exposing the slice of `SQLite3::Database` the shared SQLite code uses.
|
|
33
22
|
class Connection
|
|
34
23
|
ENDPOINT = "https://api.cloudflare.com/client/v4".freeze
|
|
35
24
|
|
|
36
|
-
# @param account_id [String] the Cloudflare account that owns the database
|
|
37
|
-
# @param database_id [String] the D1 database's id
|
|
38
|
-
# @param api_token [String] a Cloudflare API token, sent as a bearer token on every
|
|
39
|
-
# request
|
|
40
25
|
def initialize(account_id:, database_id:, api_token:)
|
|
41
26
|
@uri = URI("#{ENDPOINT}/accounts/#{account_id}/d1/database/#{database_id}/query")
|
|
42
27
|
@api_token = api_token
|
|
43
28
|
end
|
|
44
29
|
|
|
45
|
-
# Runs one statement in its own HTTP request and returns its rows.
|
|
46
|
-
#
|
|
47
|
-
# @param sql [String] the statement, with `?` placeholders
|
|
48
|
-
# @param binds [Array<Object>] one value per placeholder, in order
|
|
49
|
-
# @return [Array<Hash{String => Object}>] the result rows keyed by column name; `[]`
|
|
50
|
-
# for a statement that returns none
|
|
51
|
-
# @raise [Runtime::WiringError] if D1 reports the query failed or answers with a body
|
|
52
|
-
# that is not JSON
|
|
53
30
|
def execute(sql, binds = [])
|
|
54
31
|
response_results({ sql: sql, params: binds }).first.fetch("results", [])
|
|
55
32
|
end
|
|
56
33
|
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
# D1 batches are SQL transactions: statements execute in order and a
|
|
60
|
-
# failure rolls the entire sequence back. Keep the tuple-shaped local
|
|
61
|
-
# seam small so adapter code and focused fakes do not need to know the
|
|
62
|
-
# REST request envelope.
|
|
63
|
-
# https://developers.cloudflare.com/d1/worker-api/d1-database/#batch
|
|
64
|
-
#
|
|
65
|
-
# @param statements [Array<Array(String, Array)>] `[sql, binds]` pairs in execution
|
|
66
|
-
# order; nil binds mean none
|
|
67
|
-
# @return [Array<Array<Hash{String => Object}>>] each statement's result rows, in
|
|
68
|
-
# the order given
|
|
69
|
-
# @raise [Runtime::WiringError] if D1 reports the request or any one statement failed,
|
|
70
|
-
# or answers with a body that is not JSON
|
|
34
|
+
# D1 batches are transactions: statements run in order and a failure rolls all back.
|
|
71
35
|
def batch(statements)
|
|
72
36
|
payload = {
|
|
73
37
|
batch: statements.map do |sql, binds|
|
|
@@ -104,11 +68,7 @@ module Hecks
|
|
|
104
68
|
raise Runtime::WiringError, "D1 query failed: non-JSON response (HTTP #{response.code}): #{response.body}"
|
|
105
69
|
end
|
|
106
70
|
|
|
107
|
-
#
|
|
108
|
-
# a per-statement `failed["error"]`/`failed["message"]` (checked
|
|
109
|
-
# by key presence, not truthiness, so an explicit `nil` still
|
|
110
|
-
# counts as "the key was there") is always more specific to which
|
|
111
|
-
# statement failed, when either is present.
|
|
71
|
+
# Prefers the statement's own error/message (by key presence) over the whole-response one.
|
|
112
72
|
def failed_statement_detail(failed, messages)
|
|
113
73
|
detail =
|
|
114
74
|
if failed.key?("error")
|
|
@@ -123,26 +83,10 @@ module Hecks
|
|
|
123
83
|
|
|
124
84
|
public
|
|
125
85
|
|
|
126
|
-
# Runs one statement and keeps only its first row, as `SQLite3::Database` does.
|
|
127
|
-
#
|
|
128
|
-
# @param sql [String] the statement, with `?` placeholders
|
|
129
|
-
# @param binds [Array<Object>] one value per placeholder, in order
|
|
130
|
-
# @return [Hash{String => Object}, nil] the first row keyed by column name, or nil when
|
|
131
|
-
# the statement returned none
|
|
132
|
-
# @raise [Runtime::WiringError] if D1 reports the query failed or answers with a body
|
|
133
|
-
# that is not JSON
|
|
134
86
|
def get_first_row(sql, binds = [])
|
|
135
87
|
execute(sql, binds).first
|
|
136
88
|
end
|
|
137
89
|
|
|
138
|
-
# Runs one statement and keeps only the first column of its first row.
|
|
139
|
-
#
|
|
140
|
-
# @param sql [String] the statement, with `?` placeholders
|
|
141
|
-
# @param binds [Array<Object>] one value per placeholder, in order
|
|
142
|
-
# @return [Object, nil] the value as D1's JSON carries it, or nil when the statement
|
|
143
|
-
# returned no row
|
|
144
|
-
# @raise [Runtime::WiringError] if D1 reports the query failed or answers with a body
|
|
145
|
-
# that is not JSON
|
|
146
90
|
def get_first_value(sql, binds = [])
|
|
147
91
|
get_first_row(sql, binds)&.values&.first
|
|
148
92
|
end
|
|
@@ -156,22 +100,11 @@ module Hecks
|
|
|
156
100
|
|
|
157
101
|
attr_reader :aggregate
|
|
158
102
|
|
|
159
|
-
# Names the optional persistence capabilities `Ports::Persistence::AppendOnly` may rely on.
|
|
160
|
-
#
|
|
161
|
-
# @return [Array<Symbol>] `[:atomic_put]`
|
|
162
103
|
def persistence_capabilities = [:atomic_put]
|
|
163
104
|
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
# @param aggregate [Bluebook::Aggregate] the aggregate whose table this adapter owns
|
|
168
|
-
# @param settings [Hash{Symbol, String => Object}] world settings for the binding:
|
|
169
|
-
# `account_id`, `database_id` and `api_token` (all required) and `domain` (scopes saga
|
|
170
|
-
# rows, default the aggregate's name), each read under a Symbol or a String key
|
|
171
|
-
# @param root [String, nil] project root directory; accepted for the shared adapter
|
|
172
|
-
# constructor shape and ignored
|
|
173
|
-
# @raise [Runtime::WiringError] if a required setting is missing or empty, or D1 rejects
|
|
174
|
-
# a table-creation statement
|
|
105
|
+
# Creates the aggregate, journal, event and saga tables if absent.
|
|
106
|
+
# Settings: `account_id`, `database_id`, `api_token` (required) and `domain` (saga scope).
|
|
107
|
+
# @raise [Runtime::WiringError] if a required setting is missing or empty
|
|
175
108
|
def initialize(aggregate:, settings: {}, root: nil)
|
|
176
109
|
@aggregate = aggregate
|
|
177
110
|
|
|
@@ -183,12 +116,7 @@ module Hecks
|
|
|
183
116
|
end
|
|
184
117
|
|
|
185
118
|
@db = Connection.new(account_id: account_id, database_id: database_id, api_token: api_token)
|
|
186
|
-
#
|
|
187
|
-
# (§2/§4) — D1's domain isolation is by whole-database identity
|
|
188
|
-
# (one D1 database per domain in practice), so unlike Sqlite's
|
|
189
|
-
# own per-aggregate-file default, there's no "which file does
|
|
190
|
-
# this end up in" ambiguity here: every aggregate on D1 within a
|
|
191
|
-
# domain already shares one database.
|
|
119
|
+
# Saga rows are scoped by domain; one D1 database per domain, so aggregates share it.
|
|
192
120
|
@domain = (
|
|
193
121
|
if settings.key?(:domain)
|
|
194
122
|
settings[:domain]
|
|
@@ -199,9 +127,7 @@ module Hecks
|
|
|
199
127
|
end
|
|
200
128
|
).to_s
|
|
201
129
|
|
|
202
|
-
# No PRAGMA synchronous
|
|
203
|
-
# durable service; there is no local fsync policy for a caller to
|
|
204
|
-
# tune, and the query endpoint has no PRAGMA write-access to it.
|
|
130
|
+
# No PRAGMA synchronous: D1 is managed and its query endpoint disallows PRAGMA writes.
|
|
205
131
|
create_aggregate_table!
|
|
206
132
|
create_entry_table!
|
|
207
133
|
ensure_entry_operation_column!
|
|
@@ -210,16 +136,8 @@ module Hecks
|
|
|
210
136
|
create_saga_table!
|
|
211
137
|
end
|
|
212
138
|
|
|
213
|
-
# Names the aggregate's table; the journal table is keyed off it.
|
|
214
|
-
#
|
|
215
|
-
# @return [String] the aggregate's snake_case storage name, unquoted
|
|
216
139
|
def table = @aggregate.storage_name
|
|
217
140
|
|
|
218
|
-
# Reads the current row for one aggregate identity.
|
|
219
|
-
#
|
|
220
|
-
# @param id [String, Object] the aggregate identity, bound as `id.to_s`
|
|
221
|
-
# @return [Runtime::Instance, nil] the decoded record, or nil when no row has that id
|
|
222
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
223
141
|
def find(id)
|
|
224
142
|
row = @db.get_first_row("SELECT * FROM #{quoted_table} WHERE id = ?", [id.to_s])
|
|
225
143
|
return nil unless row
|
|
@@ -227,19 +145,8 @@ module Hecks
|
|
|
227
145
|
Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row))
|
|
228
146
|
end
|
|
229
147
|
|
|
230
|
-
# Lists every
|
|
231
|
-
#
|
|
232
|
-
# order_by is a runtime value — see postgres.rb's own all for the
|
|
233
|
-
# full reasoning; whitelisted the identical way, same order_clause
|
|
234
|
-
# Sqlite's own all reuses (D1 speaks the identical dialect).
|
|
235
|
-
#
|
|
236
|
-
# @param order_by [String, Symbol, nil] attribute (or dotted value-object path) to sort
|
|
237
|
-
# by, with id as the tie-break; nil orders by id alone
|
|
238
|
-
# @param direction [Symbol, String] `:asc` or `:desc`, case-insensitive; anything else
|
|
239
|
-
# sorts ascending
|
|
240
|
-
# @return [Array<Runtime::Instance>] the decoded records, `[]` when the table is empty
|
|
241
|
-
# @raise [Runtime::WiringError] if `order_by` names no attribute of the aggregate, or D1
|
|
242
|
-
# rejects the statement
|
|
148
|
+
# Lists every record, ordered by id or by `order_by` when it names an attribute.
|
|
149
|
+
# @raise [Runtime::WiringError] if `order_by` names no attribute of the aggregate
|
|
243
150
|
def all(order_by: nil, direction: :asc)
|
|
244
151
|
order_sql = "ORDER BY id"
|
|
245
152
|
if order_by
|
|
@@ -258,37 +165,17 @@ module Hecks
|
|
|
258
165
|
end
|
|
259
166
|
end
|
|
260
167
|
|
|
261
|
-
# Counts the rows in the aggregate's table, deleted records excluded.
|
|
262
|
-
#
|
|
263
|
-
# @return [Integer] number of current records
|
|
264
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
265
168
|
def count = @db.get_first_value("SELECT COUNT(*) FROM #{quoted_table}").to_i
|
|
266
169
|
|
|
267
|
-
# Inserts one journal row in its own HTTP request.
|
|
268
|
-
#
|
|
269
|
-
# @param entry [Ports::Persistence::Entry] the save or delete to journal; `state` is
|
|
270
|
-
# encoded through the state codec and `mirrors` stored as JSON, or NULL when nil
|
|
271
|
-
# @return [Ports::Persistence::Entry] the same `entry`
|
|
272
|
-
# @raise [Runtime::WiringError] if D1 rejects the insert
|
|
273
170
|
def append(entry)
|
|
274
171
|
@db.execute(
|
|
275
172
|
"INSERT INTO #{quoted_entry_table} (aggregate_id, operation, state, mirrors) VALUES (?, ?, ?, ?)",
|
|
276
|
-
#
|
|
277
|
-
# mirrors hash must bind a real SQL NULL, not the four-character
|
|
278
|
-
# JSON text `"null"` (`JSON.generate(nil)`), or a future `IS NULL`
|
|
279
|
-
# check against it would never match. Same guard `postgres_era.rb`
|
|
280
|
-
# already uses for its own journal's `mirrors` column.
|
|
173
|
+
# Absent mirrors bind SQL NULL, not the JSON text "null" (the column is nullable).
|
|
281
174
|
[entry.id, entry.operation, state_json(entry.state), entry.mirrors && JSON.generate(entry.mirrors)]
|
|
282
175
|
)
|
|
283
176
|
entry
|
|
284
177
|
end
|
|
285
178
|
|
|
286
|
-
# Replaces or deletes the aggregate's row for one journal entry.
|
|
287
|
-
#
|
|
288
|
-
# @param entry [Ports::Persistence::Entry] the save or delete to materialize
|
|
289
|
-
# @return [Runtime::Instance, Array] for a save, a new instance over the entry's state;
|
|
290
|
-
# for a delete, the `DELETE` statement's empty result rows
|
|
291
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
292
179
|
def project(entry)
|
|
293
180
|
return @db.execute("DELETE FROM #{quoted_table} WHERE id = ?", [entry.id]) if entry.delete?
|
|
294
181
|
|
|
@@ -304,13 +191,7 @@ module Hecks
|
|
|
304
191
|
instance
|
|
305
192
|
end
|
|
306
193
|
|
|
307
|
-
#
|
|
308
|
-
#
|
|
309
|
-
# @return [Array<Ports::Persistence::Entry>] every journalled entry, state decoded
|
|
310
|
-
# through the state codec and `mirrors` parsed with String keys (nil when none were
|
|
311
|
-
# stored); a NULL `operation` reads as `"save"`; `[]` when nothing has been appended
|
|
312
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
313
|
-
# @raise [JSON::ParserError] if a stored `state` or `mirrors` value is not valid JSON
|
|
194
|
+
# The whole journal in append order, for `AppendOnly#recover!` to replay.
|
|
314
195
|
def entries
|
|
315
196
|
@db.execute("SELECT aggregate_id, operation, state, mirrors FROM #{quoted_entry_table} ORDER BY sequence").map do |row|
|
|
316
197
|
state = JSON.parse(row["state"])
|
|
@@ -323,70 +204,25 @@ module Hecks
|
|
|
323
204
|
end
|
|
324
205
|
end
|
|
325
206
|
|
|
326
|
-
#
|
|
327
|
-
# are left in place.
|
|
328
|
-
#
|
|
329
|
-
# @return [Adapters::D1] self
|
|
330
|
-
# @raise [Runtime::WiringError] if D1 rejects a statement
|
|
207
|
+
# Clears the aggregate table and its journal; events and saga rows stay.
|
|
331
208
|
def reset!
|
|
332
209
|
@db.execute("DELETE FROM #{quoted_table}")
|
|
333
210
|
@db.execute("DELETE FROM #{quoted_entry_table}")
|
|
334
211
|
self
|
|
335
212
|
end
|
|
336
213
|
|
|
337
|
-
# Journals
|
|
338
|
-
# requests rather than one batch.
|
|
339
|
-
#
|
|
340
|
-
# @param instance [Runtime::Instance] the instance to store
|
|
341
|
-
# @return [Runtime::Instance] a new instance over a shallow copy of the saved state
|
|
342
|
-
# @raise [Runtime::WiringError] if D1 rejects either statement; a journal row already
|
|
343
|
-
# inserted stays
|
|
214
|
+
# Journals then projects as two HTTP requests; the journal row stays if projecting fails.
|
|
344
215
|
def save(instance)
|
|
345
216
|
entry = Ports::Persistence::Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
|
|
346
217
|
append(entry)
|
|
347
218
|
project(entry)
|
|
348
219
|
end
|
|
349
220
|
|
|
350
|
-
# Stores an entry
|
|
351
|
-
# batched HTTP request.
|
|
352
|
-
#
|
|
353
|
-
# Classification, durable journal append and current-state projection
|
|
354
|
-
# are one D1 batch transaction and therefore one HTTP request. The first
|
|
355
|
-
# statement supplies the outcome from database state inside that same
|
|
356
|
-
# transaction; the runtime performs no preliminary find.
|
|
221
|
+
# Stores an entry in one D1 batch; returns `:inserted`, `:replaced` or `:conflicted`.
|
|
357
222
|
#
|
|
358
|
-
#
|
|
359
|
-
#
|
|
360
|
-
#
|
|
361
|
-
# pass that check before either wrote). D1's batch has no conditional
|
|
362
|
-
# branch of its own, true, but it does not need one: a batch's own
|
|
363
|
-
# statements already execute in order, atomically, as one transaction
|
|
364
|
-
# (Connection#batch's own comment) — the exact guarantee the single-
|
|
365
|
-
# connection adapters' own `@db.transaction do ... end` gets locally.
|
|
366
|
-
# So the existence check sits inside the batch as its own first
|
|
367
|
-
# statement, and the two writes are individually gated with `WHERE NOT
|
|
368
|
-
# EXISTS (...)` against that same table, evaluated in the same
|
|
369
|
-
# transaction — a row that already existed makes both writes into
|
|
370
|
-
# real, zero-row no-ops rather than skipping them from the Ruby side,
|
|
371
|
-
# matching Sqlite#atomic_put's `next` (skip append and project both,
|
|
372
|
-
# together) with no second HTTP call and no gap for another writer to
|
|
373
|
-
# land in between the check and the write.
|
|
374
|
-
#
|
|
375
|
-
# Three SQL statements, built here and batched together as one
|
|
376
|
-
# transaction below — see the paragraph above on the real TOCTOU gap
|
|
377
|
-
# this exact shape closes (the existence check inside the
|
|
378
|
-
# batch, not run as a separate earlier round trip). Splitting the
|
|
379
|
-
# per-statement builders out would still need columns/values/slots/
|
|
380
|
-
# not_exists/quoted_table threaded into each, and would separate
|
|
381
|
-
# three pieces of one atomic batch across methods with no single
|
|
382
|
-
# place left to see that they are, together, the fix.
|
|
383
|
-
#
|
|
384
|
-
# @param entry [Ports::Persistence::Entry] the save to store
|
|
385
|
-
# @param insert_only [Boolean] when true, an existing row turns both writes into
|
|
386
|
-
# zero-row no-ops
|
|
387
|
-
# @return [Symbol] `:inserted`, `:replaced`, or `:conflicted` when `insert_only` met an
|
|
388
|
-
# existing row and nothing was written
|
|
389
|
-
# @raise [Runtime::WiringError] if D1 rejects the batch; the whole batch is rolled back
|
|
223
|
+
# The existence check is the batch's first statement and both writes are gated by
|
|
224
|
+
# WHERE NOT EXISTS, so `insert_only` has no gap between check and write.
|
|
225
|
+
# @return [Symbol] `:conflicted` only when `insert_only` met an existing row
|
|
390
226
|
# rubocop:disable-next Metrics/AbcSize
|
|
391
227
|
# rubocop:disable-next Metrics/MethodLength
|
|
392
228
|
def atomic_put(entry, insert_only: false)
|
|
@@ -405,7 +241,7 @@ module Hecks
|
|
|
405
241
|
"THEN 'replaced' ELSE 'inserted' END AS status"
|
|
406
242
|
end
|
|
407
243
|
|
|
408
|
-
# `mirrors` is nullable
|
|
244
|
+
# `mirrors` is nullable; see `append`.
|
|
409
245
|
encoded_mirrors = entry.mirrors && JSON.generate(entry.mirrors)
|
|
410
246
|
|
|
411
247
|
entry_sql, entry_binds =
|
|
@@ -444,12 +280,6 @@ module Hecks
|
|
|
444
280
|
results.fetch(0).fetch(0).fetch("status").to_sym
|
|
445
281
|
end
|
|
446
282
|
|
|
447
|
-
# Journals a delete and then removes the row, whether or not a row exists, as two
|
|
448
|
-
# separate HTTP requests.
|
|
449
|
-
#
|
|
450
|
-
# @param id [String, Object] the aggregate identity, journalled as `id.to_s`
|
|
451
|
-
# @return [Boolean] always true
|
|
452
|
-
# @raise [Runtime::WiringError] if D1 rejects either statement
|
|
453
283
|
def delete(id)
|
|
454
284
|
entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
|
|
455
285
|
append(entry)
|
|
@@ -457,11 +287,6 @@ module Hecks
|
|
|
457
287
|
true
|
|
458
288
|
end
|
|
459
289
|
|
|
460
|
-
# Inserts an emitted event into the database's shared `events` table.
|
|
461
|
-
#
|
|
462
|
-
# @param event [Runtime::Event] the emitted event; `payload` is stored as JSON
|
|
463
|
-
# @return [Array] the insert's empty result rows; callers ignore it
|
|
464
|
-
# @raise [Runtime::WiringError] if D1 rejects the insert
|
|
465
290
|
def record_event(event)
|
|
466
291
|
@db.execute(
|
|
467
292
|
"INSERT INTO events (name, aggregate, aggregate_id, payload, occurred_at) VALUES (?, ?, ?, ?, ?)",
|
|
@@ -469,12 +294,7 @@ module Hecks
|
|
|
469
294
|
)
|
|
470
295
|
end
|
|
471
296
|
|
|
472
|
-
#
|
|
473
|
-
# table, not only this aggregate's rows.
|
|
474
|
-
#
|
|
475
|
-
# @return [Array<Runtime::Event>] the stored events, `payload` parsed with Symbol keys
|
|
476
|
-
# and `occurred_at` as stored; `[]` when none are recorded
|
|
477
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
297
|
+
# Every recorded event in the shared `events` table, not only this aggregate's.
|
|
478
298
|
def events
|
|
479
299
|
@db.execute("SELECT * FROM events ORDER BY id").map do |row|
|
|
480
300
|
Runtime::Event.new(
|
|
@@ -487,13 +307,24 @@ module Hecks
|
|
|
487
307
|
end
|
|
488
308
|
end
|
|
489
309
|
|
|
490
|
-
#
|
|
491
|
-
#
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
310
|
+
# One record's recorded events, oldest first — pushed down as a `WHERE` clause
|
|
311
|
+
# (`hecks_events_aggregate_id_idx`) instead of filtering `#events`'s whole-table read.
|
|
312
|
+
def events_for(aggregate:, id:)
|
|
313
|
+
@db.execute(
|
|
314
|
+
"SELECT * FROM events WHERE aggregate = ? AND aggregate_id = ? ORDER BY id",
|
|
315
|
+
[aggregate, id.to_s]
|
|
316
|
+
).map do |row|
|
|
317
|
+
Runtime::Event.new(
|
|
318
|
+
name: row["name"],
|
|
319
|
+
aggregate: row["aggregate"],
|
|
320
|
+
id: row["aggregate_id"],
|
|
321
|
+
payload: JSON.parse(row["payload"], symbolize_names: true),
|
|
322
|
+
occurred_at: row["occurred_at"]
|
|
323
|
+
)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Persists a saga's checkpointed state as one D1 statement.
|
|
497
328
|
#
|
|
498
329
|
# @param process_manager [String, Symbol] the process manager's name
|
|
499
330
|
# @param correlation [String, Object] the instance's correlation value, stored as
|
|
@@ -513,13 +344,6 @@ module Hecks
|
|
|
513
344
|
)
|
|
514
345
|
end
|
|
515
346
|
|
|
516
|
-
# Removes a finished saga instance's checkpoint; a missing row is not an error.
|
|
517
|
-
#
|
|
518
|
-
# @param process_manager [String, Symbol] the process manager's name
|
|
519
|
-
# @param correlation [String, Object] the instance's correlation value, matched as
|
|
520
|
-
# `correlation.to_s`
|
|
521
|
-
# @return [Array] the statement's empty result rows; callers ignore it
|
|
522
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
523
347
|
def delete_saga(process_manager:, correlation:)
|
|
524
348
|
@db.execute(
|
|
525
349
|
"DELETE FROM hecks_saga_instances WHERE domain = ? AND process_manager = ? AND correlation = ?",
|
|
@@ -527,18 +351,7 @@ module Hecks
|
|
|
527
351
|
)
|
|
528
352
|
end
|
|
529
353
|
|
|
530
|
-
# Yields
|
|
531
|
-
# `Registry#rehydrate_sagas!` to restore at boot.
|
|
532
|
-
#
|
|
533
|
-
# @yieldparam process_manager [String] the process manager's name
|
|
534
|
-
# @yieldparam correlation [String] the instance's correlation value
|
|
535
|
-
# @yieldparam state [String] the saga's state name
|
|
536
|
-
# @yieldparam memory [Hash{Symbol => Object}] the saga's memory, Symbol keys at every depth
|
|
537
|
-
# @yieldparam completed_compensations [Array] the completed-compensation ledger, `[]`
|
|
538
|
-
# when the column is NULL
|
|
539
|
-
# @return [Enumerator, Array<Hash>] an enumerator over the same five values when no
|
|
540
|
-
# block is given; otherwise the raw result rows
|
|
541
|
-
# @raise [Runtime::WiringError] if D1 rejects the statement
|
|
354
|
+
# Yields each checkpointed saga of this domain, for `Registry#rehydrate_sagas!`.
|
|
542
355
|
def each_saga
|
|
543
356
|
return enum_for(:each_saga) unless block_given?
|
|
544
357
|
|
|
@@ -555,10 +368,7 @@ module Hecks
|
|
|
555
368
|
|
|
556
369
|
private
|
|
557
370
|
|
|
558
|
-
#
|
|
559
|
-
# D1 speaks the same dialect (copied, not shared by module include,
|
|
560
|
-
# because Sqlite's own copies are private instance methods on a
|
|
561
|
-
# different class — see the file header) ───────────────────────
|
|
371
|
+
# SqlQueryBuilder dialect hooks, copied from Sqlite's private methods.
|
|
562
372
|
def select_list = "*"
|
|
563
373
|
def from_relation = quoted_table
|
|
564
374
|
def dialect_name = "D1"
|
|
@@ -585,8 +395,7 @@ module Hecks
|
|
|
585
395
|
"json_extract(#{quote_ident(name)}, '#{json_path}')"
|
|
586
396
|
end
|
|
587
397
|
|
|
588
|
-
# SQLite
|
|
589
|
-
# its own documented unbounded spelling, exactly for this case.
|
|
398
|
+
# SQLite has no bare OFFSET; LIMIT -1 is its unbounded spelling.
|
|
590
399
|
def unbounded_limit = " LIMIT -1"
|
|
591
400
|
|
|
592
401
|
def order_clause(order_by, policy)
|
|
@@ -597,8 +406,6 @@ module Hecks
|
|
|
597
406
|
@db.execute(sql, binds).map { |row| Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row)) }
|
|
598
407
|
end
|
|
599
408
|
|
|
600
|
-
# ── the rest of the dialect ─────────────────────────────────────
|
|
601
|
-
|
|
602
409
|
def quote_ident(name)
|
|
603
410
|
%("#{name.to_s.gsub('"', '""')}")
|
|
604
411
|
end
|
|
@@ -2,13 +2,8 @@ require_relative "../../vocabulary"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Adapters
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# files off disk, in the order `Vocabulary.fetch("LoadOrder")` requires,
|
|
8
|
-
# and locate a domain's own root directory by walking up from any file
|
|
9
|
-
# inside it looking for a `.hecksagon`. What `Hecks.boot(path)` uses when
|
|
10
|
-
# a caller names a directory rather than an explicit file list (see
|
|
11
|
-
# `Loader.boot_files` for that other path).
|
|
5
|
+
# Loads a domain's files off disk in `Vocabulary.fetch("LoadOrder")` order and finds
|
|
6
|
+
# a domain's root directory. Used by `Hecks.boot(path)` when given a directory.
|
|
12
7
|
class Folder
|
|
13
8
|
DOMAIN_ORDER = Hecks::Vocabulary.fetch("LoadOrder")
|
|
14
9
|
PORTS = "ports".freeze
|
|
@@ -41,34 +36,12 @@ module Hecks
|
|
|
41
36
|
load_each(File.join(root, ADAPTERS), %w[*.adapter */*.adapter */*/*.adapter])
|
|
42
37
|
end
|
|
43
38
|
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
# refuses references that are perfectly well declared a file later —
|
|
48
|
-
# see MetaValidator.defer for the whole reasoning. DOMAIN_ORDER
|
|
49
|
-
# already places every `*.bluebook` ahead of hecksagons and worlds,
|
|
50
|
-
# so the window ends at the last chapter pattern rather than at a
|
|
51
|
-
# hand-written list this would otherwise have to keep in step.
|
|
39
|
+
# Loads bluebook chapters first, judged once as a deferred group, then everything
|
|
40
|
+
# else in `DOMAIN_ORDER`. Deferring keeps a chapter split across files from being
|
|
41
|
+
# judged before its later files exist (see MetaValidator.defer).
|
|
52
42
|
#
|
|
53
|
-
# `environment:`
|
|
54
|
-
#
|
|
55
|
-
# the provenance. A caller passing `Hecks.boot(path, environment:
|
|
56
|
-
# "production")` gets exactly `environments/production.hecksagon`
|
|
57
|
-
# and `environments/production.world` loaded, whichever exist (a
|
|
58
|
-
# missing one is a silent no-op — not every environment overrides
|
|
59
|
-
# both; see docs/implemented/guides/wiring.md's "Swapping wiring per
|
|
60
|
-
# environment" for the motivating case: swapping a driven adapter
|
|
61
|
-
# — e.g. a real payment gateway for a mock one, or a hosting
|
|
62
|
-
# layer's tenancy settings — without an `if`/`else` anywhere in
|
|
63
|
-
# the domain's own wiring). Never matched by `DOMAIN_ORDER`'s own
|
|
64
|
-
# globs (all non-recursive, none named `environments/*`), so this
|
|
65
|
-
# is the only thing that ever reaches them. Loaded as genuine
|
|
66
|
-
# `Hecks.hecksagon "SameDomain" do ... end` / `Hecks.world
|
|
67
|
-
# "SameDomain" do ... end` blocks — merged into the base file's
|
|
68
|
-
# own hecksagon/world (Registry#add_hecksagon / #add_world,
|
|
69
|
-
# concatenate/override rather than replace), so an overlay can
|
|
70
|
-
# rebind or add settings for anything the base file declared
|
|
71
|
-
# without needing to know what else the base file said.
|
|
43
|
+
# An `environment:` overlay (`environments/<name>.hecksagon` and `.world`) loads
|
|
44
|
+
# last and merges into the base hecksagon/world; a missing overlay file is skipped.
|
|
72
45
|
#
|
|
73
46
|
# @param directory [String] the domain's bluebook directory to load, as
|
|
74
47
|
# `bluebook_directory` resolves it
|
|
@@ -90,12 +63,8 @@ module Hecks
|
|
|
90
63
|
load_each(directory, [File.join("environments", "#{environment}.world")])
|
|
91
64
|
end
|
|
92
65
|
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
# unit callers load. Builders group declarations by the chapter name in
|
|
96
|
-
# each file, so a folder may hold more than one chapter without a catalog.
|
|
97
|
-
# Sorting makes source order deterministic while the deferred window keeps
|
|
98
|
-
# cross-file references from being judged against a partial chapter.
|
|
66
|
+
# Loads every bluebook in a folder as one declaration set, judged after all are loaded
|
|
67
|
+
# so cross-file references never meet a partial chapter.
|
|
99
68
|
#
|
|
100
69
|
# @param directory [String] the directory to glob for bluebook chapter files
|
|
101
70
|
# @param patterns [Array<String>] glob patterns, relative to `directory`, selecting the
|
|
@@ -106,23 +75,11 @@ module Hecks
|
|
|
106
75
|
Bluebook::MetaValidator.judge_deferred!(Hecks.current_registry)
|
|
107
76
|
end
|
|
108
77
|
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
# a `.behaviors` file's `loads` scopes a boot this way specifically so a
|
|
114
|
-
# per-test boot never has to fake isolation by staging bluebooks into a
|
|
115
|
-
# tmpdir (see Loader.boot_files's own header for why that pattern is a
|
|
116
|
-
# hazard, not a convenience).
|
|
78
|
+
# Loads exactly the named files in place, without globbing (see `Loader.boot_files`).
|
|
79
|
+
#
|
|
80
|
+
# Files load by category, not in the caller's order: bluebooks (judged as one deferred
|
|
81
|
+
# group), then hecksagons, then worlds, since a hecksagon may reference bluebook constants.
|
|
117
82
|
#
|
|
118
|
-
# Ordered by category, not by the caller's own list order — same four
|
|
119
|
-
# groups `Vocabulary.fetch("LoadOrder")` walks a directory in
|
|
120
|
-
# (bluebook chapters, translations, hecksagons, worlds), because a
|
|
121
|
-
# hecksagon can reference a bluebook's own constants and must not load
|
|
122
|
-
# first regardless of which order a caller happened to write `loads
|
|
123
|
-
# "x.hecksagon", "x.bluebook"` in. Bluebook chapters are judged as one
|
|
124
|
-
# deferred group exactly like `load_domain` does, for the identical
|
|
125
|
-
# forward-reference reason (MetaValidator.defer's own header).
|
|
126
83
|
# @param files [Array<String>] file paths to load, relative to `bluebook_directory`
|
|
127
84
|
# @param environment [String, nil] the environment name whose overlay, if present,
|
|
128
85
|
# loads after the selected files
|
|
@@ -181,27 +138,11 @@ module Hecks
|
|
|
181
138
|
|
|
182
139
|
# Finds the nearest domain directory at or above `from`, or nil if there is not one.
|
|
183
140
|
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
186
|
-
# or nil if there is not one above you.
|
|
187
|
-
#
|
|
188
|
-
# Marked by a `.hecksagon`, not by a `.bluebook`. Chapters are
|
|
189
|
-
# everywhere: era translations, the language's own self-hosted grammar,
|
|
190
|
-
# and `spec/fixtures`, which holds a dozen unrelated ones in a single
|
|
191
|
-
# directory. A `.hecksagon` is the file that says "this is a domain, and
|
|
192
|
-
# here is how its aggregates are stored", which is exactly the claim a
|
|
193
|
-
# caller is relying on when they omit the path.
|
|
141
|
+
# Walks up from `from`, like git finding `.git`. A domain is marked by a `.hecksagon`,
|
|
142
|
+
# not a `.bluebook`, since chapters also appear in translations and fixtures.
|
|
194
143
|
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
# this corpus), or one holding the files directly.
|
|
198
|
-
# Normalised to the outer directory. Standing in `examples/banking/bluebook`,
|
|
199
|
-
# the `.hecksagon` is right there, so a plain walk stops on the
|
|
200
|
-
# `bluebook/` directory itself. Both boot identically — `bluebook_directory`
|
|
201
|
-
# accepts either and `Loader.boot` takes `File.dirname` of what it gets,
|
|
202
|
-
# so the registry root comes out the same — but `examples/banking` is the
|
|
203
|
-
# directory a person names, and the one a `.world`'s `dir "data"` reads
|
|
204
|
-
# as relative to.
|
|
144
|
+
# A `bluebook/` subdirectory result is normalised to its parent, the directory
|
|
145
|
+
# a `.world`'s `dir "data"` is relative to.
|
|
205
146
|
#
|
|
206
147
|
# @param from [String] the directory to walk up from; defaults to the process's current
|
|
207
148
|
# working directory
|