hecks 2.9.0 → 3.0.1
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 +51 -6
- data/lib/hecks/adapters/driven/heki/journal.rb +1 -1
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +1 -1
- data/lib/hecks/adapters/driven/memory.rb +16 -3
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +6 -2
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +13 -4
- data/lib/hecks/adapters/driven/prism.rb +41 -8
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +73 -16
- data/lib/hecks/behaviors/expectations.rb +1 -1
- data/lib/hecks/behaviors.rb +1 -1
- 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/assembly/contracts.rb +2 -0
- data/lib/hecks/bluebook/attribute.rb +1 -1
- data/lib/hecks/bluebook/behaviour/aggregate.rb +30 -1
- data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -0
- data/lib/hecks/bluebook/chapter.rb +6 -2
- data/lib/hecks/bluebook/domain_port.rb +36 -5
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +10 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +8 -0
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -1
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +31 -3
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +122 -3
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +1 -1
- data/lib/hecks/bluebook/dsl/query_builder.rb +27 -1
- data/lib/hecks/bluebook/dsl/rule_reference.rb +1 -1
- data/lib/hecks/bluebook/dsl/world_builder.rb +29 -2
- data/lib/hecks/bluebook/expression/canonical_form.rb +1 -1
- data/lib/hecks/bluebook/expression/resolver.rb +3 -2
- data/lib/hecks/bluebook/hexagon.rb +13 -5
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +1 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +4 -1
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator.rb +9 -4
- data/lib/hecks/bluebook/model_check.rb +23 -0
- data/lib/hecks/bluebook/pattern_subset.rb +38 -0
- data/lib/hecks/bluebook/query.rb +20 -5
- data/lib/hecks/bluebook/smoke_test.rb +1 -1
- 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 +2 -2
- 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 +1 -1
- data/lib/hecks/cli/mcp.rb +3 -3
- data/lib/hecks/cli/model_check.rb +15 -8
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +224 -32
- data/lib/hecks/cli/project_diagrams.rb +4 -3
- 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 +3 -3
- 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 +5 -3
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -5
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +201 -52
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +591 -23
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -4
- 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 +1 -1
- data/lib/hecks/{facade → doors}/handle.rb +2 -2
- data/lib/hecks/{facade → doors}/json_door.rb +4 -4
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +7 -7
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/{facade/surface → doors/ruby_door}/aggregate_door.rb +8 -3
- data/lib/hecks/{facade/surface → doors/ruby_door}/chapter.rb +3 -3
- data/lib/hecks/{facade/surface.rb → doors/ruby_door.rb} +36 -5
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +1 -1
- data/lib/hecks/embryonaut_bluebook.rb +1 -1
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +24 -37
- data/lib/hecks/forms/app.rb +6 -6
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/field_shape.rb +2 -1
- data/lib/hecks/forms/port_argument.rb +1 -1
- 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/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/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +11 -0
- data/lib/hecks/language/bluebook/query.bluebook +7 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +4 -4
- data/lib/hecks/language/hecksagon/domain_port.bluebook +10 -0
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +20 -0
- data/lib/hecks/mcp_stdio_guard.rb +2 -2
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +8 -5
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +4 -1
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +15 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +32 -15
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +15 -5
- 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 +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +43 -24
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/state_codec.rb +24 -5
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +1 -1
- data/lib/hecks/projections/deploy/fargate.rb +5 -5
- data/lib/hecks/projections/deploy/lambda.rb +43 -32
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/template.rb +1 -1
- 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/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/shared.rb +1 -1
- data/lib/hecks/projections/diagrams.rb +3 -3
- data/lib/hecks/projections/model/deviations.rb +1 -1
- data/lib/hecks/projections/parser_table.rb +4 -4
- data/lib/hecks/projections/reference.rb +2 -3
- data/lib/hecks/projections/rust_vocabulary.rb +1 -1
- data/lib/hecks/projector/cli_projector.rb +106 -37
- data/lib/hecks/projector.rb +1 -1
- 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/release/runner/ci_publisher.rb +2 -2
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +14 -7
- data/lib/hecks/release/runner/npm_publisher.rb +6 -36
- data/lib/hecks/release/runner/preflight.rb +26 -2
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +30 -15
- data/lib/hecks/release/runner.rb +57 -6
- data/lib/hecks/router/namespace_installer.rb +3 -3
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +4 -0
- data/lib/hecks/runtime/dependency_planning.rb +20 -2
- data/lib/hecks/runtime/dispatcher.rb +53 -3
- data/lib/hecks/runtime/interpreting.rb +3 -0
- data/lib/hecks/runtime/loader.rb +65 -12
- data/lib/hecks/runtime/outbox.rb +1 -1
- data/lib/hecks/runtime/policy_interpreter.rb +5 -2
- data/lib/hecks/runtime/port_operation_interpreter.rb +2 -10
- data/lib/hecks/runtime/query_interpreter.rb +77 -0
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/refusal_wording.rb +23 -1
- data/lib/hecks/runtime/registry/verification.rb +163 -4
- data/lib/hecks/runtime/registry.rb +57 -3
- data/lib/hecks/runtime/remote_dispatcher.rb +31 -2
- data/lib/hecks/runtime/value/coercion.rb +23 -135
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +4 -1
- data/lib/hecks/runtime.rb +20 -6
- 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 +16 -16
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +2 -2
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +1 -1
- 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/version.rb +1 -1
- data/lib/hecks.rb +32 -15
- 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 +477 -12
- data/lib/hecks/facade/cli_door.rb +0 -96
- data/lib/hecks/facade/cli_runner.rb +0 -127
- data/lib/hecks/mcp_door_scope.rb +0 -95
data/lib/hecks/corpus.rb
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
require_relative "fuzzing/target_capabilities"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
# The corpus: every place in this repo that holds a real domain, named once.
|
|
5
|
+
# Plain Dir/File only — the tools require this before booting anything.
|
|
6
|
+
module Corpus
|
|
7
|
+
ROOT = File.expand_path("../..", __dir__).freeze
|
|
8
|
+
|
|
9
|
+
Member = Struct.new(:stem, :kind, :path)
|
|
10
|
+
|
|
11
|
+
# **One domain per directory** — its bluebooks sit in `<dir>/bluebook/`
|
|
12
|
+
# or directly in `<dir>` (see `bluebook_files`). Stemmed by directory.
|
|
13
|
+
DIRECTORY_KINDS = {
|
|
14
|
+
example: "examples/*",
|
|
15
|
+
stress: "qa/stress_domains/*",
|
|
16
|
+
semantics: "spec/corpus/semantics/domains/*",
|
|
17
|
+
# The Hecks domain (ADR 0080): its chapters share one namespace and one hecksagon, so
|
|
18
|
+
# they load together, as a directory, never file by file.
|
|
19
|
+
hecks: "lib/hecks/hecks",
|
|
20
|
+
# A package vendored via `uses_embryonaut_bluebook` — nested inside the
|
|
21
|
+
# consuming example's own checkout, not this gem's own framework/bluebook/.
|
|
22
|
+
vendored: "examples/*/vendor/embryonaut_bluebooks/*"
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
# **One chapter per file**. Stemmed by the path below the glob's fixed
|
|
26
|
+
# prefix, so a nested fixture keeps its subdirectory (`eras/base`)
|
|
27
|
+
# and never collides with a same-named file elsewhere in the kind.
|
|
28
|
+
FILE_KINDS = {
|
|
29
|
+
grammar: "lib/hecks/grammar/*.bluebook",
|
|
30
|
+
framework: "lib/hecks/framework/bluebook/*.bluebook",
|
|
31
|
+
qa: "lib/hecks/quality_control/*.bluebook",
|
|
32
|
+
language: "lib/hecks/language/**/*.bluebook",
|
|
33
|
+
deploy: "lib/hecks/deploy/bluebook/*.bluebook",
|
|
34
|
+
tenancy: "lib/hecks/tenancy/bluebook/*.bluebook",
|
|
35
|
+
fixture: "spec/fixtures/**/*.bluebook"
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
KINDS = (DIRECTORY_KINDS.keys + FILE_KINDS.keys).freeze
|
|
39
|
+
|
|
40
|
+
# A route sends what the sweep does not boot elsewhere; each entry's
|
|
41
|
+
# `check` (:named_in, :gitignored, :gap) is verified by
|
|
42
|
+
# spec/corpus_accounting_spec.rb, matched in order.
|
|
43
|
+
Route = Struct.new(:pattern, :check, :destination, :names, :why)
|
|
44
|
+
|
|
45
|
+
ROUTES = [
|
|
46
|
+
Route.new(%r{\Atmp/}, :gitignored, ".gitignore", "tmp/",
|
|
47
|
+
"scratch output — generated and mined candidate domains, fuzz failures — never committed"),
|
|
48
|
+
Route.new(%r{/\.aws-sam/}, :gitignored, ".gitignore", ".aws-sam/",
|
|
49
|
+
"SAM build output — a vendored copy of real sources, never committed"),
|
|
50
|
+
Route.new(%r{/data/eras/}, :gitignored, ".gitignore", "**/data/eras/",
|
|
51
|
+
"era snapshots a file adapter writes at runtime, never committed"),
|
|
52
|
+
Route.new(%r{\Arust/}, :named_in, "rust/parser/tests/gates.rs", :each_file,
|
|
53
|
+
"the Rust parser's own fixtures, each loaded by its gate tests"),
|
|
54
|
+
Route.new(%r{/translations/}, :named_in, "spec/translation/committed_edges_spec.rb", "bluebook/translations",
|
|
55
|
+
"translation edges, not chapters; each must load, chain era to era, and end at the storage " \
|
|
56
|
+
"shape its bluebook declares today"),
|
|
57
|
+
Route.new(%r{\Alib/hecks/forms/examples/}, :named_in, "spec/forms/app_spec.rb", :each_file,
|
|
58
|
+
"a Forms presentation config wearing the .bluebook extension"),
|
|
59
|
+
Route.new(%r{\Aspec/fixtures/eras/}, :named_in, "spec/runtime/storage_shape_spec.rb", "fixtures/eras",
|
|
60
|
+
"deliberately conflicting versions of one domain; each must classify as the verdict " \
|
|
61
|
+
"its filename declares (bump_* / same_*)"),
|
|
62
|
+
Route.new(%r{\Aspec/fixtures/model_check/}, :named_in, "spec/model_check_spec.rb", :each_file,
|
|
63
|
+
"domains broken on purpose; each must produce exactly the finding kinds it is built to trigger"),
|
|
64
|
+
# hecks fuzz sweeps it too, once Fuzzing::Replay coerces value-object args
|
|
65
|
+
# before recomputing givens — today it doesn't, so this given reads as
|
|
66
|
+
# wrongly admitted.
|
|
67
|
+
Route.new(%r{\Aspec/fixtures/rust_host/}, :named_in, "rust/host/src/web.rs", "checkout_fixture",
|
|
68
|
+
"the Rust host's checkout fixture, pinned by its web and /api tests")
|
|
69
|
+
].freeze
|
|
70
|
+
|
|
71
|
+
module_function
|
|
72
|
+
|
|
73
|
+
# Lists corpus members of the given kinds (every kind, by default).
|
|
74
|
+
#
|
|
75
|
+
# @param kinds [Array<Symbol>] corpus kinds to include, from `KINDS`; every kind
|
|
76
|
+
# when empty
|
|
77
|
+
# @param root [String] repository root to search under
|
|
78
|
+
# @return [Array<Member>] matching members
|
|
79
|
+
# @raise [ArgumentError] if `kinds` names a kind not in `KINDS`
|
|
80
|
+
def members(*kinds, root: ROOT)
|
|
81
|
+
kinds = KINDS if kinds.empty?
|
|
82
|
+
kinds.flat_map do |kind|
|
|
83
|
+
if (glob = DIRECTORY_KINDS[kind])
|
|
84
|
+
Dir.glob(File.join(root, glob)).select { |path| File.directory?(path) }.sort
|
|
85
|
+
.map { |dir| Member.new(File.basename(dir), kind, dir) }
|
|
86
|
+
elsif (glob = FILE_KINDS[kind])
|
|
87
|
+
prefix = File.join(root, glob[/\A[^*]*/].chomp("/"))
|
|
88
|
+
Dir.glob(File.join(root, glob))
|
|
89
|
+
.map { |file| Member.new(file.delete_prefix("#{prefix}/").delete_suffix(".bluebook"), kind, file) }
|
|
90
|
+
else
|
|
91
|
+
raise ArgumentError, "unknown corpus kind #{kind.inspect} — known: #{KINDS.join(', ')}"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# What a boot loads for a member — a directory kind's bluebook
|
|
97
|
+
# directory, or a file kind's own file.
|
|
98
|
+
#
|
|
99
|
+
# @param member [Member] the corpus member
|
|
100
|
+
# @return [String, nil] the path to boot, or nil when a directory member holds
|
|
101
|
+
# no bluebook
|
|
102
|
+
def source_of(member)
|
|
103
|
+
DIRECTORY_KINDS.key?(member.kind) ? bluebook_dir(member.path) : member.path
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# How a domain's hecksagon names a chapter the gem carries and loads by name, as the QA
|
|
107
|
+
# ledger's does (`Hecks::Chapters.load!("QualityControl")`).
|
|
108
|
+
ATTACHED_CHAPTER = /Chapters\.load!\(\s*"([^"]+)"\s*\)/
|
|
109
|
+
|
|
110
|
+
# Where a domain path keeps its bluebooks — `<domain>/bluebook/*.bluebook`, or the directory
|
|
111
|
+
# itself when that holds none, or the chapter files its hecksagons load by name (the QA
|
|
112
|
+
# ledger, `qa/bluebook`, holds only wiring: its chapter ships in `lib/hecks/quality_control/`).
|
|
113
|
+
#
|
|
114
|
+
# @param domain_path [String] path to a domain directory
|
|
115
|
+
# @return [Array<String>, nil] `.bluebook` file paths found, or nil when none
|
|
116
|
+
def bluebook_files(domain_path)
|
|
117
|
+
[File.join(domain_path, "bluebook"), domain_path].each do |dir|
|
|
118
|
+
files = Dir[File.join(dir, "*.bluebook")]
|
|
119
|
+
return files unless files.empty?
|
|
120
|
+
end
|
|
121
|
+
attached_chapter_files(domain_path)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# The bluebook files of every chapter a domain's own hecksagons load by name.
|
|
125
|
+
#
|
|
126
|
+
# @param domain_path [String] path to a domain directory
|
|
127
|
+
# @return [Array<String>, nil] the chapters' `.bluebook` file paths, or nil when none is named
|
|
128
|
+
def attached_chapter_files(domain_path)
|
|
129
|
+
names = Dir[File.join(domain_path, "{bluebook/,}*.hecksagon")]
|
|
130
|
+
.flat_map { |path| File.read(path).scan(ATTACHED_CHAPTER).flatten }.uniq
|
|
131
|
+
files = names.flat_map { |name| Chapters.index.fetch(name, []) }
|
|
132
|
+
files.empty? ? nil : files
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# The directory holding `domain_path`'s bluebooks.
|
|
136
|
+
#
|
|
137
|
+
# @param domain_path [String] path to a domain directory
|
|
138
|
+
# @return [String, nil] directory of the first `.bluebook` file found, or nil
|
|
139
|
+
# when `domain_path` holds none
|
|
140
|
+
def bluebook_dir(domain_path)
|
|
141
|
+
files = bluebook_files(domain_path)
|
|
142
|
+
files && File.dirname(files.first)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# The route a repo-relative path takes instead of the sweep — the
|
|
146
|
+
# first one it matches — or `nil` when the sweep boots it.
|
|
147
|
+
#
|
|
148
|
+
# @param relative_path [String] a corpus member's path, relative to the repo root
|
|
149
|
+
# @return [Route, nil] the first matching route, or nil when the sweep boots it
|
|
150
|
+
def route_for(relative_path)
|
|
151
|
+
ROUTES.find { |route| route.pattern.match?(relative_path) }
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Every kind hecks model_check walks: excludes language/deploy (checked
|
|
155
|
+
# elsewhere) and anything a route already sends to its own destination.
|
|
156
|
+
MODEL_CHECK_KINDS = %i[example grammar framework vendored qa stress fixture hecks].freeze
|
|
157
|
+
|
|
158
|
+
# Every corpus member `hecks model_check` and `spec/model_check_spec.rb` walk.
|
|
159
|
+
#
|
|
160
|
+
# @param root [String] repository root to search under
|
|
161
|
+
# @return [Array<Member>] members of `MODEL_CHECK_KINDS`, less any routed elsewhere
|
|
162
|
+
def model_check_members(root: ROOT)
|
|
163
|
+
members(*MODEL_CHECK_KINDS, root: root).reject { |member| route_for(member.path.delete_prefix("#{root}/")) }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# **The ledger sweeps itself** — its own chapter is a domain like any
|
|
167
|
+
# other, and the one rotation member that is neither an example nor a
|
|
168
|
+
# stress domain.
|
|
169
|
+
ROTATION_LEDGER = { "quality_control" => "qa/bluebook" }.freeze
|
|
170
|
+
|
|
171
|
+
# What the QA rotation is made of — every example and stress domain,
|
|
172
|
+
# plus the ledger, as `reference => repo-relative path` — derived, not hand-kept.
|
|
173
|
+
#
|
|
174
|
+
# @param root [String] repository root to search under
|
|
175
|
+
# @return [Hash{String => String}] each rotation member's stem/reference mapped
|
|
176
|
+
# to its repo-relative path
|
|
177
|
+
def rotation_targets(root: ROOT)
|
|
178
|
+
members(:example, :stress, root: root)
|
|
179
|
+
.to_h { |member| [member.stem, member.path.delete_prefix("#{root}/")] }
|
|
180
|
+
.merge(ROTATION_LEDGER)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Every bootable domain in the project — any directory holding a
|
|
184
|
+
# `.bluebook` no route sends elsewhere (a `bluebook/` folder stands for its parent).
|
|
185
|
+
#
|
|
186
|
+
# @param root [String] repository root to search under
|
|
187
|
+
# @return [Array<String>] absolute paths of every sweepable domain directory
|
|
188
|
+
def sweepable_domains(root = ROOT)
|
|
189
|
+
Dir.chdir(root) do
|
|
190
|
+
Dir.glob("**/*.bluebook")
|
|
191
|
+
.reject { |path| route_for(path) }
|
|
192
|
+
.map { |path| File.dirname(path) }
|
|
193
|
+
.map { |dir| File.basename(dir) == "bluebook" ? File.dirname(dir) : dir }
|
|
194
|
+
.uniq.sort
|
|
195
|
+
.map { |dir| File.join(root, dir) }
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Sweepable domains a fuzz cannot boot from its copy, by repo-relative directory, each with
|
|
200
|
+
# the reason. A fuzz boots a tmpdir copy of a domain to isolate its state.
|
|
201
|
+
FUZZ_UNBOOTABLE = {
|
|
202
|
+
"lib/hecks/hecks" => "the gem's own chapter; model_check covers it",
|
|
203
|
+
"spec/fixtures/qa_discover_external_domains/projects/hecks" => "declares the reserved chapter name `Hecks`"
|
|
204
|
+
}.freeze
|
|
205
|
+
|
|
206
|
+
# Every sweepable domain a fuzz can boot: `sweepable_domains` less `FUZZ_UNBOOTABLE`.
|
|
207
|
+
#
|
|
208
|
+
# @param root [String] repository root to search under
|
|
209
|
+
# @return [Array<String>] absolute paths of the domain directories `hecks fuzz` sweeps
|
|
210
|
+
def fuzzable_domains(root = ROOT)
|
|
211
|
+
sweepable_domains(root) - FUZZ_UNBOOTABLE.keys.map { |dir| File.join(root, dir) }
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# The domain directory a member stands for, spelled the way
|
|
215
|
+
# `sweepable_domains` spells it: a `bluebook/` folder is its parent.
|
|
216
|
+
#
|
|
217
|
+
# @param member [Member] the corpus member
|
|
218
|
+
# @return [String] the member's owning domain directory path
|
|
219
|
+
def domain_dir_of(member)
|
|
220
|
+
dir = File.directory?(member.path) ? member.path : File.dirname(member.path)
|
|
221
|
+
File.basename(dir) == "bluebook" ? File.dirname(dir) : dir
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Every Rust-facing list reads `rust/Cargo.toml`'s `[features]` as its
|
|
225
|
+
# one source, rather than each consumer typing it out by hand.
|
|
226
|
+
GENERATED_DIR = "rust/src/generated".freeze
|
|
227
|
+
RUST_DOMAIN_KINDS = %i[example stress fixture].freeze
|
|
228
|
+
|
|
229
|
+
RustDomain = Struct.new(:feature, :dir, :kind)
|
|
230
|
+
|
|
231
|
+
# `check: :named_in` — `destination` must name `names`.
|
|
232
|
+
Elsewhere = Struct.new(:check, :destination, :names, :why)
|
|
233
|
+
|
|
234
|
+
RUST_ELSEWHERE = {
|
|
235
|
+
"meta" => Elsewhere.new(:named_in, "spec/codegen_parity_spec.rb", "bluebook_language",
|
|
236
|
+
"the self-hosted grammar (lib/hecks/language), not a domain directory — every " \
|
|
237
|
+
"hecks project_rust run rewrites it (so the drift check diffs it), codegen parity " \
|
|
238
|
+
"checks it as bluebook_language, and there is no directory to fuzz")
|
|
239
|
+
}.freeze
|
|
240
|
+
|
|
241
|
+
# Every place a Rust-facing domain's own `uses_framework`/
|
|
242
|
+
# `uses_embryonaut_bluebook` attachment could be declared.
|
|
243
|
+
#
|
|
244
|
+
# @param root [String] repository root to search under
|
|
245
|
+
# @return [String] every reachable hecksagon file's own text, joined by newlines
|
|
246
|
+
def rust_attachment_hecksagon_text(root: ROOT)
|
|
247
|
+
rust_domains(root: root).flat_map { |domain| Dir.glob(File.join(domain.dir, "**", "*.hecksagon")) }
|
|
248
|
+
.map { |path| File.read(path) }.join("\n")
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# **Shrink-only**: a generated module `hecks rust_coverage` still flags.
|
|
252
|
+
# `hecks corpus_rust_coverage --rust-coverage` requires each entry to still fail, so a
|
|
253
|
+
# newly-passing module breaks the build until removed here.
|
|
254
|
+
RUST_COVERAGE_PENDING = {}.freeze
|
|
255
|
+
|
|
256
|
+
# The Cargo `[features]` table's raw text.
|
|
257
|
+
#
|
|
258
|
+
# @param root [String] repository root to search under
|
|
259
|
+
# @return [String] the table's text, or `""` when `rust/Cargo.toml` has none
|
|
260
|
+
def cargo_features_table(root: ROOT)
|
|
261
|
+
File.read(File.join(root, "rust/Cargo.toml"))[Fuzzing::TargetCapabilities::FEATURES_TABLE] || ""
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Every feature name Cargo declares with no dependency array of its own.
|
|
265
|
+
#
|
|
266
|
+
# @param root [String] repository root to search under
|
|
267
|
+
# @return [Array<String>] feature names, in file order
|
|
268
|
+
def cargo_features(root: ROOT)
|
|
269
|
+
cargo_features_table(root: root).scan(/^(\w+)\s*=\s*\[\]/).flatten
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# The feature `hecks project_rust` last wrote as Cargo's `default`.
|
|
273
|
+
#
|
|
274
|
+
# @param root [String] repository root to search under
|
|
275
|
+
# @return [String, nil] the default feature's name, or nil when Cargo.toml
|
|
276
|
+
# declares none
|
|
277
|
+
def cargo_default(root: ROOT)
|
|
278
|
+
cargo_features_table(root: root)[/^default\s*=\s*\["(\w+)"\]/, 1]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Every in-repo domain directory whose name is a Cargo feature, sorted
|
|
282
|
+
# by path — disambiguated by the generated module's metadata.rs stamp when one exists.
|
|
283
|
+
#
|
|
284
|
+
# @param root [String] repository root to search under
|
|
285
|
+
# @return [Array<RustDomain>] each Rust-facing domain, sorted by directory path
|
|
286
|
+
def rust_domains(root: ROOT)
|
|
287
|
+
features = cargo_features(root: root)
|
|
288
|
+
members(*RUST_DOMAIN_KINDS, root: root)
|
|
289
|
+
.map { |member| [domain_dir_of(member), member.kind] }
|
|
290
|
+
.uniq(&:first)
|
|
291
|
+
.select { |dir, _| rust_domain_dir?(dir, features, root) }
|
|
292
|
+
.sort_by(&:first)
|
|
293
|
+
.map { |dir, kind| RustDomain.new(File.basename(dir).downcase, dir, kind) }
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Tells whether `dir` is the real source directory for its Cargo feature.
|
|
297
|
+
#
|
|
298
|
+
# @param dir [String] a candidate domain directory
|
|
299
|
+
# @param features [Array<String>] known Cargo feature names
|
|
300
|
+
# @param root [String] repository root `dir` is rooted under
|
|
301
|
+
# @return [Boolean]
|
|
302
|
+
def rust_domain_dir?(dir, features, root)
|
|
303
|
+
feature = File.basename(dir).downcase
|
|
304
|
+
source = generated_source(feature, root: root)
|
|
305
|
+
features.include?(feature) && (source.nil? || source == dir.delete_prefix("#{root}/"))
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# The stamp hecks project_rust writes into metadata.rs, e.g.
|
|
309
|
+
# `examples/pizzas` or `the self-hosted language (...)`, with any
|
|
310
|
+
# ` (uses_framework "X")`/` (uses_embryonaut_bluebook "X")` suffix stripped.
|
|
311
|
+
SOURCE_STAMP = /
|
|
312
|
+
GENERATED\ by\ hecks\ project_rust\ —\ (.+?)
|
|
313
|
+
(?:\ \((?:uses_framework|uses_embryonaut_bluebook)\ "\w+"\))?
|
|
314
|
+
's\ own\ canonical\ IR,
|
|
315
|
+
/x
|
|
316
|
+
|
|
317
|
+
# Where a generated module came from, read off the stamp `hecks project_rust`
|
|
318
|
+
# writes into its metadata.rs.
|
|
319
|
+
#
|
|
320
|
+
# @param module_name [String] a generated module's name
|
|
321
|
+
# @param root [String] repository root to search under
|
|
322
|
+
# @return [String, nil] the source path the stamp names, or nil when the module
|
|
323
|
+
# is not generated
|
|
324
|
+
def generated_source(module_name, root: ROOT)
|
|
325
|
+
metadata = File.join(root, GENERATED_DIR, module_name, "metadata.rs")
|
|
326
|
+
File.file?(metadata) ? File.read(metadata)[SOURCE_STAMP, 1] : nil
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Every module directory under `rust/src/generated`.
|
|
330
|
+
#
|
|
331
|
+
# @param root [String] repository root to search under
|
|
332
|
+
# @return [Array<String>] generated module names, sorted
|
|
333
|
+
def generated_modules(root: ROOT)
|
|
334
|
+
Dir.children(File.join(root, GENERATED_DIR)).select { |name| File.directory?(File.join(root, GENERATED_DIR, name)) }.sort
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# Tells whether `feature` has already been generated (has a merged.rs).
|
|
338
|
+
#
|
|
339
|
+
# @param feature [String] a Cargo feature / domain name
|
|
340
|
+
# @param root [String] repository root to search under
|
|
341
|
+
# @return [Boolean]
|
|
342
|
+
def generated?(feature, root: ROOT)
|
|
343
|
+
File.file?(File.join(root, GENERATED_DIR, feature, "merged.rs"))
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# Chapters attached via `kind` that get a generated module as a side
|
|
347
|
+
# effect of the attaching domain's regen, with no merged.rs of their own.
|
|
348
|
+
#
|
|
349
|
+
# @param kind [Symbol] :framework or :vendored
|
|
350
|
+
# @param root [String] repository root to search under
|
|
351
|
+
# @return [Array<String>] stems with a generated module but no merged.rs
|
|
352
|
+
# of their own
|
|
353
|
+
def rust_side_chapters(kind, root: ROOT)
|
|
354
|
+
modules = generated_modules(root: root)
|
|
355
|
+
members(kind, root: root).map(&:stem)
|
|
356
|
+
.select do |stem|
|
|
357
|
+
module_name = Naming.pascal(stem).downcase
|
|
358
|
+
modules.include?(module_name) && !generated?(module_name, root: root)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# The generated module name a `:framework`/`:vendored` stem writes
|
|
363
|
+
# under — strips underscores, so it can differ from the raw stem.
|
|
364
|
+
#
|
|
365
|
+
# @param stem [String] a `:framework`/`:vendored` corpus member's stem
|
|
366
|
+
# @return [String] the generated module's own directory name
|
|
367
|
+
def rust_side_module_name(stem)
|
|
368
|
+
Naming.pascal(stem).downcase
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Names the framework chapters Rust carries as modules, beside its domains' own bluebooks.
|
|
372
|
+
#
|
|
373
|
+
# @param root [String] repository root to search under
|
|
374
|
+
# @return [Array<String>] generated module names for the `:framework` corpus members
|
|
375
|
+
def rust_framework_chapters(root: ROOT)
|
|
376
|
+
rust_side_chapters(:framework, root: root)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Names the vendored chapters Rust carries as modules, beside its domains' own bluebooks.
|
|
380
|
+
#
|
|
381
|
+
# @param root [String] repository root to search under
|
|
382
|
+
# @return [Array<String>] generated module names for the `:vendored` corpus members
|
|
383
|
+
def rust_vendored_chapters(root: ROOT)
|
|
384
|
+
rust_side_chapters(:vendored, root: root)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Chapters an in-repo Rust domain carries beside its own bluebook,
|
|
388
|
+
# written as a module by `hecks project_rust` with no merged.rs of its own.
|
|
389
|
+
#
|
|
390
|
+
# @param root [String] repository root to search under
|
|
391
|
+
# @return [Array<String>] generated module names with no merged.rs of their own
|
|
392
|
+
def rust_sibling_chapters(root: ROOT)
|
|
393
|
+
modules = generated_modules(root: root)
|
|
394
|
+
rust_domains(root: root)
|
|
395
|
+
.flat_map { |domain| Dir.glob(File.join(domain.dir, "bluebook", "*.bluebook")) }
|
|
396
|
+
.map { |path| Naming.pascal(File.basename(path, ".bluebook")).downcase }
|
|
397
|
+
.uniq
|
|
398
|
+
.select { |name| modules.include?(name) && !generated?(name, root: root) }
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
# The regeneration order the drift check runs, sorted by path — so which
|
|
402
|
+
# domain wins Cargo's `default` is derived, not hand-picked.
|
|
403
|
+
#
|
|
404
|
+
# @param root [String] repository root to search under
|
|
405
|
+
# @return [Array<RustDomain>] already-generated Rust domains, in regeneration order
|
|
406
|
+
def rust_regen_order(root: ROOT)
|
|
407
|
+
rust_domains(root: root).select { |domain| generated?(domain.feature, root: root) }
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# The chapter a bluebook declares — `Hecks.bluebook "<Name>"` — read off
|
|
411
|
+
# the file rather than guessed from its name, since the two can differ.
|
|
412
|
+
#
|
|
413
|
+
# @param bluebook_path [String, Array<String>] a `.bluebook` file path, or an
|
|
414
|
+
# array whose first element is used
|
|
415
|
+
# @return [String, nil] the declared chapter name, or nil when the file never
|
|
416
|
+
# declares one
|
|
417
|
+
def chapter_name_of(bluebook_path)
|
|
418
|
+
bluebook_path = Array(bluebook_path).first
|
|
419
|
+
header = File.foreach(bluebook_path).find { |line| line =~ /\A\s*Hecks\.bluebook\s+"([^"]+)"/ }
|
|
420
|
+
header && Regexp.last_match(1)
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|