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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module QualityControlCli
|
|
5
|
+
class QaSweep
|
|
6
|
+
# The dials a sweep reads once the ledger has booted, and the modes they enable. A dial-less
|
|
7
|
+
# fixture ledger falls back to a sweep with the adversarial layer off and self-consistency on.
|
|
8
|
+
module Dials
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def dial(name, fallback)
|
|
12
|
+
::QualityControlDials.const_defined?(name, false) ? ::QualityControlDials.const_get(name) : fallback
|
|
13
|
+
rescue NameError
|
|
14
|
+
fallback
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Dials are read after boot because the bluebook defines them; a dial-less fixture ledger
|
|
18
|
+
# runs the adversarial layer off and self-consistency on.
|
|
19
|
+
def read_dials
|
|
20
|
+
@adversarial ||= dial(:ADVERSARIAL_FRACTION, 0.0).to_f
|
|
21
|
+
# Remembered before defaulting: the alias below applies only when the flag was typed, so
|
|
22
|
+
# an explicit `--modes ruby_only` stays exclusive.
|
|
23
|
+
@self_consistency_explicit = !@self_consistency.nil?
|
|
24
|
+
@self_consistency = dial(:SELF_CONSISTENCY_CHECKS, true) if @self_consistency.nil?
|
|
25
|
+
# Same off-without-a-dial default as the adversarial layer.
|
|
26
|
+
@role_draw ||= dial(:ROLE_DRAW_PROBABILITY, 0.0).to_f
|
|
27
|
+
@dry_run ||= dial(:DRY_RUN_FRACTION, 0.0).to_f
|
|
28
|
+
# The loop's identity: `held_by` on claims, `engineer` on sweeps, and the literal
|
|
29
|
+
# `WaivedBy` refuses.
|
|
30
|
+
@engineer = dial(:AUTOMATED_ENGINEER, "qa_sweep")
|
|
31
|
+
@widening_tiers = dial(:WIDENING_TIERS, Hecks::Fuzzing::SweepDepth::DEFAULT_TIERS)
|
|
32
|
+
@guided_generation = dial(:GUIDED_GENERATION, false)
|
|
33
|
+
@corpus_splice_probability = dial(:CORPUS_SPLICE_PROBABILITY, 0.5)
|
|
34
|
+
@favor_rare_verbs = dial(:FAVOR_RARE_VERBS, 3)
|
|
35
|
+
@max_parallel = dial(:SWEEP_MAX_PARALLEL, 4)
|
|
36
|
+
@shrink_budget = dial(:SHRINK_BUDGET, 200)
|
|
37
|
+
@structural_boundary = dial(:STRUCTURAL_REFUSAL_BOUNDARY, [])
|
|
38
|
+
# The adapter pair each parity mode compares; a new pairing is a data change here, not a
|
|
39
|
+
# new diff.
|
|
40
|
+
@adapter_parity_pairs = dial(:ADAPTER_PARITY_PAIRS,
|
|
41
|
+
{ persistence_parity: { left: :memory, right: :postgres_era },
|
|
42
|
+
adapter_parity_sqlite: { left: :memory, right: :sqlite } }.freeze)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# `--modes` wins outright; otherwise the dial's enabled modes. `--self-consistency` adjusts
|
|
46
|
+
# the set only when typed or when `--modes` was not given, so an explicit `--modes a,b`
|
|
47
|
+
# stays exact.
|
|
48
|
+
def resolve_enabled_modes
|
|
49
|
+
@enabled_modes = @explicit_modes || dial_modes
|
|
50
|
+
if @self_consistency_explicit || @explicit_modes.nil?
|
|
51
|
+
@enabled_modes = if @self_consistency
|
|
52
|
+
@enabled_modes | [:self_consistency]
|
|
53
|
+
else
|
|
54
|
+
@enabled_modes - [:self_consistency]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
# `--all --persistence-parity` forces the wave on regardless of the dial.
|
|
58
|
+
@enabled_modes |= [:persistence_parity] if @force_parity_wave
|
|
59
|
+
|
|
60
|
+
# Refuse modes with no implementation before claiming, so `resolved modes:` never
|
|
61
|
+
# advertises coverage nobody wrote.
|
|
62
|
+
unrunnable = @enabled_modes - Hecks::Fuzzing::TargetCapabilities::RUNNABLE_MODES
|
|
63
|
+
return if unrunnable.empty?
|
|
64
|
+
|
|
65
|
+
abort "enabled mode(s) #{unrunnable.join(',')} have no implementation in hecks quality_control ask run " \
|
|
66
|
+
"(Hecks::Fuzzing::TargetCapabilities::RUNNABLE_MODES is what exists). Set them false in " \
|
|
67
|
+
"qa/settings.yml, or drop them from --modes, until the code lands."
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def dial_modes
|
|
71
|
+
return DEFAULT_MODES unless ::QualityControlDials.const_defined?(:MODES, false)
|
|
72
|
+
|
|
73
|
+
::QualityControlDials::MODES.select { |_, on| on }.keys
|
|
74
|
+
rescue NameError
|
|
75
|
+
DEFAULT_MODES
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# `--no-parity` skips every later wave. A mode gets a wave only when the dial enabled it and
|
|
79
|
+
# `--modes` did not narrow the run.
|
|
80
|
+
def deferred_waves
|
|
81
|
+
%i[era_boundary concurrency].select do |mode|
|
|
82
|
+
!@skip_parity_wave && @explicit_modes.nil? && @enabled_modes.include?(mode)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def parity_wave?
|
|
87
|
+
!@skip_parity_wave && @explicit_modes.nil? && @enabled_modes.include?(:persistence_parity)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module QualityControlCli
|
|
5
|
+
class QaSweep
|
|
6
|
+
# What a sweep prints when a check surprised: the header, the reproduction, every divergence
|
|
7
|
+
# and the generated and shrunk steps, so an agent can decide from the report alone.
|
|
8
|
+
module FindingReport
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# @param surprise [Hash] the surprising seed's result: `seed`, `steps`, `checks`, `plan` and
|
|
12
|
+
# optionally `shrunk`
|
|
13
|
+
# @return [void]
|
|
14
|
+
def print_finding(surprise)
|
|
15
|
+
print_finding_header
|
|
16
|
+
print_finding_facts(surprise)
|
|
17
|
+
# One block per surprised check, so a seed that surprised on two axes prints both.
|
|
18
|
+
surprise[:checks].each { |check| print_surprised_check(check) }
|
|
19
|
+
print_generated_steps(surprise[:steps])
|
|
20
|
+
# One shrunk demonstration per shrinkable check, written to a file so the replay line
|
|
21
|
+
# works as printed.
|
|
22
|
+
Array(surprise[:shrunk]).each { |shrunk| print_shrunk(shrunk, surprise[:seed]) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def print_finding_header
|
|
26
|
+
puts
|
|
27
|
+
puts "=" * 72
|
|
28
|
+
puts "FOUND SOMETHING — sweep #{@sweep_reference} left OPEN, target #{@target_reference} SUSPENDED."
|
|
29
|
+
puts "No Bug was logged (that needs a real failing-test demonstration, which"
|
|
30
|
+
puts "needs judgment this script does not have — hecks quality_control log is the door)"
|
|
31
|
+
puts "and the sweep was not concluded. The ledger's own SuspendOnSurprise"
|
|
32
|
+
puts "policy took the target out of the rotation; it stays out until a PERSON"
|
|
33
|
+
puts "runs: hecks quality_control ask run target=#{@target_reference} " \
|
|
34
|
+
"arguments=\"--release --notes …\""
|
|
35
|
+
puts "An agent decides from here: self-contained fix with a regression test"
|
|
36
|
+
puts "and a PR (hecks quality_control patch.open), or a Bug left open for something bigger."
|
|
37
|
+
puts "Never waived here, never filed upstream from here."
|
|
38
|
+
puts "=" * 72
|
|
39
|
+
puts
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def print_finding_facts(surprise)
|
|
43
|
+
puts "domain: #{@target_path} (#{@domain_path})"
|
|
44
|
+
puts "target: #{@target_reference}"
|
|
45
|
+
puts "sweep: #{@sweep_reference} (id #{@sweep.id})"
|
|
46
|
+
puts "mode: #{@mode} (active modes: #{@active_modes.join(', ')}; " \
|
|
47
|
+
"capabilities: #{@capabilities.join(', ')})"
|
|
48
|
+
puts "seed: #{surprise[:seed] || 'n/a (once-per-sweep check)'}"
|
|
49
|
+
puts "steps: #{@steps_per_sequence}"
|
|
50
|
+
puts "adversarial: #{@adversarial}"
|
|
51
|
+
puts "role-draw: #{@role_draw}"
|
|
52
|
+
puts "dry-run: #{@dry_run}"
|
|
53
|
+
puts "streak: clean_streak was #{@current_streak} going into this pass"
|
|
54
|
+
if surprise[:seed]
|
|
55
|
+
puts "reproduce: Hecks::Fuzzing::SequenceGenerator.generate(#{@domain_path.inspect}, " \
|
|
56
|
+
"seed: #{surprise[:seed]}, steps: #{@steps_per_sequence}, adversarial: #{@adversarial}, " \
|
|
57
|
+
"role_draw: #{@role_draw}, dry_run: #{@dry_run}#{plan_arguments(surprise[:plan])})"
|
|
58
|
+
end
|
|
59
|
+
puts "surprised: #{surprise[:checks].map { |c| c[:mode] }.join(', ')}"
|
|
60
|
+
puts
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def print_surprised_check(check)
|
|
64
|
+
puts "subject: #{check[:subject]}"
|
|
65
|
+
puts "expectation: #{check[:expectation]}"
|
|
66
|
+
puts "observation: #{check[:observation]}"
|
|
67
|
+
puts
|
|
68
|
+
|
|
69
|
+
# One generic printer for every divergence shape (ruby/rust, memory/postgres_era,
|
|
70
|
+
# live/rehydrated): print every key except the field and the redundant
|
|
71
|
+
# domain/aggregate/type.
|
|
72
|
+
check[:divergences].each do |divergence|
|
|
73
|
+
label = [divergence[:field], divergence[:domain], divergence[:aggregate], divergence[:type]]
|
|
74
|
+
.compact.join(" ")
|
|
75
|
+
puts "-- #{label} --"
|
|
76
|
+
divergence.except(:field, :domain, :aggregate, :type).each { |key, value| puts "#{key}: #{value.inspect}" }
|
|
77
|
+
puts
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Lists every step in order with its `adversarial` metadata, so a divergence's verb matches
|
|
82
|
+
# back to its step and the Bug can name the mutation.
|
|
83
|
+
def print_generated_steps(steps)
|
|
84
|
+
puts "-- generated steps (index: verb, adversarial mutation if any) --"
|
|
85
|
+
steps.each_with_index do |step, index|
|
|
86
|
+
label = %w[verb query dry_run].filter_map { |key| step[key] if step.key?(key) }.first
|
|
87
|
+
mutation = step["adversarial"] ? JSON.generate(step["adversarial"]) : "(not mutated)"
|
|
88
|
+
puts "#{index}: #{label} #{mutation}"
|
|
89
|
+
puts " args: #{JSON.generate(step['args'])}" if step["adversarial"]
|
|
90
|
+
end
|
|
91
|
+
puts
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def print_shrunk(shrunk, seed)
|
|
95
|
+
path = write_shrunk!(shrunk, seed)
|
|
96
|
+
budget = shrunk[:exhausted] ? ", budget exhausted — may shrink further" : ""
|
|
97
|
+
puts "shrunk: [#{shrunk[:mode]}] #{shrunk[:original_size]} -> #{shrunk[:steps].size} step(s) " \
|
|
98
|
+
"(#{shrunk[:attempts]} candidate checks#{budget})"
|
|
99
|
+
puts "file: #{path.delete_prefix("#{@root}/")}"
|
|
100
|
+
replay =
|
|
101
|
+
if %i[differential self_consistency].include?(shrunk[:mode]) && @binary
|
|
102
|
+
"hecks check_conformance domain=#{@domain_path} script=#{path} artifact=#{@binary}"
|
|
103
|
+
else
|
|
104
|
+
"hecks run #{@domain_path} #{path}"
|
|
105
|
+
end
|
|
106
|
+
puts "replay: #{replay}"
|
|
107
|
+
puts "-- shrunk steps [#{shrunk[:mode]}] --"
|
|
108
|
+
shrunk[:steps].each_with_index do |step, index|
|
|
109
|
+
kind = %w[verb query dry_run].find { |key| step.key?(key) }
|
|
110
|
+
puts "#{index}: #{"#{kind} " unless kind == 'verb'}#{step[kind]} args: #{JSON.generate(step['args'])}"
|
|
111
|
+
end
|
|
112
|
+
puts
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module QualityControlCli
|
|
5
|
+
class QaSweep
|
|
6
|
+
# The command line of `QaSweep`: every flag, and the rules for which combinations are refused.
|
|
7
|
+
#
|
|
8
|
+
# `seeds_override` and `steps_override` stay nil rather than a default, so an explicit
|
|
9
|
+
# `--seeds 10` can be told apart from the streak-derived depth. The dials are read after the
|
|
10
|
+
# ledger boots, so `adversarial`, `self_consistency`, `role_draw` and `dry_run` stay nil
|
|
11
|
+
# until then.
|
|
12
|
+
module Parsing
|
|
13
|
+
# Each flag that reads a value, and the setting it fills.
|
|
14
|
+
VALUE_SETTINGS = { "--role-draw" => :role_draw, "--dry-run" => :dry_run, "--adversarial" => :adversarial,
|
|
15
|
+
"--seeds" => :seeds_override, "--steps" => :steps_override }.freeze
|
|
16
|
+
|
|
17
|
+
# Each flag that stands alone, and the setting it turns on.
|
|
18
|
+
SWITCH_SETTINGS = { "--all" => :all_mode, "--no-parity" => :skip_parity_wave,
|
|
19
|
+
"--release" => :release_mode }.freeze
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# Parses the flags into the instance's settings.
|
|
24
|
+
#
|
|
25
|
+
# @param argv [Array<String>] the command line's arguments, consumed
|
|
26
|
+
# @return [Symbol, nil] `:help` once the usage is printed, else nil
|
|
27
|
+
# @raise [SystemExit] with the usage when a flag or combination is refused
|
|
28
|
+
def parse_arguments(argv)
|
|
29
|
+
@target_ref = @seeds_override = @steps_override = nil
|
|
30
|
+
@all_mode = @persistence_parity_mode = @skip_parity_wave = @release_mode = false
|
|
31
|
+
@adversarial = @self_consistency = @role_draw = @dry_run = nil
|
|
32
|
+
# `--modes` (or its alias `--persistence-parity`); nil means the dial decides.
|
|
33
|
+
@explicit_modes = nil
|
|
34
|
+
@release_notes = nil
|
|
35
|
+
until argv.empty?
|
|
36
|
+
arg = argv.shift
|
|
37
|
+
if %w[-h --help].include?(arg)
|
|
38
|
+
puts USAGE
|
|
39
|
+
return :help
|
|
40
|
+
end
|
|
41
|
+
parse_flag(arg, argv)
|
|
42
|
+
end
|
|
43
|
+
validate_arguments
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def parse_flag(arg, argv)
|
|
48
|
+
if SWITCH_SETTINGS.key?(arg)
|
|
49
|
+
instance_variable_set(:"@#{SWITCH_SETTINGS.fetch(arg)}", true)
|
|
50
|
+
elsif VALUE_SETTINGS.key?(arg)
|
|
51
|
+
parse_value_flag(arg, argv.shift)
|
|
52
|
+
else
|
|
53
|
+
parse_other_flag(arg, argv)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def parse_value_flag(arg, value)
|
|
58
|
+
setting = VALUE_SETTINGS.fetch(arg)
|
|
59
|
+
parsed = %w[--seeds --steps].include?(arg) ? parse_integer(arg, value) : parse_fraction(arg, value)
|
|
60
|
+
instance_variable_set(:"@#{setting}", parsed)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def parse_other_flag(arg, argv)
|
|
64
|
+
case arg
|
|
65
|
+
when "--persistence-parity"
|
|
66
|
+
@persistence_parity_mode = true
|
|
67
|
+
@explicit_modes = %i[persistence_parity]
|
|
68
|
+
when "--modes"
|
|
69
|
+
@explicit_modes = parse_modes(argv.shift)
|
|
70
|
+
@persistence_parity_mode = @explicit_modes == %i[persistence_parity]
|
|
71
|
+
when "--notes"
|
|
72
|
+
@release_notes = argv.shift
|
|
73
|
+
abort "#{USAGE}\n--notes needs the text a person concluded" unless @release_notes
|
|
74
|
+
when "--self-consistency" then @self_consistency = parse_boolean(arg, argv.shift)
|
|
75
|
+
else record_target(arg)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def record_target(arg)
|
|
80
|
+
abort "#{USAGE}\nunexpected argument: #{arg.inspect} (target already given: #{@target_ref.inspect})" if @target_ref
|
|
81
|
+
|
|
82
|
+
@target_ref = arg
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def parse_modes(value)
|
|
86
|
+
names = value.to_s.split(",").map(&:strip).reject(&:empty?).map(&:to_sym)
|
|
87
|
+
abort "#{USAGE}\n--modes needs at least one mode name" if names.empty?
|
|
88
|
+
|
|
89
|
+
known = Hecks::Fuzzing::TargetCapabilities::MODE_REQUIREMENTS.keys
|
|
90
|
+
unknown = names - known
|
|
91
|
+
abort "#{USAGE}\n--modes names no such mode: #{unknown.join(', ')} (known: #{known.join(', ')})" unless unknown.empty?
|
|
92
|
+
|
|
93
|
+
names
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def parse_fraction(flag, value)
|
|
97
|
+
abort "#{USAGE}\n#{flag} needs a fraction between 0 and 1" unless value
|
|
98
|
+
|
|
99
|
+
fraction = begin
|
|
100
|
+
Float(value)
|
|
101
|
+
rescue ArgumentError
|
|
102
|
+
abort "#{USAGE}\n#{flag} must be a number, got #{value.inspect}"
|
|
103
|
+
end
|
|
104
|
+
abort "#{USAGE}\n#{flag} must be between 0 and 1, got #{value}" unless fraction.between?(0, 1)
|
|
105
|
+
fraction
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def parse_integer(flag, value)
|
|
109
|
+
abort "#{USAGE}\n#{flag} needs a number" unless value
|
|
110
|
+
|
|
111
|
+
begin
|
|
112
|
+
Integer(value)
|
|
113
|
+
rescue ArgumentError
|
|
114
|
+
abort "#{USAGE}\n#{flag} must be an integer, got #{value.inspect}"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def parse_boolean(flag, value)
|
|
119
|
+
abort "#{USAGE}\n#{flag} needs true or false" unless value
|
|
120
|
+
|
|
121
|
+
case value
|
|
122
|
+
when "true" then true
|
|
123
|
+
when "false" then false
|
|
124
|
+
else abort "#{USAGE}\n#{flag} must be true or false, got #{value.inspect}"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def validate_arguments
|
|
129
|
+
if @seeds_override && @seeds_override < 1
|
|
130
|
+
abort "#{USAGE}\n--seeds must be at least 1 — Sweep.Conclude refuses a sweep that checked nothing"
|
|
131
|
+
end
|
|
132
|
+
abort "#{USAGE}\n--steps must be at least 1" if @steps_override && @steps_override < 1
|
|
133
|
+
if @all_mode && @target_ref
|
|
134
|
+
abort "#{USAGE}\n--all sweeps every waiting target itself — it does not take a target-reference " \
|
|
135
|
+
"(got #{@target_ref.inspect})"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# `--all --persistence-parity` forces the parity wave on; narrowing every child to that
|
|
139
|
+
# one mode would abort each ineligible target. A single named target still narrows to that
|
|
140
|
+
# mode.
|
|
141
|
+
@force_parity_wave = @all_mode && @persistence_parity_mode
|
|
142
|
+
if @force_parity_wave
|
|
143
|
+
@persistence_parity_mode = false
|
|
144
|
+
@explicit_modes = nil
|
|
145
|
+
end
|
|
146
|
+
validate_parity_and_release
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def validate_parity_and_release
|
|
150
|
+
if @persistence_parity_mode && !@target_ref
|
|
151
|
+
abort "#{USAGE}\n--persistence-parity needs an explicit target-reference — it never auto-picks " \
|
|
152
|
+
"from the rotation, since only a PostgresEra-bound domain gains anything from this " \
|
|
153
|
+
"comparison at all (`resolved modes:` on any single-target run says whether a target qualifies)"
|
|
154
|
+
end
|
|
155
|
+
validate_release if @release_mode
|
|
156
|
+
abort "#{USAGE}\n--notes only means something with --release" if @release_notes && !@release_mode
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def validate_release
|
|
160
|
+
unless @target_ref
|
|
161
|
+
abort "#{USAGE}\n--release needs an explicit target-reference — the suspended target a person is " \
|
|
162
|
+
"putting back"
|
|
163
|
+
end
|
|
164
|
+
unless @release_notes
|
|
165
|
+
abort "#{USAGE}\n--release needs --notes — what a person concluded is the one thing this script " \
|
|
166
|
+
"cannot supply"
|
|
167
|
+
end
|
|
168
|
+
return unless @all_mode || @persistence_parity_mode
|
|
169
|
+
|
|
170
|
+
abort "#{USAGE}\n--release is its own mode — it does not combine with --all or --persistence-parity"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module QualityControlCli
|
|
5
|
+
class QaSweep
|
|
6
|
+
# `--release`: a person puts a suspended target back. It concludes or abandons what was open
|
|
7
|
+
# against the target, then releases it with the streak moved by what was found.
|
|
8
|
+
module ReleaseMode
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# `--release`: a person puts a suspended target back, concluding what was open against it.
|
|
12
|
+
def release_suspended_target
|
|
13
|
+
target = ::QualityControl::Target.find(@target_reference)
|
|
14
|
+
abort "target #{@target_reference.inspect} vanished between being queried and being released" unless target
|
|
15
|
+
unless %w[suspended held].include?(target.status)
|
|
16
|
+
abort "target #{@target_reference.inspect} is #{target.status.inspect}, not suspended (or held) — " \
|
|
17
|
+
"nothing to release"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
open_sweeps = query("Sweep.Sweeping").select { |row| row[:target] == target.id }
|
|
21
|
+
.map { |row| ::QualityControl::Sweep.find(row[:reference][:value]) }
|
|
22
|
+
surprises = 0
|
|
23
|
+
clean = !open_sweeps.empty?
|
|
24
|
+
open_sweeps.each do |sweep|
|
|
25
|
+
surprises += query("Bug.FoundIn", sweep_id: { value: sweep.id }).size
|
|
26
|
+
clean &&= sweep_was_clean?(sweep)
|
|
27
|
+
close_open_sweep(sweep, surprises)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# No open sweep (a crash between claim and open): nothing was watched, so the streak
|
|
31
|
+
# resets rather than incrementing.
|
|
32
|
+
puts "no open sweep against #{@target_reference} — releasing with the streak reset" if open_sweeps.empty?
|
|
33
|
+
|
|
34
|
+
capabilities = Hecks::Fuzzing::TargetCapabilities.infer(@domain_path, rust_dir: @rust_dir)
|
|
35
|
+
was = target.status
|
|
36
|
+
target = release_target!(target, capabilities, target.clean_streak.value, surprises: surprises, clean: clean)
|
|
37
|
+
puts "released #{@target_reference} (was #{was}) — status #{target.status}, " \
|
|
38
|
+
"clean_streak #{target.clean_streak.value}, yield_score #{target.yield_score.value}, " \
|
|
39
|
+
"capabilities #{target.capabilities.value.inspect}"
|
|
40
|
+
EXIT_OK
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def close_open_sweep(sweep, surprises)
|
|
44
|
+
if sweep.made.value.positive? || sweep.waived.value.positive?
|
|
45
|
+
begin
|
|
46
|
+
sweep.conclude!(notes: { value: @release_notes })
|
|
47
|
+
rescue Hecks::Runtime::InvariantViolation => e
|
|
48
|
+
abort "--notes was refused by Sweep.Conclude — #{e.message}"
|
|
49
|
+
end
|
|
50
|
+
puts "concluded #{sweep.id} (#{sweep.made.value} check(s), #{surprises} bug(s) logged against it so far)"
|
|
51
|
+
else
|
|
52
|
+
# Never made a check: `Sweep.Conclude` refuses it, so abandon it to leave `Sweeping`.
|
|
53
|
+
sweep.abandon!
|
|
54
|
+
puts "abandoned #{sweep.id} (it never made a check)"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|