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,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tree"
|
|
4
|
+
require_relative "../shell"
|
|
5
|
+
require_relative "../console_capture"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
module Codebase
|
|
10
|
+
# The `SqliteFixture` adapter: regenerates the persistence legacy fixtures
|
|
11
|
+
# (`spec/fixtures/persistence_legacy/`) by writing through the real adapters.
|
|
12
|
+
#
|
|
13
|
+
# The fixtures are a baseline that later adapters are compared with, so the run is never
|
|
14
|
+
# started by accident: unconfirmed it reports what it would rewrite and whether the `sqlite3`
|
|
15
|
+
# program it dumps a database with is installed, and writes nothing. Confirmed, it runs
|
|
16
|
+
# `PersistenceLegacyFixture::Regenerate` in this process, which needs a reachable Postgres as
|
|
17
|
+
# well.
|
|
18
|
+
class SqliteFixture
|
|
19
|
+
# Where the fixtures stand, relative to the checkout.
|
|
20
|
+
DIRECTORY = "spec/fixtures/persistence_legacy"
|
|
21
|
+
|
|
22
|
+
# The stores each fixture set is written for.
|
|
23
|
+
STORES = %w[heki sqlite d1 postgres postgres_era].freeze
|
|
24
|
+
|
|
25
|
+
# @param tree [Tree] the checkout whose fixtures are rewritten
|
|
26
|
+
# @param shell [#capture, nil] starts the `sqlite3` probe; a `Shell` when nil
|
|
27
|
+
# @param regenerator [#call, nil] rewrites the fixtures, as `call(dir:)` answering what was
|
|
28
|
+
# written; `PersistenceLegacyFixture::Regenerate` when nil
|
|
29
|
+
def initialize(tree, shell: nil, regenerator: nil)
|
|
30
|
+
@tree = tree
|
|
31
|
+
@shell = shell || Shell.new
|
|
32
|
+
@regenerator = regenerator
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Regenerates the fixtures, or reports what a regeneration would rewrite.
|
|
36
|
+
#
|
|
37
|
+
# @param confirm [Boolean] whether to rewrite
|
|
38
|
+
# @return [String] what was written, or (unconfirmed) what would be
|
|
39
|
+
# @raise [ConsoleCapture::Failure] when a fixture cannot be written
|
|
40
|
+
def regenerate(confirm:)
|
|
41
|
+
return rewrite if confirm
|
|
42
|
+
|
|
43
|
+
"dry run, would rewrite #{DIRECTORY}/ for #{STORES.join(', ')} through the real adapters " \
|
|
44
|
+
"(#{installed}; add --confirm)"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [Boolean] whether the `sqlite3` program answers
|
|
48
|
+
def sqlite_installed?
|
|
49
|
+
@shell.capture("sqlite3", "--version").ok?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def rewrite
|
|
55
|
+
regenerator.call(dir: @tree.path(DIRECTORY))
|
|
56
|
+
rescue LoadError, StandardError => e
|
|
57
|
+
raise ConsoleCapture::Failure, "#{e.class}: #{e.message}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def regenerator
|
|
61
|
+
@regenerator ||= begin
|
|
62
|
+
require "hecks/persistence_legacy_fixture"
|
|
63
|
+
PersistenceLegacyFixture::Regenerate
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def installed = sqlite_installed? ? "sqlite3 is installed" : "sqlite3 is not installed"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require_relative "tree"
|
|
5
|
+
require_relative "ruby_child"
|
|
6
|
+
require "hecks/canonical_json"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
module Codebase
|
|
11
|
+
# What Codebase's `StyleRun` asks of the working tree: keeping comments to the style guides
|
|
12
|
+
# (Ruby's `docs/COMMENT_STYLE_GUIDE.md`, Rust's `docs/COMMENT_STYLE_GUIDE_RUST.md`), and
|
|
13
|
+
# writing a JSON document with its keys in order.
|
|
14
|
+
#
|
|
15
|
+
# The linters are `Hecks::Tools::CommentStyle` and `Hecks::Tools::RustCommentStyle`, which own
|
|
16
|
+
# their options, so each ask runs one in this process from the checkout's root. A check
|
|
17
|
+
# that finds violations refuses with the list. A fix rewrites files, so unconfirmed it lists
|
|
18
|
+
# what it would rewrite (the fixable categories only) and writes nothing.
|
|
19
|
+
module Style
|
|
20
|
+
# Every operation this family carries out.
|
|
21
|
+
OPERATIONS = %w[check_comments fix_comments write_comment_baseline check_comments_unchanged
|
|
22
|
+
check_rust_comments fix_rust_comments canonicalise].freeze
|
|
23
|
+
|
|
24
|
+
# The categories a fix rewrites, in both linters.
|
|
25
|
+
FIXABLE = "all_caps,long_bold,long_line"
|
|
26
|
+
|
|
27
|
+
# Where the long-block baseline is written from, and what a `--code-unchanged` compares.
|
|
28
|
+
BASELINE_PATHS = ["lib/hecks"].freeze
|
|
29
|
+
|
|
30
|
+
# The paths a code-unchanged check looks at when none are named.
|
|
31
|
+
UNCHANGED_PATHS = ["lib"].freeze
|
|
32
|
+
|
|
33
|
+
# The linter each operation runs.
|
|
34
|
+
SCRIPTS = { "check_rust_comments" => "standardize_comments_rust",
|
|
35
|
+
"fix_rust_comments" => "standardize_comments_rust",
|
|
36
|
+
"report_rust_comments" => "standardize_comments_rust" }.freeze
|
|
37
|
+
|
|
38
|
+
module_function
|
|
39
|
+
|
|
40
|
+
# Carries out one operation.
|
|
41
|
+
#
|
|
42
|
+
# @param operation [String] one of `OPERATIONS`
|
|
43
|
+
# @param held [Hash] the `StyleRun` record's fields
|
|
44
|
+
# @param tree [Tree] the working tree, already known to be a hecks checkout
|
|
45
|
+
# @param shell [#capture, nil] unused: the linters run in this process
|
|
46
|
+
# @return [String] what the linter printed, or the file in order
|
|
47
|
+
# @raise [ConsoleCapture::Failure] when a check finds a violation, or the linter or file is
|
|
48
|
+
# refused
|
|
49
|
+
def call(operation, held, tree, shell: nil)
|
|
50
|
+
args = held.transform_values { |value| value.is_a?(Hash) ? value[:value] : value }
|
|
51
|
+
return canonical(args, tree) if operation == "canonicalise"
|
|
52
|
+
|
|
53
|
+
child = RubyChild.new(tree)
|
|
54
|
+
case operation
|
|
55
|
+
when "check_comments", "check_rust_comments" then check(operation, args, child)
|
|
56
|
+
when "fix_comments", "fix_rust_comments" then fix(operation, args, child)
|
|
57
|
+
when "write_comment_baseline" then baseline(args, child)
|
|
58
|
+
else unchanged(args, child)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# A pure read: the linter's summary, its violations, or its JSON.
|
|
63
|
+
#
|
|
64
|
+
# @param operation [String] `report_comments` or `report_rust_comments`
|
|
65
|
+
# @param args [Hash] the query's plain arguments: `paths`, `only`, `json`, `top`
|
|
66
|
+
# @param tree [Tree] the checkout
|
|
67
|
+
# @param shell [#capture, nil] unused: the linters run in this process
|
|
68
|
+
# @return [String] the linter's report
|
|
69
|
+
# @raise [ConsoleCapture::Failure] when the linter refuses its arguments
|
|
70
|
+
def report(operation, args, tree, shell: nil)
|
|
71
|
+
flags = ["--report", *only_flags(args)]
|
|
72
|
+
flags << "--json" if args[:json]
|
|
73
|
+
flags.push("--top", args[:top].to_s) if args[:top]
|
|
74
|
+
paths = after_separator(paths_of(args))
|
|
75
|
+
RubyChild.new(tree).answer(script_of(operation), *flags, *paths)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @param args [Hash] the record's plain fields
|
|
79
|
+
# @param tree [Tree] the checkout
|
|
80
|
+
# @return [String] the JSON document at `file`, every object's keys in order
|
|
81
|
+
# @raise [ConsoleCapture::Failure] when the file cannot be read or is not JSON
|
|
82
|
+
def canonical(args, tree)
|
|
83
|
+
path = File.expand_path(args[:file].to_s)
|
|
84
|
+
CanonicalJson.pretty(File.read(path))
|
|
85
|
+
rescue Errno::ENOENT
|
|
86
|
+
raise ConsoleCapture::Failure, "no such file #{path} (relative to #{Dir.pwd}, tree #{tree.root})"
|
|
87
|
+
rescue JSON::ParserError => e
|
|
88
|
+
raise ConsoleCapture::Failure, "#{path} is not JSON: #{e.message.lines.first.strip}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @param operation [String] `check_comments` or `check_rust_comments`
|
|
92
|
+
# @param args [Hash] the record's plain fields
|
|
93
|
+
# @param child [RubyChild] the linter's runner
|
|
94
|
+
# @return [String] the linter's clean verdict
|
|
95
|
+
# @raise [ConsoleCapture::Failure] with every violation, when there is one
|
|
96
|
+
def check(operation, args, child)
|
|
97
|
+
paths = after_separator(paths_of(args))
|
|
98
|
+
answer = child.answer(script_of(operation), "--check", *only_flags(args), *paths)
|
|
99
|
+
answer.empty? ? "no comment violations" : answer
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @param operation [String] `fix_comments` or `fix_rust_comments`
|
|
103
|
+
# @param args [Hash] the record's plain fields
|
|
104
|
+
# @param child [RubyChild] the linter's runner
|
|
105
|
+
# @return [String] the files rewritten, or (unconfirmed) the violations a fix would rewrite
|
|
106
|
+
# @raise [ConsoleCapture::Failure] when the linter refuses its arguments
|
|
107
|
+
def fix(operation, args, child)
|
|
108
|
+
script = script_of(operation)
|
|
109
|
+
paths = after_separator(paths_of(args))
|
|
110
|
+
return child.answer(script, "--fix", *only_flags(args), *paths) if args[:confirm] == true
|
|
111
|
+
|
|
112
|
+
found = child.capture(script, "--check", "--only", FIXABLE, *paths).out.strip
|
|
113
|
+
return "dry run: nothing a fix would rewrite" if found.empty?
|
|
114
|
+
|
|
115
|
+
"dry run, #{found.lines.size} violations a fix would rewrite (add --confirm to rewrite):\n#{found}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @param args [Hash] the record's plain fields
|
|
119
|
+
# @param child [RubyChild] the linter's runner
|
|
120
|
+
# @return [String] what the baseline recorded, or (unconfirmed) the blocks it would record
|
|
121
|
+
def baseline(args, child)
|
|
122
|
+
paths = after_separator(args[:paths] ? paths_of(args) : BASELINE_PATHS)
|
|
123
|
+
return child.answer("standardize_comments", "--write-baseline", *paths) if args[:confirm] == true
|
|
124
|
+
|
|
125
|
+
found = child.capture("standardize_comments", "--check", "--only", "long_block", *paths).out.strip
|
|
126
|
+
return "dry run: no block would be newly tolerated" if found.empty?
|
|
127
|
+
|
|
128
|
+
"dry run, #{found.lines.size} blocks would be recorded as tolerated (add --confirm):\n#{found}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @param args [Hash] the record's plain fields: `ref`, and `paths` (`lib` when absent)
|
|
132
|
+
# @param child [RubyChild] the linter's runner
|
|
133
|
+
# @return [String] "code unchanged"
|
|
134
|
+
# @raise [ConsoleCapture::Failure] naming each file whose code differs from the ref, or when
|
|
135
|
+
# the ref is blank or begins with `-`
|
|
136
|
+
def unchanged(args, child)
|
|
137
|
+
ref = args[:ref].to_s.strip
|
|
138
|
+
raise ConsoleCapture::Failure, "a ref to compare with is required" if ref.empty?
|
|
139
|
+
raise ConsoleCapture::Failure, "a ref may not begin with '-': #{ref}" if ref.start_with?("-")
|
|
140
|
+
|
|
141
|
+
paths = args[:paths] ? paths_of(args) : UNCHANGED_PATHS
|
|
142
|
+
child.answer("standardize_comments", "--code-unchanged", ref, *after_separator(paths))
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# @param operation [String] an operation
|
|
146
|
+
# @return [String] the linter it runs
|
|
147
|
+
def script_of(operation) = SCRIPTS.fetch(operation, "standardize_comments")
|
|
148
|
+
|
|
149
|
+
# @param args [Hash] the record's plain fields
|
|
150
|
+
# @return [Array<String>] `--only <list>` when categories are named
|
|
151
|
+
def only_flags(args) = args[:only] ? ["--only", args[:only].to_s] : []
|
|
152
|
+
|
|
153
|
+
# @param args [Hash] the record's plain fields
|
|
154
|
+
# @return [Array<String>] the paths, from a comma-separated list
|
|
155
|
+
def paths_of(args) = args[:paths].to_s.split(",").map(&:strip).reject(&:empty?)
|
|
156
|
+
|
|
157
|
+
# Paths as the linter takes them: after `--`, so no path is read as a flag.
|
|
158
|
+
#
|
|
159
|
+
# @param paths [Array<String>] the paths a query names, or its default paths
|
|
160
|
+
# @return [Array<String>] `--` and the paths
|
|
161
|
+
# @raise [ConsoleCapture::Failure] when a path begins with `-`
|
|
162
|
+
def after_separator(paths)
|
|
163
|
+
flagged = paths.select { |path| path.start_with?("-") }
|
|
164
|
+
raise ConsoleCapture::Failure, "paths may not begin with '-': #{flagged.join(', ')}" if flagged.any?
|
|
165
|
+
|
|
166
|
+
["--", *paths]
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
require_relative "tree"
|
|
5
|
+
require_relative "../console_capture"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
module Codebase
|
|
10
|
+
# The `TestRunner` adapter: runs one spec example through the test runner in this process.
|
|
11
|
+
#
|
|
12
|
+
# It hands the runner one file and one example description, so a caller never quotes the
|
|
13
|
+
# description for a shell. What the runner prints is captured and comes back as the answer;
|
|
14
|
+
# a run that fails refuses with the same text.
|
|
15
|
+
class TestRunner
|
|
16
|
+
class << self
|
|
17
|
+
# @return [#call, nil] takes `(args, err, out)` and answers the exit status; the test
|
|
18
|
+
# runner when nil. A spec replaces it so no example has to run to test what is asked.
|
|
19
|
+
attr_accessor :runner
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param tree [Tree] the checkout whose spec is run
|
|
23
|
+
def initialize(tree)
|
|
24
|
+
@tree = tree
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Runs one example of one spec file, from the checkout's root.
|
|
28
|
+
#
|
|
29
|
+
# @param file [String] the spec file, relative to the checkout or absolute
|
|
30
|
+
# @param example [String] part of the example's description
|
|
31
|
+
# @return [String] what the runner printed when every matching example passed
|
|
32
|
+
# @raise [ConsoleCapture::Failure] when the file is not there, or an example failed
|
|
33
|
+
def run(file:, example:)
|
|
34
|
+
path = File.expand_path(file, @tree.root)
|
|
35
|
+
raise ConsoleCapture::Failure, "no such spec file #{file}" unless File.file?(path)
|
|
36
|
+
|
|
37
|
+
out = StringIO.new
|
|
38
|
+
status = Dir.chdir(@tree.root) { runner.call(["--example", example, path], out, out) }
|
|
39
|
+
raise ConsoleCapture::Failure, out.string.strip unless status.zero?
|
|
40
|
+
|
|
41
|
+
out.string.strip
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def runner
|
|
47
|
+
return self.class.runner if self.class.runner
|
|
48
|
+
|
|
49
|
+
require "rspec/core"
|
|
50
|
+
RSpec::Core::Runner.method(:run)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tree"
|
|
4
|
+
require_relative "test_runner"
|
|
5
|
+
require_relative "sqlite_fixture"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
module Codebase
|
|
10
|
+
# What Codebase's `TestSuiteRun` asks of the working tree: the tooling around this
|
|
11
|
+
# repository's specs.
|
|
12
|
+
#
|
|
13
|
+
# The tooling owns its options, so each ask runs one of the `Hecks::CLI` commands in this
|
|
14
|
+
# process from the checkout's root, except a single example (the `TestRunner` adapter runs it)
|
|
15
|
+
# and the persistence fixtures (the `SqliteFixture` adapter). A listing is a pure read.
|
|
16
|
+
# Refreshing the committed timings, regenerating the fixtures and writing the committed spec
|
|
17
|
+
# list change tracked files, so unconfirmed they report what they would do and write nothing.
|
|
18
|
+
module TestSuite
|
|
19
|
+
# Every operation this family carries out.
|
|
20
|
+
OPERATIONS = %w[refresh_runtime_baseline run_spec_example stress_concurrency
|
|
21
|
+
regenerate_legacy_fixtures seed_semantics_corpus write_io_parallel_spec_list].freeze
|
|
22
|
+
|
|
23
|
+
# The tag filter the postgres job lists its specs by when none is named.
|
|
24
|
+
DEFAULT_TAGS = "--tag io --tag ~fuzzing"
|
|
25
|
+
|
|
26
|
+
# The committed files a baseline refresh writes.
|
|
27
|
+
BASELINES = %w[.github/rspec_runtime_baseline.log .github/postgres_io_runtime_baseline.log].freeze
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# Loads the command a `Hecks::CLI` file defines, the first time an ask needs it: several
|
|
32
|
+
# read the checkout's specs or need a development gem, which an installed gem lacks.
|
|
33
|
+
#
|
|
34
|
+
# @param file [String] the command's file under `lib/hecks/cli/`, without the extension
|
|
35
|
+
# @return [Module] the command, named as the file is, in camel case
|
|
36
|
+
def command(file)
|
|
37
|
+
require "hecks/cli/#{file}"
|
|
38
|
+
Hecks::CLI.const_get(file.split("_").map(&:capitalize).join)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Carries out one operation.
|
|
42
|
+
#
|
|
43
|
+
# @param operation [String] one of `OPERATIONS`
|
|
44
|
+
# @param held [Hash] the `TestSuiteRun` record's fields
|
|
45
|
+
# @param tree [Tree] the working tree, already known to be a hecks checkout
|
|
46
|
+
# @param shell [#capture, nil] starts the fixtures' child process
|
|
47
|
+
# @return [String] what was found, run or written
|
|
48
|
+
# @raise [ConsoleCapture::Failure] when a run fails or a script is refused
|
|
49
|
+
def call(operation, held, tree, shell: nil)
|
|
50
|
+
args = plain(held)
|
|
51
|
+
case operation
|
|
52
|
+
when "refresh_runtime_baseline" then refresh(args, tree)
|
|
53
|
+
when "run_spec_example" then TestRunner.new(tree).run(file: args[:file], example: args[:example])
|
|
54
|
+
when "stress_concurrency"
|
|
55
|
+
answer { command("stress_concurrency_specs").call(stress_flags(args), root: tree.root) }
|
|
56
|
+
when "regenerate_legacy_fixtures"
|
|
57
|
+
SqliteFixture.new(tree, shell: shell).regenerate(confirm: args[:confirm] == true)
|
|
58
|
+
when "seed_semantics_corpus"
|
|
59
|
+
answer { command("seed_semantics_corpus").call(root: tree.root, env: seed_env(args)) }
|
|
60
|
+
else write_list(args, tree)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# A pure read: a listing, or the recorded pattern cases.
|
|
65
|
+
#
|
|
66
|
+
# @param operation [String] `shard_specs`, `list_io_parallel_specs`, `record_pattern_cases`
|
|
67
|
+
# @param args [Hash] the query's plain arguments
|
|
68
|
+
# @param tree [Tree] the checkout
|
|
69
|
+
# @param shell [#capture, nil] unused: every listing is read in this process
|
|
70
|
+
# @return [String] what the command printed to stdout
|
|
71
|
+
# @raise [ConsoleCapture::Failure] when the command refuses its arguments
|
|
72
|
+
def report(operation, args, tree, shell: nil)
|
|
73
|
+
case operation
|
|
74
|
+
when "shard_specs"
|
|
75
|
+
read { |out| command("rspec_shard_files").call(shard_args(args), root: tree.root, out: out) }
|
|
76
|
+
when "list_io_parallel_specs"
|
|
77
|
+
read { |out| command("rspec_io_parallel_files").call(list_args(args), root: tree.root, out: out) }
|
|
78
|
+
else read { |out| command("pattern_cases").call(out: out) }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Runs a command in this process and answers what it printed to stdout only, for a command
|
|
83
|
+
# whose stdout is its data and whose stderr is progress.
|
|
84
|
+
#
|
|
85
|
+
# @yield [out] the command, given the stream its data goes to; it answers an exit status
|
|
86
|
+
# @yieldparam out [StringIO] where the data goes
|
|
87
|
+
# @return [String] the data, without the trailing newline
|
|
88
|
+
# @raise [ConsoleCapture::Failure] with what it printed when the status is not 0
|
|
89
|
+
def read
|
|
90
|
+
out = StringIO.new
|
|
91
|
+
outcome = ConsoleCapture.capture { exit(yield(out)) }
|
|
92
|
+
raise ConsoleCapture::Failure, outcome.output.strip unless outcome.ok?
|
|
93
|
+
|
|
94
|
+
out.string.chomp
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Runs a command in this process and answers everything it printed.
|
|
98
|
+
#
|
|
99
|
+
# @yield the command; it answers an exit status
|
|
100
|
+
# @return [String] what it printed to stdout and stderr
|
|
101
|
+
# @raise [ConsoleCapture::Failure] with what it printed when the status is not 0
|
|
102
|
+
def answer
|
|
103
|
+
ConsoleCapture.answer { exit(yield) }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @param held [Hash] the record's fields, each perhaps a value object's `{ value: x }`
|
|
107
|
+
# @return [Hash] the same fields as plain values
|
|
108
|
+
def plain(held) = held.transform_values { |value| value.is_a?(Hash) ? value[:value] : value }
|
|
109
|
+
|
|
110
|
+
# @param args [Hash] `group`, `groups` and `runtime_log`
|
|
111
|
+
# @return [Array<String>] the script's arguments
|
|
112
|
+
def shard_args(args) = [args[:group].to_s, args[:groups].to_s, *args[:runtime_log]]
|
|
113
|
+
|
|
114
|
+
# @param args [Hash] `exclude`, `tags` and `check`
|
|
115
|
+
# @return [Array<String>] the script's arguments: `--check FILE`, the pattern, then the tags
|
|
116
|
+
def list_args(args)
|
|
117
|
+
check = args[:check] ? ["--check", args[:check]] : []
|
|
118
|
+
[*check, args[:exclude].to_s, "--", *tag_words(args)]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @param args [Hash] `tags`, perhaps absent
|
|
122
|
+
# @return [Array<String>] the tag filter, one word each
|
|
123
|
+
def tag_words(args) = (args[:tags] || DEFAULT_TAGS).split
|
|
124
|
+
|
|
125
|
+
# @param args [Hash] `workers` and `from_run`
|
|
126
|
+
# @param tree [Tree] the checkout whose baselines are rewritten
|
|
127
|
+
# @return [String] what was written, or (unconfirmed) what would be
|
|
128
|
+
# @raise [ConsoleCapture::Failure] when the refresh ends badly
|
|
129
|
+
def refresh(args, tree)
|
|
130
|
+
source = args[:from_run] ? ["--from-run", args[:from_run]] : [*args[:workers]&.to_s]
|
|
131
|
+
return answer { command("refresh_rspec_runtime_baseline").call(source, root: tree.root) } if args[:confirm] == true
|
|
132
|
+
|
|
133
|
+
"dry run, would #{args[:from_run] ? "read CI run #{args[:from_run]}'s timings" : 'time a local run'} " \
|
|
134
|
+
"and rewrite #{BASELINES.join(', ')} (add --confirm)"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# @param args [Hash] `runs`, `parallel` and `seed_start`
|
|
138
|
+
# @return [Array<String>] the script's flags for those that are named
|
|
139
|
+
def stress_flags(args)
|
|
140
|
+
{ "--runs" => :runs, "--parallel" => :parallel, "--seed-start" => :seed_start }
|
|
141
|
+
.filter_map { |flag, name| [flag, args[name].to_s] if args[name] }.flatten
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# @param args [Hash] `fixture`, perhaps absent
|
|
145
|
+
# @return [Hash{String => String}] the variable that names the one fixture to re-seed
|
|
146
|
+
def seed_env(args) = args[:fixture] ? { "SEED" => args[:fixture] } : {}
|
|
147
|
+
|
|
148
|
+
# @param args [Hash] `exclude`, `tags`, `write` and `confirm`
|
|
149
|
+
# @param tree [Tree] the checkout whose spec list is written
|
|
150
|
+
# @return [String] what was written, or (unconfirmed) how many files would be
|
|
151
|
+
# @raise [ConsoleCapture::Failure] when the listing is refused
|
|
152
|
+
def write_list(args, tree)
|
|
153
|
+
if args[:confirm] == true
|
|
154
|
+
words = ["--write", args[:write], args[:exclude], "--", *tag_words(args)]
|
|
155
|
+
answer { command("rspec_io_parallel_files").call(words, root: tree.root) }
|
|
156
|
+
return "wrote #{args[:write]}"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
files = report("list_io_parallel_specs", args, tree).lines.size
|
|
160
|
+
"dry run, would write #{files} spec files to #{args[:write]} (add --confirm)"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require_relative "../console_capture"
|
|
5
|
+
require "hecks/runtime/errors"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
# Adapters of the Codebase part of the Hecks domain: the tools for working on this repository.
|
|
10
|
+
module Codebase
|
|
11
|
+
# The working tree a Codebase request acts on, and the one rule they all share: it is a hecks
|
|
12
|
+
# checkout, a tree with `hecks.gemspec` beside `lib/`.
|
|
13
|
+
#
|
|
14
|
+
# The package carries `lib/` and the Rust workspace but never the gemspec, so an installed gem
|
|
15
|
+
# cannot be mistaken for a checkout and answers "needs a hecks checkout" instead of globbing
|
|
16
|
+
# an absent `rust/` or rewriting its own `lib/`. A request that changes files goes through
|
|
17
|
+
# {#apply}: it compares each file with what it should hold, reports the drift, and writes
|
|
18
|
+
# only when confirmed.
|
|
19
|
+
class Tree
|
|
20
|
+
# The file whose presence beside `lib/` marks a hecks checkout.
|
|
21
|
+
MARKER = "hecks.gemspec"
|
|
22
|
+
|
|
23
|
+
# What a request outside a checkout is refused with.
|
|
24
|
+
NEEDS = "needs a hecks checkout"
|
|
25
|
+
|
|
26
|
+
# The repository this file lives in.
|
|
27
|
+
DEFAULT_ROOT = File.expand_path("../../../../..", __dir__)
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
# @return [String, nil] the tree to act on; this repository when nil. A spec points it
|
|
31
|
+
# at a directory that is not a checkout, so no install is needed to test the refusal.
|
|
32
|
+
attr_accessor :root
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Raised when a request needs a hecks checkout and the tree is not one. It is the runtime's
|
|
36
|
+
# own refusal for an unmet rule, so a query answered here reads as a refusal in the
|
|
37
|
+
# launcher.
|
|
38
|
+
class NeedsCheckout < Runtime::GivenNotMet; end
|
|
39
|
+
|
|
40
|
+
# @return [String] the tree's root directory
|
|
41
|
+
attr_reader :root
|
|
42
|
+
|
|
43
|
+
# @param root [String, nil] the tree's root; {.root}, or this repository, when nil
|
|
44
|
+
def initialize(root: nil)
|
|
45
|
+
@root = File.expand_path(root || self.class.root || DEFAULT_ROOT)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Boolean] whether the tree is a hecks checkout
|
|
49
|
+
def checkout?
|
|
50
|
+
File.exist?(File.join(@root, MARKER)) && Dir.exist?(File.join(@root, "lib"))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [void]
|
|
54
|
+
# @raise [NeedsCheckout] "needs a hecks checkout" when the tree is not one
|
|
55
|
+
def require_checkout!
|
|
56
|
+
return if checkout?
|
|
57
|
+
|
|
58
|
+
raise NeedsCheckout, "#{NEEDS}: #{MARKER} does not stand beside lib/ in #{@root}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @param parts [Array<String>] path segments below the root
|
|
62
|
+
# @return [String] the absolute path
|
|
63
|
+
def path(*parts) = File.join(@root, *parts)
|
|
64
|
+
|
|
65
|
+
# @param absolute [String] a path inside the tree
|
|
66
|
+
# @return [String] the path relative to the root
|
|
67
|
+
def relative(absolute) = absolute.delete_prefix("#{@root}/")
|
|
68
|
+
|
|
69
|
+
# Compares each file with what it should hold, and writes the differences only when
|
|
70
|
+
# confirmed.
|
|
71
|
+
#
|
|
72
|
+
# @param files [Hash{String => String}] absolute path to the text it should hold
|
|
73
|
+
# @param stale [Array<String>] absolute paths that should not exist
|
|
74
|
+
# @param confirm [Boolean] whether to write; the comparison is all that happens when false
|
|
75
|
+
# @return [String] what differs, and whether it was written
|
|
76
|
+
def apply(files, stale: [], confirm: false)
|
|
77
|
+
changes = drift(files, stale)
|
|
78
|
+
return "nothing to change: #{files.size} files already hold what the language projects" if changes.empty?
|
|
79
|
+
|
|
80
|
+
write(files, stale) if confirm
|
|
81
|
+
summarize(changes, confirm)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def drift(files, stale)
|
|
87
|
+
changed = files.filter_map do |path, text|
|
|
88
|
+
next [:new, path] unless File.exist?(path)
|
|
89
|
+
|
|
90
|
+
[:changed, path] unless File.read(path) == text
|
|
91
|
+
end
|
|
92
|
+
changed + stale.select { |path| File.exist?(path) }.map { |path| [:removed, path] }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def write(files, stale)
|
|
96
|
+
files.each do |path, text|
|
|
97
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
98
|
+
File.write(path, text)
|
|
99
|
+
end
|
|
100
|
+
stale.each { |path| FileUtils.rm_f(path) }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def summarize(changes, confirm)
|
|
104
|
+
lines = changes.map { |kind, path| " #{kind} #{relative(path)}" }
|
|
105
|
+
head = confirm ? "wrote #{changes.size} files:" : "dry run, #{changes.size} files differ (add --confirm to write):"
|
|
106
|
+
[head, *lines].join("\n")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "monitor"
|
|
4
|
+
require "stringio"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
# Runs a command-line entry point that prints and exits, and hands back what it said and how
|
|
9
|
+
# it ended, so an adapter can reuse `Hecks::CLI::*` unchanged.
|
|
10
|
+
#
|
|
11
|
+
# It is the shared base for every Custodian adapter that wraps an existing CLI: the entry
|
|
12
|
+
# point keeps its own printing, `exit` and `abort`, and the adapter turns the outcome into a
|
|
13
|
+
# port answer (the text) or a refusal (`Failed`). `$stdout`, `$stderr`, `ENV` and the working
|
|
14
|
+
# directory are process-wide, so every capture, and every `RustBuild` call, holds the one
|
|
15
|
+
# `LOCK` for its length: two captures never interleave, and one may nest inside another on
|
|
16
|
+
# the same thread.
|
|
17
|
+
module ConsoleCapture
|
|
18
|
+
# What an entry point said and how it ended.
|
|
19
|
+
#
|
|
20
|
+
# @!attribute [r] output
|
|
21
|
+
# @return [String] everything printed to stdout and stderr, in order
|
|
22
|
+
# @!attribute [r] status
|
|
23
|
+
# @return [Integer] the exit status; 0 when the entry point returned normally
|
|
24
|
+
Outcome = Struct.new(:output, :status) do
|
|
25
|
+
# @return [Boolean] whether the entry point ended with status 0
|
|
26
|
+
def ok? = status.zero?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Raised when a captured entry point ends with a non-zero status; the message is its output.
|
|
30
|
+
class Failure < StandardError; end
|
|
31
|
+
|
|
32
|
+
# The process-wide lock a capture holds; reentrant, so a capture may run another.
|
|
33
|
+
LOCK = Monitor.new
|
|
34
|
+
|
|
35
|
+
module_function
|
|
36
|
+
|
|
37
|
+
# Runs the block holding the process-wide capture lock.
|
|
38
|
+
#
|
|
39
|
+
# @yield the work that swaps a process-wide stream, variable or directory
|
|
40
|
+
# @return [Object] the block's value
|
|
41
|
+
def synchronize(&) = LOCK.synchronize(&)
|
|
42
|
+
|
|
43
|
+
# Runs the block with stdout and stderr captured.
|
|
44
|
+
#
|
|
45
|
+
# @yield the entry point to run
|
|
46
|
+
# @return [Outcome] the text printed and the exit status
|
|
47
|
+
def capture
|
|
48
|
+
synchronize do
|
|
49
|
+
saved = [$stdout, $stderr]
|
|
50
|
+
buffer = StringIO.new
|
|
51
|
+
begin
|
|
52
|
+
$stdout = $stderr = buffer
|
|
53
|
+
status = begin
|
|
54
|
+
yield
|
|
55
|
+
0
|
|
56
|
+
rescue SystemExit => e
|
|
57
|
+
e.status
|
|
58
|
+
end
|
|
59
|
+
Outcome.new(buffer.string, status)
|
|
60
|
+
ensure
|
|
61
|
+
$stdout, $stderr = saved
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Runs the block captured and answers its text, or refuses with it.
|
|
67
|
+
#
|
|
68
|
+
# @yield the entry point to run
|
|
69
|
+
# @return [String] the output when the entry point ended with status 0
|
|
70
|
+
# @raise [Failure] when it ended otherwise; the message is what it printed
|
|
71
|
+
def answer(&)
|
|
72
|
+
outcome = capture(&)
|
|
73
|
+
raise Failure, outcome.output.strip unless outcome.ok?
|
|
74
|
+
|
|
75
|
+
outcome.output
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Required by name, not relative to this file: a fuzz or model check boots a copy of this directory,
|
|
2
|
+
# and the implementation must load once, from `lib/`, not from the copy.
|
|
3
|
+
require "hecks/hecks/adapters/deploy_toolchain"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "DeployToolchain" do
|
|
6
|
+
port "DeployToolchain"
|
|
7
|
+
end
|