hecks 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +19 -12
- data/lib/hecks/adapters/driven/claude_code.rb +2 -2
- data/lib/hecks/adapters/driven/folder.rb +10 -1
- data/lib/hecks/adapters/driven/folder_overlay.rb +15 -0
- data/lib/hecks/adapters/driven/heki.rb +1 -1
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +1 -1
- data/lib/hecks/adapters/driven/memory/outbox_rows.rb +2 -2
- data/lib/hecks/adapters/driven/postgres/name_guard.rb +25 -0
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -3
- data/lib/hecks/adapters/driven/postgres/repository.rb +1 -1
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +1 -1
- data/lib/hecks/adapters/driven/postgres.rb +3 -0
- data/lib/hecks/adapters/driven/postgres_era/boot.rb +28 -16
- data/lib/hecks/adapters/driven/postgres_era/class_methods.rb +27 -7
- data/lib/hecks/adapters/driven/postgres_era/dialect.rb +10 -5
- data/lib/hecks/adapters/driven/postgres_era/field_cache_provisioner.rb +39 -0
- data/lib/hecks/adapters/driven/postgres_era/journal.rb +52 -13
- data/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +29 -49
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_sql.rb +73 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.json +10 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.rb +65 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename.rb +77 -25
- data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename_state.rb +108 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_integrity.rb +11 -6
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +63 -5
- data/lib/hecks/adapters/driven/postgres_era/lineage/layered_sql.rb +64 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/ledger_reset.rb +150 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_provisioning.rb +85 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +11 -7
- data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +11 -5
- data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +76 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/sql_templates.rb +9 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage.rb +10 -2
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/context.rb +23 -3
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +3 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/disposable_ledger.rb +119 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolution.rb +219 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +68 -71
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/held_era.rb +68 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/ledger_change.rb +63 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_decision.rb +163 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +24 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +59 -21
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +24 -11
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +40 -6
- data/lib/hecks/adapters/driven/postgres_era/shared_tables.rb +32 -0
- data/lib/hecks/adapters/driven/postgres_era.adapter +12 -0
- data/lib/hecks/adapters/driven/postgres_era.rb +25 -10
- data/lib/hecks/adapters/driven/prism.rb +0 -1
- data/lib/hecks/adapters/driven/sql_query_builder.rb +1 -0
- data/lib/hecks/adapters/driven/sqlite/dispatch_claims.rb +1 -1
- data/lib/hecks/adapters/driven/sqlite/name_guard.rb +25 -0
- data/lib/hecks/adapters/driven/sqlite/outbox.rb +2 -2
- data/lib/hecks/adapters/driven/sqlite/repository.rb +1 -1
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +20 -0
- data/lib/hecks/adapters/driven/sqlite.rb +9 -1
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +1 -1
- data/lib/hecks/adapters/driven/worktree_overlay.rb +117 -0
- data/lib/hecks/adapters/driving/cli/shorthand.rb +5 -1
- data/lib/hecks/adapters/driving/cli.rb +1 -1
- data/lib/hecks/adapters/driving/cli_runner/answers.rb +77 -22
- data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +35 -0
- data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +36 -0
- data/lib/hecks/adapters/driving/cli_runner/json_words.rb +55 -0
- data/lib/hecks/adapters/driving/cli_runner/name_index.rb +63 -0
- data/lib/hecks/adapters/driving/cli_runner/read_context.rb +32 -0
- data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +49 -0
- data/lib/hecks/adapters/driving/cli_runner/resolution.rb +43 -17
- data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +63 -0
- data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +66 -0
- data/lib/hecks/adapters/driving/cli_runner/run_replay.rb +118 -0
- data/lib/hecks/adapters/driving/cli_runner/search_words.rb +35 -0
- data/lib/hecks/adapters/driving/cli_runner/settling.rb +6 -5
- data/lib/hecks/adapters/driving/cli_runner/streaming.rb +11 -10
- data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +1 -1
- data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +77 -0
- data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +36 -4
- data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +75 -0
- data/lib/hecks/adapters/driving/cli_runner.rb +106 -7
- data/lib/hecks/adapters/driving/context_line.rb +85 -0
- data/lib/hecks/adapters/driving/exit_status.rb +31 -0
- data/lib/hecks/adapters/driving/launcher_options.rb +7 -5
- data/lib/hecks/adapters/driving/mcp/progress_sink.rb +45 -0
- data/lib/hecks/adapters/driving/mcp/tool_calls.rb +7 -5
- data/lib/hecks/adapters/driving/mcp.rb +25 -5
- data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +40 -7
- data/lib/hecks/adapters/driving/mcp_scope.rb +8 -7
- data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +154 -0
- data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +64 -93
- data/lib/hecks/adapters/driving/usage_log.rb +146 -0
- data/lib/hecks/adapters/driving/write_guard.rb +55 -0
- data/lib/hecks/adapters/driving.rb +0 -1
- data/lib/hecks/behaviors/dsl.rb +5 -1
- data/lib/hecks/behaviors/expectations/boot.rb +0 -1
- data/lib/hecks/bluebook/acknowledgements.rb +1 -1
- data/lib/hecks/bluebook/aggregate.rb +21 -18
- data/lib/hecks/bluebook/assembly/contracts/sagas.rb +2 -0
- data/lib/hecks/bluebook/assembly/contracts/structure.rb +18 -13
- data/lib/hecks/bluebook/behaviour/aggregate.rb +27 -3
- data/lib/hecks/bluebook/command.rb +16 -5
- data/lib/hecks/bluebook/declaration.rb +32 -4
- data/lib/hecks/bluebook/domain_port.rb +7 -3
- data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +0 -2
- data/lib/hecks/bluebook/dsl/aggregate_builder/renaming.rb +25 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +3 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +0 -1
- data/lib/hecks/bluebook/dsl/audience_word.rb +40 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +56 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +80 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +51 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +1 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +17 -34
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +8 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +13 -3
- data/lib/hecks/bluebook/dsl/entity_builder.rb +0 -2
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +6 -4
- data/lib/hecks/bluebook/dsl/kinds.rb +53 -0
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +9 -2
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +25 -15
- data/lib/hecks/bluebook/dsl/translation_builder.rb +16 -1
- data/lib/hecks/bluebook/dsl/word_gate.rb +1 -1
- data/lib/hecks/bluebook/dsl.rb +1 -0
- data/lib/hecks/bluebook/meta_validator/judge/identity.rb +9 -4
- data/lib/hecks/bluebook/meta_validator/plan/category.rb +10 -2
- data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +9 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +2 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +3 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +7 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +7 -2
- data/lib/hecks/bluebook/meta_validator/shapes.rb +3 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +1 -1
- data/lib/hecks/bluebook/model_check/aggregate_checks.rb +27 -0
- data/lib/hecks/bluebook/model_check/ask_checks.rb +25 -0
- data/lib/hecks/bluebook/model_check/reaction_chains.rb +114 -0
- data/lib/hecks/bluebook/model_check/reaction_cycles.rb +53 -0
- data/lib/hecks/bluebook/model_check/reaction_depth_checks.rb +58 -0
- data/lib/hecks/bluebook/model_check/reaction_walk.rb +62 -0
- data/lib/hecks/bluebook/model_check.rb +5 -27
- data/lib/hecks/bluebook/process_manager.rb +20 -3
- data/lib/hecks/bluebook/translation.rb +5 -3
- data/lib/hecks/bluebook/translation_plan.rb +9 -2
- data/lib/hecks/ci_pipeline/adapters/ci_cache.adapter +7 -0
- data/lib/hecks/ci_pipeline/adapters/ci_cache.rb +39 -0
- data/lib/hecks/ci_pipeline/adapters/ci_runner.adapter +7 -0
- data/lib/hecks/ci_pipeline/adapters/ci_runner.rb +55 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.behaviors +322 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.bluebook +938 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.hecksagon +12 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.ports.hecksagon +16 -0
- data/lib/hecks/ci_speed/adapters/ci_reader.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/ci_reader.rb +141 -0
- data/lib/hecks/ci_speed/adapters/local_runner/answer.rb +41 -0
- data/lib/hecks/ci_speed/adapters/local_runner/catalog.rb +89 -0
- data/lib/hecks/ci_speed/adapters/local_runner/checkouts.rb +89 -0
- data/lib/hecks/ci_speed/adapters/local_runner/launcher.rb +69 -0
- data/lib/hecks/ci_speed/adapters/local_runner/load_average.rb +38 -0
- data/lib/hecks/ci_speed/adapters/local_runner/refs.rb +39 -0
- data/lib/hecks/ci_speed/adapters/local_runner/refused.rb +11 -0
- data/lib/hecks/ci_speed/adapters/local_runner/verdict.rb +71 -0
- data/lib/hecks/ci_speed/adapters/local_runner.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/local_runner.rb +168 -0
- data/lib/hecks/ci_speed/adapters/replayed_runner.rb +39 -0
- data/lib/hecks/ci_speed/ci_speed.behaviors +341 -0
- data/lib/hecks/ci_speed/ci_speed.bluebook +1073 -0
- data/lib/hecks/ci_speed/ci_speed.hecksagon +11 -0
- data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +21 -0
- data/lib/hecks/ci_workflows/ci_workflows.behaviors +13 -0
- data/lib/hecks/ci_workflows/ci_workflows.bluebook +173 -0
- data/lib/hecks/ci_workflows/ci_workflows.hecksagon +15 -0
- data/lib/hecks/coder/coder.bluebook +385 -0
- data/lib/hecks/coder/coder.hecksagon +12 -0
- data/lib/hecks/command_names/check.rb +39 -0
- data/lib/hecks/command_names/extractor.rb +67 -0
- data/lib/hecks/command_names/index.rb +40 -0
- data/lib/hecks/command_names/resolution.rb +81 -0
- data/lib/hecks/command_names/scan.rb +54 -0
- data/lib/hecks/command_names/sources.rb +73 -0
- data/lib/hecks/command_names.rb +26 -0
- data/lib/hecks/composer/jobs.rb +1 -1
- data/lib/hecks/composer/toolbox.rb +8 -1
- data/lib/hecks/corpus/generated_key.rb +205 -0
- data/lib/hecks/corpus/listing.rb +34 -0
- data/lib/hecks/corpus/rust.rb +27 -11
- data/lib/hecks/corpus/sources.rb +2 -1
- data/lib/hecks/corpus.rb +37 -42
- data/lib/hecks/deprecation.rb +23 -0
- data/lib/hecks/doc/reference/readme.rb +1 -1
- data/lib/hecks/doc/reference/rendering.rb +2 -2
- data/lib/hecks/doc/reference.rb +1 -1
- data/lib/hecks/embryonaut_bluebook/manifest.rb +1 -1
- data/lib/hecks/fixer/fixer.bluebook +240 -0
- data/lib/hecks/fixer/fixer.hecksagon +17 -0
- data/lib/hecks/framework_bluebooks.rb +32 -7
- data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +1 -0
- data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +11 -12
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +23 -5
- data/lib/hecks/fuzzing/isolated_boot.rb +1 -1
- data/lib/hecks/fuzzing/mutation/checks.rb +3 -3
- data/lib/hecks/grammar/translation.bluebook +1 -1
- data/lib/hecks/grammar/translation_rules.json +64 -0
- data/lib/hecks/hecks/adapter_words.json +7 -0
- data/lib/hecks/hecks/adapters/area_overlap.rb +156 -0
- data/lib/hecks/hecks/adapters/claude_agents.rb +8 -3
- data/lib/hecks/hecks/adapters/codebase/batch_runs.rb +60 -0
- data/lib/hecks/hecks/adapters/codebase/changed_specs.rb +52 -0
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +3 -2
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +14 -1
- data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +53 -0
- data/lib/hecks/hecks/adapters/codebase/generated_keys.rb +31 -0
- data/lib/hecks/hecks/adapters/codebase/impacted_specs.rb +110 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +2 -2
- data/lib/hecks/hecks/adapters/codebase/launcher_text.rb +39 -0
- data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +52 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +51 -8
- data/lib/hecks/hecks/adapters/codebase/run_options.rb +35 -0
- data/lib/hecks/hecks/adapters/codebase/scripting.rb +39 -0
- data/lib/hecks/hecks/adapters/codebase/search.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +79 -51
- data/lib/hecks/hecks/adapters/codebase/spec_files/report.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/spec_files/shared_run.rb +73 -0
- data/lib/hecks/hecks/adapters/codebase/spec_files.rb +95 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +53 -4
- data/lib/hecks/hecks/adapters/codebase/test_scope.rb +105 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +48 -34
- data/lib/hecks/hecks/adapters/console_capture.rb +1 -1
- data/lib/hecks/hecks/adapters/cost_explorer.rb +9 -1
- data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +51 -0
- data/lib/hecks/hecks/adapters/dispatching/launcher.rb +97 -0
- data/lib/hecks/hecks/adapters/dispatching/plan.rb +82 -0
- data/lib/hecks/hecks/adapters/dispatching/rows.rb +66 -0
- data/lib/hecks/hecks/adapters/dispatching/settings.rb +81 -0
- data/lib/hecks/hecks/adapters/dispatching/settler.rb +40 -0
- data/lib/hecks/hecks/adapters/dispatching.adapter +7 -0
- data/lib/hecks/hecks/adapters/dispatching.rb +93 -0
- data/lib/hecks/hecks/adapters/doctor_reading/report.rb +27 -0
- data/lib/hecks/hecks/adapters/doctor_reading.adapter +7 -0
- data/lib/hecks/hecks/adapters/doctor_reading.rb +161 -0
- data/lib/hecks/hecks/adapters/git_checkout.rb +1 -1
- data/lib/hecks/hecks/adapters/git_commit.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_commit.rb +61 -0
- data/lib/hecks/hecks/adapters/git_landing/finisher.rb +82 -0
- data/lib/hecks/hecks/adapters/git_landing/foreign_hold.rb +111 -0
- data/lib/hecks/hecks/adapters/git_landing/line.rb +171 -0
- data/lib/hecks/hecks/adapters/git_landing/lineup.rb +98 -0
- data/lib/hecks/hecks/adapters/git_landing/merger.rb +1 -1
- data/lib/hecks/hecks/adapters/git_landing/numbering.rb +54 -0
- data/lib/hecks/hecks/adapters/git_landing/rivals.rb +59 -0
- data/lib/hecks/hecks/adapters/git_landing/ticket.rb +156 -0
- data/lib/hecks/hecks/adapters/git_landing/tidy.rb +147 -0
- data/lib/hecks/hecks/adapters/git_landing/train.rb +104 -0
- data/lib/hecks/hecks/adapters/git_landing/verdict.rb +64 -0
- data/lib/hecks/hecks/adapters/git_landing/waiting.rb +120 -0
- data/lib/hecks/hecks/adapters/git_landing.rb +106 -20
- data/lib/hecks/hecks/adapters/git_main_pull.rb +99 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/bench.rb +82 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/due.rb +84 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted/skips.rb +47 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted/spec_run.rb +75 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted.rb +181 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/line.rb +76 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/reading.rb +24 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/record.rb +146 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/corpus.rb +25 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/needles.rb +61 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map.rb +105 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/stages.rb +118 -0
- data/lib/hecks/hecks/adapters/git_rehearsal.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_rehearsal.rb +141 -0
- data/lib/hecks/hecks/adapters/git_train/bench.rb +15 -15
- data/lib/hecks/hecks/adapters/git_train/branch_guard.rb +62 -0
- data/lib/hecks/hecks/adapters/git_train/carriage.rb +27 -28
- data/lib/hecks/hecks/adapters/git_train/launcher_shape.rb +75 -0
- data/lib/hecks/hecks/adapters/git_train/mint_step.rb +47 -0
- data/lib/hecks/hecks/adapters/git_train/settlement.rb +167 -0
- data/lib/hecks/hecks/adapters/git_train.rb +73 -15
- data/lib/hecks/hecks/adapters/git_worktree_add.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_worktree_add.rb +68 -0
- data/lib/hecks/hecks/adapters/github_pull_requests.adapter +7 -0
- data/lib/hecks/hecks/adapters/github_pull_requests.rb +109 -0
- data/lib/hecks/hecks/adapters/host_http.rb +6 -6
- data/lib/hecks/hecks/adapters/in_process_boot.rb +10 -8
- data/lib/hecks/hecks/adapters/in_process_operations.rb +11 -17
- data/lib/hecks/hecks/adapters/in_process_undo.rb +17 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +13 -4
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +28 -15
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +17 -1
- data/lib/hecks/hecks/adapters/journal_store/held_domain/renaming.rb +45 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +31 -5
- data/lib/hecks/hecks/adapters/journal_store/held_mint.rb +128 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +1 -1
- data/lib/hecks/hecks/adapters/journal_store/readings/boot_status.rb +58 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/outcomes.rb +76 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/postgres_reader.rb +44 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/reader.rb +64 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/report.rb +102 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/sqlite_reader.rb +43 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/stores.rb +80 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/subscribers.rb +72 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/summary.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/command_line.rb +57 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/edge_guards.rb +107 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/inspection.rb +94 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/plan.rb +66 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/report.rb +72 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/store.rb +34 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/watermark_guards.rb +86 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/world.rb +66 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan.rb +36 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/projection_audit.rb +64 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +3 -3
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/database_reading.rb +113 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/read_only.rb +33 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status.rb +32 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +13 -1
- data/lib/hecks/hecks/adapters/journal_store/reconcile_report.rb +60 -0
- data/lib/hecks/hecks/adapters/journal_store/reconciliation.rb +121 -0
- data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +59 -0
- data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +123 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +16 -0
- data/lib/hecks/hecks/adapters/landed_work.adapter +7 -0
- data/lib/hecks/hecks/adapters/landed_work.rb +52 -0
- data/lib/hecks/hecks/adapters/local_files.rb +6 -6
- data/lib/hecks/hecks/adapters/process_pool.rb +3 -2
- data/lib/hecks/hecks/adapters/push_size.rb +57 -0
- data/lib/hecks/hecks/adapters/qa_quiescing.adapter +7 -0
- data/lib/hecks/hecks/adapters/qa_quiescing.rb +57 -0
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +30 -3
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +63 -3
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +29 -6
- data/lib/hecks/hecks/adapters/rehearsal/subject.rb +11 -5
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +10 -1
- data/lib/hecks/hecks/adapters/rust_workspace.rb +1 -1
- data/lib/hecks/hecks/adapters/settings_reading/disposable_ledger.rb +32 -0
- data/lib/hecks/hecks/adapters/settings_reading/push_nudge.rb +26 -0
- data/lib/hecks/hecks/adapters/settings_reading/stores.rb +76 -0
- data/lib/hecks/hecks/adapters/settings_reading/test_scope.rb +28 -0
- data/lib/hecks/hecks/adapters/settings_reading.rb +28 -2
- data/lib/hecks/hecks/adapters/started_work.rb +42 -0
- data/lib/hecks/hecks/adapters/terminal.rb +12 -10
- data/lib/hecks/hecks/adapters/where_reading.adapter +7 -0
- data/lib/hecks/hecks/adapters/where_reading.rb +64 -0
- data/lib/hecks/hecks/adapters/work_areas.rb +57 -0
- data/lib/hecks/hecks/adapters/work_limits.rb +57 -0
- data/lib/hecks/hecks/build/build.bluebook +576 -0
- data/lib/hecks/hecks/check/check.bluebook +966 -0
- data/lib/hecks/hecks/codebase.behaviors +61 -5
- data/lib/hecks/hecks/composer.behaviors +1 -1
- data/lib/hecks/hecks/context_map.hecksagon +1 -1
- data/lib/hecks/hecks/custodian.behaviors +33 -7
- data/lib/hecks/hecks/delegate/delegate.bluebook +355 -0
- data/lib/hecks/hecks/deliver/deliver.bluebook +945 -0
- data/lib/hecks/hecks/deploy.behaviors +1 -1
- data/lib/hecks/hecks/evolve/evolve.bluebook +788 -0
- data/lib/hecks/hecks/find/find.bluebook +81 -0
- data/lib/hecks/hecks/hecks.behaviors +1 -1
- data/lib/hecks/hecks/hecks.bluebook +0 -133
- data/lib/hecks/hecks/hecks.contextmap +2 -0
- data/lib/hecks/hecks/hecks.hecksagon +185 -29
- data/lib/hecks/hecks/hecks.world +35 -9
- data/lib/hecks/hecks/implicit_moves.json +24 -0
- data/lib/hecks/hecks/migrate/migrate.bluebook +1066 -0
- data/lib/hecks/hecks/operate/operate.bluebook +695 -0
- data/lib/hecks/hecks/quiesce/quiesce.bluebook +117 -0
- data/lib/hecks/hecks/rehearse/rehearse.bluebook +133 -0
- data/lib/hecks/hecks/release/release.bluebook +916 -0
- data/lib/hecks/hecks/serve/serve.bluebook +134 -0
- data/lib/hecks/hecks/shapes.json +1 -15
- data/lib/hecks/hecks/site.behaviors +1 -1
- data/lib/hecks/hecks/start/start.bluebook +194 -0
- data/lib/hecks/hecks/test/test.bluebook +638 -0
- data/lib/hecks/hecks/tickets.world +14 -0
- data/lib/hecks/language/bluebook/aggregate.bluebook +22 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +34 -0
- data/lib/hecks/language/bluebook/command.bluebook +35 -0
- data/lib/hecks/language/bluebook/process_manager.bluebook +14 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +174 -54
- data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -0
- data/lib/hecks/language/hecksagon/port_operation.bluebook +14 -0
- data/lib/hecks/language/kinds/run.kind +120 -0
- data/lib/hecks/language/oidc.json +10 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +24 -0
- data/lib/hecks/module_folders.rb +31 -0
- data/lib/hecks/ports/key_vault.rb +1 -1
- data/lib/hecks/ports/persistence/append_only.rb +26 -8
- data/lib/hecks/ports/persistence/binding_policy.rb +3 -1
- data/lib/hecks/ports/persistence/codec_boundary.rb +1 -1
- data/lib/hecks/ports/persistence/mint_door.rb +74 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +6 -5
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +5 -1
- data/lib/hecks/ports/persistence/plugins/era/era_status.rb +48 -0
- data/lib/hecks/ports/persistence/plugins/era/projected_bluebook.rb +127 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/additive_shape.rb +107 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +155 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/compose_render.rb +79 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/edge_files.rb +49 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/edge_route.rb +61 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/implicit_edge.rb +67 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/reconcile.rb +130 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/reconcile_files.rb +35 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +13 -5
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +5 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +1 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +11 -3
- data/lib/hecks/ports/persistence/stored_name_guard.rb +36 -0
- data/lib/hecks/ports/persistence.rb +2 -0
- data/lib/hecks/projections/ci_pipeline/table/checks.rb +137 -0
- data/lib/hecks/projections/ci_pipeline/table/lookup.rb +59 -0
- data/lib/hecks/projections/ci_pipeline/table/refusals.rb +58 -0
- data/lib/hecks/projections/ci_pipeline/table/rows.rb +119 -0
- data/lib/hecks/projections/ci_pipeline/table/tree.rb +30 -0
- data/lib/hecks/projections/ci_pipeline/table/typing.rb +92 -0
- data/lib/hecks/projections/ci_pipeline/table.rb +112 -0
- data/lib/hecks/projections/ci_pipeline/workflows.rb +162 -0
- data/lib/hecks/projections/ci_pipeline/yaml_text.rb +104 -0
- data/lib/hecks/projections/deploy/box/hosting.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_scripts.rb +1 -1
- data/lib/hecks/projections/deploy/box.rb +1 -1
- data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +1 -1
- data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +3 -3
- data/lib/hecks/projections/undo.rb +46 -0
- data/lib/hecks/projections.rb +2 -0
- data/lib/hecks/projector/cli_projector/claims.rb +11 -0
- data/lib/hecks/projector/cli_projector/command_help.rb +6 -1
- data/lib/hecks/projector/cli_projector/command_specs.rb +11 -1
- data/lib/hecks/projector/cli_projector/completion.rb +87 -0
- data/lib/hecks/projector/cli_projector/everyday.rb +40 -0
- data/lib/hecks/projector/cli_projector/json_listing.rb +77 -0
- data/lib/hecks/projector/cli_projector/listing.rb +1 -1
- data/lib/hecks/projector/cli_projector/modules.rb +39 -0
- data/lib/hecks/projector/cli_projector/query_specs.rb +1 -0
- data/lib/hecks/projector/cli_projector/renames.rb +58 -0
- data/lib/hecks/projector/cli_projector/search.rb +74 -0
- data/lib/hecks/projector/cli_projector/usage.rb +23 -6
- data/lib/hecks/projector/cli_projector.rb +24 -1
- data/lib/hecks/quality_control/adapters/ci_head.adapter +8 -0
- data/lib/hecks/quality_control/adapters/image_roll.adapter +9 -0
- data/lib/hecks/quality_control/adapters/image_roll.rb +158 -0
- data/lib/hecks/quality_control/adapters/main_maintenance.adapter +8 -0
- data/lib/hecks/quality_control/adapters/main_maintenance.rb +275 -0
- data/lib/hecks/quality_control/adapters/pump_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/pump_tools.rb +18 -0
- data/lib/hecks/quality_control/adapters/push_due_reader.adapter +8 -0
- data/lib/hecks/quality_control/adapters/push_due_reader.rb +99 -0
- data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +183 -0
- data/lib/hecks/quality_control/adapters/qa_era_mint.rb +94 -0
- data/lib/hecks/quality_control/adapters/qa_quiesce_marker.rb +126 -0
- data/lib/hecks/quality_control/adapters/run_keys.rb +36 -0
- data/lib/hecks/quality_control/adapters/run_reader.adapter +7 -0
- data/lib/hecks/quality_control/adapters/run_reader.rb +188 -0
- data/lib/hecks/quality_control/cli/child.rb +1 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_event_pump/attached.rb +67 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/consumer.rb +103 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/cursors.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/reactions.rb +46 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/reader.rb +30 -0
- data/lib/hecks/quality_control/cli/qa_event_pump.rb +76 -0
- data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +79 -0
- data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +167 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +52 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +47 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +59 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +62 -0
- data/lib/hecks/quality_control/cli/qa_main_gate.rb +135 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +2 -3
- data/lib/hecks/quality_control/cli/qa_push_nudge.rb +48 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_tick/event_pump_step.rb +34 -0
- data/lib/hecks/quality_control/cli/qa_tick/output.rb +16 -1
- data/lib/hecks/quality_control/cli/qa_tick/push_nudge_step.rb +28 -0
- data/lib/hecks/quality_control/cli/qa_tick/quiesce_guard.rb +51 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +36 -8
- data/lib/hecks/quality_control/quality_control.behaviors +65 -0
- data/lib/hecks/quality_control/quality_control.bluebook +1131 -11
- data/lib/hecks/quality_control/quality_control.hecksagon +11 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +138 -0
- data/lib/hecks/query_ir/touchpoints.rb +5 -7
- data/lib/hecks/refused.rb +21 -0
- data/lib/hecks/release/approval.rb +6 -3
- data/lib/hecks/release/conditions.rb +46 -0
- data/lib/hecks/release/runner/gem_publisher.rb +4 -4
- data/lib/hecks/release/version_commit.rb +48 -0
- data/lib/hecks/runtime/command_interpreter/hydration.rb +5 -4
- data/lib/hecks/runtime/command_interpreter/persisting.rb +11 -3
- data/lib/hecks/runtime/command_interpreter.rb +2 -2
- data/lib/hecks/runtime/command_rules/admissibility.rb +0 -2
- data/lib/hecks/runtime/command_rules/emission.rb +0 -1
- data/lib/hecks/runtime/dependency_planning/expression_reads.rb +0 -1
- data/lib/hecks/runtime/dispatcher/planning.rb +24 -0
- data/lib/hecks/runtime/dispatcher/routing.rb +6 -0
- data/lib/hecks/runtime/dispatcher/value_routing.rb +54 -0
- data/lib/hecks/runtime/dispatcher.rb +7 -1
- data/lib/hecks/runtime/dry_run_plan.rb +60 -0
- data/lib/hecks/runtime/entity_element/location.rb +0 -1
- data/lib/hecks/runtime/entity_element/mutations.rb +0 -1
- data/lib/hecks/runtime/entity_interpreter/locating.rb +5 -0
- data/lib/hecks/runtime/entity_interpreter.rb +0 -1
- data/lib/hecks/runtime/errors.rb +26 -0
- data/lib/hecks/runtime/instance.rb +0 -1
- data/lib/hecks/runtime/invocation_builder.rb +0 -1
- data/lib/hecks/runtime/outbox/consumer_runner.rb +9 -1
- data/lib/hecks/runtime/outbox/relay.rb +25 -4
- data/lib/hecks/runtime/outbox/runnable.rb +3 -1
- data/lib/hecks/runtime/outbox.rb +6 -2
- data/lib/hecks/runtime/policy_interpreter/fan_out.rb +18 -2
- data/lib/hecks/runtime/policy_interpreter.rb +17 -9
- data/lib/hecks/runtime/port_operation_interpreter.rb +21 -7
- data/lib/hecks/runtime/query_interpreter/arguments.rb +6 -5
- data/lib/hecks/runtime/reaction_invocation.rb +0 -1
- data/lib/hecks/runtime/refusal_wording.rb +12 -1
- data/lib/hecks/runtime/registry/context_maps.rb +1 -5
- data/lib/hecks/runtime/registry/declarations.rb +34 -4
- data/lib/hecks/runtime/registry/hecksagon_rules.rb +15 -1
- data/lib/hecks/runtime/registry/runtime_state.rb +10 -0
- data/lib/hecks/runtime/registry/world_defaults.rb +24 -2
- data/lib/hecks/runtime/registry/world_names.rb +99 -0
- data/lib/hecks/runtime/registry.rb +33 -27
- data/lib/hecks/runtime/saga_interpreter/compensation.rb +10 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +29 -3
- data/lib/hecks/runtime/saga_interpreter/delivery.rb +0 -1
- data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +1 -1
- data/lib/hecks/runtime/saga_interpreter.rb +46 -2
- data/lib/hecks/runtime/value/coercion.rb +36 -8
- data/lib/hecks/rust_build/conformance.rb +16 -5
- data/lib/hecks/rust_build/parser.rb +25 -0
- data/lib/hecks/rust_build/project_rust/codegen_run.rb +45 -12
- data/lib/hecks/rust_build/project_rust/declared.rb +80 -0
- data/lib/hecks/rust_build/project_rust/features_header.rb +22 -0
- data/lib/hecks/rust_build/project_rust/manifest.rb +96 -0
- data/lib/hecks/rust_build/project_rust/meta.rb +36 -0
- data/lib/hecks/rust_build/project_rust.rb +28 -90
- data/lib/hecks/rust_build/write_if_changed.rb +19 -4
- data/lib/hecks/rust_build.rb +2 -1
- data/lib/hecks/rust_format.rb +32 -2
- data/lib/hecks/secrets.rb +111 -0
- data/lib/hecks/shape_ledger/edge_hygiene.rb +170 -0
- data/lib/hecks/shape_ledger/scope.rb +51 -0
- data/lib/hecks/shape_ledger/status.rb +89 -0
- data/lib/hecks/shape_ledger.rb +78 -33
- data/lib/hecks/site/bluebook/site.bluebook +1 -0
- data/lib/hecks/storehouse/audit.rb +34 -4
- data/lib/hecks/storehouse/callers.rb +8 -0
- data/lib/hecks/storehouse/dispatching.rb +14 -3
- data/lib/hecks/storehouse/identity.rb +41 -0
- data/lib/hecks/storehouse/querying.rb +7 -7
- data/lib/hecks/storehouse.rb +28 -10
- data/lib/hecks/tickets/bluebook/adapters/work_areas.adapter +7 -0
- data/lib/hecks/tickets/bluebook/adapters/work_limits.adapter +7 -0
- data/lib/hecks/tickets/bluebook/tickets.behaviors +70 -0
- data/lib/hecks/tickets/bluebook/tickets.bluebook +323 -28
- data/lib/hecks/tickets/bluebook/tickets.hecksagon +7 -0
- data/lib/hecks/tickets/bluebook/tickets.ports.hecksagon +17 -0
- data/lib/hecks/{cli → tools}/behaviors.rb +1 -1
- data/lib/hecks/{cli → tools}/canonicalise.rb +1 -1
- data/lib/hecks/{cli → tools}/check_engine_agreement.rb +1 -1
- data/lib/hecks/{cli → tools}/check_era.rb +6 -6
- data/lib/hecks/tools/ci_gates.rb +8 -2
- data/lib/hecks/tools/ci_workflows.rb +98 -0
- data/lib/hecks/{cli → tools}/console.rb +1 -1
- data/lib/hecks/{cli → tools}/deploy_template_diff.rb +1 -1
- data/lib/hecks/{cli → tools}/doc_coverage.rb +2 -2
- data/lib/hecks/{cli → tools}/document.rb +1 -1
- data/lib/hecks/{cli → tools}/domain_stub.rb +1 -1
- data/lib/hecks/{cli → tools}/domain_writer.rb +1 -1
- data/lib/hecks/tools/downstream_model_check.rb +122 -0
- data/lib/hecks/tools/evolve_run.rb +2 -2
- data/lib/hecks/{cli → tools}/expected_era.rb +1 -1
- data/lib/hecks/{cli → tools}/expression_projection.rb +1 -1
- data/lib/hecks/{cli → tools}/follow.rb +1 -1
- data/lib/hecks/tools/fuzz_sweep/options.rb +40 -5
- data/lib/hecks/tools/fuzz_sweep/pool.rb +12 -1
- data/lib/hecks/tools/fuzz_sweep/shards.rb +155 -0
- data/lib/hecks/tools/fuzz_sweep.rb +11 -5
- data/lib/hecks/tools/gate.rb +38 -29
- data/lib/hecks/tools/gate_memo/local_files.rb +33 -0
- data/lib/hecks/tools/gate_memo/rehearsal.rb +54 -0
- data/lib/hecks/tools/gate_memo/ruby_files.rb +152 -0
- data/lib/hecks/tools/gate_memo/session.rb +114 -0
- data/lib/hecks/tools/gate_memo/standalone.rb +67 -0
- data/lib/hecks/tools/gate_memo.rb +196 -0
- data/lib/hecks/tools/gate_report.rb +56 -0
- data/lib/hecks/{cli → tools}/history.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_agent.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_aggregate.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_draft.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_record.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_run.rb +2 -2
- data/lib/hecks/{cli → tools}/interview_session/agent_state.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/catalog.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/manual_findings.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/proposals.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session.rb +2 -2
- data/lib/hecks/{cli → tools}/interview_shape/lifecycle.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_shape.rb +1 -1
- data/lib/hecks/{cli → tools}/ir.rb +1 -1
- data/lib/hecks/tools/lanes/files.rb +1 -1
- data/lib/hecks/tools/lanes/watch_workflow.rb +6 -8
- data/lib/hecks/tools/lanes/workflow.rb +1 -1
- data/lib/hecks/tools/lanes.rb +1 -1
- data/lib/hecks/{cli → tools}/mcp.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check/examination.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check/sources.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check.rb +1 -1
- data/lib/hecks/tools/move_disables/reasons.rb +35 -0
- data/lib/hecks/tools/move_disables.rb +211 -0
- data/lib/hecks/tools/move_former_name.rb +105 -0
- data/lib/hecks/{cli → tools}/pattern_cases.rb +1 -1
- data/lib/hecks/{cli → tools}/persistence_notice.rb +1 -1
- data/lib/hecks/{cli → tools}/present.rb +1 -1
- data/lib/hecks/{cli → tools}/project_cli/launcher_source.rb +32 -22
- data/lib/hecks/{cli → tools}/project_cli/templates.rb +22 -15
- data/lib/hecks/{cli → tools}/project_cli.rb +11 -7
- data/lib/hecks/{cli → tools}/project_diagrams.rb +3 -3
- data/lib/hecks/{cli → tools}/project_glossary.rb +2 -2
- data/lib/hecks/{cli → tools}/reference.rb +2 -2
- data/lib/hecks/{cli → tools}/refresh_projections.rb +1 -1
- data/lib/hecks/{cli → tools}/refresh_rspec_runtime_baseline.rb +1 -1
- data/lib/hecks/tools/regeneration_run/pool.rb +148 -0
- data/lib/hecks/tools/regeneration_run/scratch.rb +76 -0
- data/lib/hecks/tools/regeneration_run.rb +125 -103
- data/lib/hecks/{cli → tools}/release.rb +1 -1
- data/lib/hecks/{cli → tools}/release_gem.rb +1 -1
- data/lib/hecks/{cli → tools}/rspec_io_parallel_files.rb +1 -1
- data/lib/hecks/{cli → tools}/rspec_shard_files.rb +1 -1
- data/lib/hecks/{cli → tools}/run.rb +9 -2
- data/lib/hecks/{cli → tools}/run_expectations.rb +1 -1
- data/lib/hecks/{cli → tools}/seed_semantics_corpus.rb +4 -4
- data/lib/hecks/{cli → tools}/serve_query_ir_mcp.rb +1 -1
- data/lib/hecks/{cli → tools}/shape.rb +3 -2
- data/lib/hecks/{cli → tools}/smoke_http/checks.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http/settings.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http/transport.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_test.rb +1 -1
- data/lib/hecks/{cli → tools}/spec_example.rb +1 -1
- data/lib/hecks/tools/stage_progress.rb +54 -0
- data/lib/hecks/{cli → tools}/statements.rb +1 -1
- data/lib/hecks/{cli → tools}/stores.rb +1 -1
- data/lib/hecks/{cli → tools}/stress_concurrency_specs/reporting.rb +1 -1
- data/lib/hecks/{cli → tools}/stress_concurrency_specs/usage.rb +4 -4
- data/lib/hecks/{cli → tools}/stress_concurrency_specs.rb +3 -3
- data/lib/hecks/tools/tenant_provisioning.rb +23 -0
- data/lib/hecks/tools/tools_doc.rb +10 -8
- data/lib/hecks/tools/translation_audit/edges.rb +21 -16
- data/lib/hecks/tools/translation_audit/verdicts.rb +1 -1
- data/lib/hecks/tools/translation_audit.rb +1 -1
- data/lib/hecks/tools/translation_scaffold.rb +1 -1
- data/lib/hecks/tools.rb +4 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +61 -31
- data/lib/hecks/workflow_pagination/judge.rb +48 -0
- data/lib/hecks/workflow_pagination/statement.rb +50 -0
- data/lib/hecks/workflow_pagination.rb +58 -0
- data/lib/hecks.rb +2 -0
- data/lib/rubocop/cop/hecks/bare_event_and_query_names.rb +58 -0
- data/lib/rubocop/cop/hecks/correlates_by_aggregate.rb +39 -0
- data/lib/rubocop/cop/hecks/creating_command_sets.rb +75 -0
- data/lib/rubocop/cop/hecks/invariant_expression_language.rb +47 -0
- data/lib/rubocop/cop/hecks/lifecycle_needs_attribute.rb +58 -0
- data/lib/rubocop/cop/hecks/no_id_string_attribute.rb +49 -0
- data/lib/rubocop/cop/hecks/one_terminal_mark_per_lifecycle.rb +47 -0
- data/lib/rubocop/cop/hecks/value_object_shorthand.rb +56 -0
- data/prebuilt/13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal +0 -0
- data/prebuilt/e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal +0 -0
- data/qa/settings.yml +23 -0
- data/rust/.gitignore +0 -6
- data/rust/Cargo.toml +2 -1
- data/rust/build/Cargo.toml +1 -1
- data/rust/build/src/binding_pass.rs +57 -4
- data/rust/build/src/pipeline.rs +6 -4
- data/rust/build/src/resolve.rs +1 -0
- data/rust/codegen/Cargo.toml +1 -1
- data/rust/codegen/src/domain_generator.rs +3 -0
- data/rust/codegen/src/json_codec.rs +182 -23
- data/rust/codegen/src/one_of_references.rs +1 -0
- data/rust/codegen/src/queries.rs +20 -2
- data/rust/codegen/src/registry.rs +21 -5
- data/rust/expr/Cargo.toml +1 -1
- data/rust/host/Cargo.toml +1 -1
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/core/Cargo.toml +1 -1
- data/rust/host/src/bin/mint_harness.rs +1 -0
- data/rust/host/src/boot.rs +1 -0
- data/rust/host/src/store/mint.rs +40 -6
- data/rust/lsp/Cargo.toml +1 -1
- data/rust/parser/Cargo.toml +1 -1
- data/rust/parser/src/build/correlation_keys.rs +125 -0
- data/rust/parser/src/build/mod.rs +1 -0
- data/rust/parser/src/emit.rs +55 -3
- data/rust/parser/src/ir.rs +33 -1
- data/rust/parser/src/keywords.rs +289 -1
- data/rust/parser/src/main.rs +2 -0
- data/rust/parser/src/parse/aggregate.rs +10 -1
- data/rust/parser/src/parse/audience.rs +65 -0
- data/rust/parser/src/parse/command.rs +14 -0
- data/rust/parser/src/parse/declaration.rs +97 -0
- data/rust/parser/src/parse/domain_port.rs +6 -0
- data/rust/parser/src/parse/mod.rs +1 -0
- data/rust/parser/src/parse/process_manager.rs +17 -10
- data/rust/parser/src/parse/world.rs +12 -8
- data/rust/parser/src/render_ruby.rs +9 -0
- data/rust/parser/src/sentence/format.rs +3 -0
- data/rust/parser/src/sentence/process.rs +6 -2
- data/rust/src/exemplar/json.rs +17 -0
- data/rust/src/kernel/cli.rs +27 -3
- data/rust/src/kernel/dispatch.rs +4 -2
- data/rust/src/kernel/json.rs +62 -0
- data/rust/src/kernel/orchestrate.rs +28 -3
- data/rust/src/kernel/orchestrate_guard_tests.rs +12 -12
- data/rust/web/Cargo.toml +1 -1
- metadata +389 -96
- data/lib/hecks/cli/command_table.rb +0 -72
- data/lib/hecks/cli/launcher_words.rb +0 -168
- data/lib/hecks/cli.rb +0 -133
- data/lib/hecks/hecks/agents.bluebook +0 -246
- data/lib/hecks/hecks/codebase.bluebook +0 -3209
- data/lib/hecks/hecks/custodian.bluebook +0 -1300
- data/lib/hecks/hecks/ledger.bluebook +0 -190
- data/lib/hecks/hecks/rehearsal.bluebook +0 -437
- data/lib/hecks/hecks/tooling.bluebook +0 -1234
- data/lib/hecks/hecks/translations/2-148748.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-15a2e4.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-1b447c.bluebook +0 -5
- data/lib/hecks/hecks/translations/2-240474.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-44446d.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-46ca26.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-473eab.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-75cc28.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-781c07.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-84c18b.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-aa5fff.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-bfdb48.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-cd96d8.bluebook +0 -10
- data/lib/hecks/hecks/translations/2-d43f71.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-eea577.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-f53248.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-fbb677.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-ffdf12.bluebook +0 -6
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +0 -36
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +0 -56
- data/prebuilt/31cf81e12f16236ad26249be590cfea3799c9db67432e6a4ef54b801c355b6ae.marshal +0 -0
- data/prebuilt/68ecb2bd3abb1a221007db4f2b0375834c13aaccac8f2b99778e8517f11aa113.marshal +0 -0
- data/prebuilt/verdicts-0328c2403383837d780ad5ed81d1da351c56436b894cf9015b5d56b8f1f1bf10.json +0 -1
|
@@ -4,7 +4,7 @@ require_relative "../../hecks"
|
|
|
4
4
|
require_relative "../doc/reference"
|
|
5
5
|
|
|
6
6
|
module Hecks
|
|
7
|
-
module
|
|
7
|
+
module Tools
|
|
8
8
|
# The command behind `hecks measure_doc_coverage`: refuses unless every live word in
|
|
9
9
|
# `docs/implemented/reference/` has prose and a running example. It checks that an example
|
|
10
10
|
# exists; `spec/reference_doctest_spec.rb` checks that it passes. `ruby skip` fences and
|
|
@@ -24,7 +24,7 @@ module Hecks
|
|
|
24
24
|
return 0 if clean
|
|
25
25
|
|
|
26
26
|
err.puts "docs/implemented/reference/ is behind the language. " \
|
|
27
|
-
"Regenerate with hecks language_run.project_reference to see the words in place."
|
|
27
|
+
"Regenerate with hecks language_run.project_reference! to see the words in place."
|
|
28
28
|
1
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Tools
|
|
7
|
+
# The model check a domain repository runs in its CI, generated from Hecks' own definition of it:
|
|
8
|
+
# the client profile, over the domain's bluebooks, from the hecks the Gemfile pins.
|
|
9
|
+
#
|
|
10
|
+
# A downstream repository commits the file this writes (`.github/workflows/model-check.yml`) and
|
|
11
|
+
# never edits it; a change to the check is made here, and every repository regenerates from it.
|
|
12
|
+
#
|
|
13
|
+
# ruby lib/hecks/tools/downstream_model_check.rb <checkout> <domain-directory> [--check]
|
|
14
|
+
#
|
|
15
|
+
# With `--check` nothing is written: the tool answers 1 when the committed file differs.
|
|
16
|
+
module DownstreamModelCheck
|
|
17
|
+
# Where the workflow lives under the checkout.
|
|
18
|
+
FILE = ".github/workflows/model-check.yml"
|
|
19
|
+
|
|
20
|
+
# The hecks profile the check runs under (Hecks' client profile, which refuses what the
|
|
21
|
+
# client cannot answer for).
|
|
22
|
+
PROFILE = "client"
|
|
23
|
+
|
|
24
|
+
# The bluebook directory the check reads, relative to the domain directory.
|
|
25
|
+
DOMAINS = "bluebook"
|
|
26
|
+
|
|
27
|
+
# The Ruby the check runs on, matching the domain repositories' CI.
|
|
28
|
+
RUBY_VERSION = "3.3"
|
|
29
|
+
|
|
30
|
+
BANNER = "# Generated by hecks lib/hecks/tools/downstream_model_check.rb from Hecks' client-profile model " \
|
|
31
|
+
"check. Do not edit; change the generator in hecks."
|
|
32
|
+
|
|
33
|
+
module_function
|
|
34
|
+
|
|
35
|
+
# @param domain_directory [String] the directory the domain's Gemfile and bluebooks live in,
|
|
36
|
+
# relative to the checkout (`.` when they are at the root)
|
|
37
|
+
# @return [String] the workflow's text, ending in a newline
|
|
38
|
+
def workflow(domain_directory:)
|
|
39
|
+
<<~YAML
|
|
40
|
+
#{BANNER}
|
|
41
|
+
|
|
42
|
+
name: Model check
|
|
43
|
+
|
|
44
|
+
on:
|
|
45
|
+
pull_request:
|
|
46
|
+
push:
|
|
47
|
+
branches: [main]
|
|
48
|
+
workflow_dispatch: {}
|
|
49
|
+
|
|
50
|
+
permissions:
|
|
51
|
+
contents: read
|
|
52
|
+
|
|
53
|
+
jobs:
|
|
54
|
+
model-check:
|
|
55
|
+
runs-on: ubuntu-24.04
|
|
56
|
+
timeout-minutes: 15
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
|
|
59
|
+
|
|
60
|
+
- uses: ruby/setup-ruby@14594264cd68ce8a2345dd349bc3d138a4ef85c8 # v1
|
|
61
|
+
with:
|
|
62
|
+
ruby-version: "#{RUBY_VERSION}"
|
|
63
|
+
bundler-cache: false
|
|
64
|
+
|
|
65
|
+
# The generator ships inside the pinned hecks gem, so the file is checked against the
|
|
66
|
+
# same generator that a bump brings in: a hand edit, or a stale file after a bump, fails here.
|
|
67
|
+
- name: Generated workflow is current
|
|
68
|
+
working-directory: #{domain_directory}
|
|
69
|
+
run: |
|
|
70
|
+
bundle install --quiet --jobs 4
|
|
71
|
+
ruby "$(bundle info hecks --path)/lib/hecks/tools/downstream_model_check.rb" "$GITHUB_WORKSPACE" #{domain_directory} --check
|
|
72
|
+
|
|
73
|
+
- name: Model check (hecks #{PROFILE} profile)
|
|
74
|
+
working-directory: #{domain_directory}
|
|
75
|
+
env:
|
|
76
|
+
HECKS_ENVIRONMENT: memory
|
|
77
|
+
run: |
|
|
78
|
+
bundle install --quiet --jobs 4
|
|
79
|
+
bundle exec hecks model_check_run.model_check! profile=#{PROFILE} domains=#{DOMAINS} --wait
|
|
80
|
+
YAML
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Writes the workflow under `root`, or with `check` compares it and reports whether it is current.
|
|
84
|
+
#
|
|
85
|
+
# @param root [String] the checkout
|
|
86
|
+
# @param domain_directory [String] see {workflow}
|
|
87
|
+
# @param check [Boolean] compare without writing
|
|
88
|
+
# @return [Integer] 0 when written or current, 1 when `check` finds the file out of date
|
|
89
|
+
def main(root:, domain_directory:, check: false)
|
|
90
|
+
path = File.join(root, FILE)
|
|
91
|
+
text = workflow(domain_directory: domain_directory)
|
|
92
|
+
current = File.file?(path) && File.read(path) == text
|
|
93
|
+
return check_report(current, path) if check
|
|
94
|
+
return puts("#{FILE}: already current") && 0 if current
|
|
95
|
+
|
|
96
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
97
|
+
File.write(path, text)
|
|
98
|
+
puts "wrote #{FILE}"
|
|
99
|
+
0
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @return [Integer] 0 when the file is current, else 1 with the reason on stderr
|
|
103
|
+
def check_report(current, path)
|
|
104
|
+
if current
|
|
105
|
+
puts "#{FILE}: current"
|
|
106
|
+
return 0
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
warn "#{FILE}: out of date at #{path} (regenerate with downstream_model_check.rb)"
|
|
110
|
+
1
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
if $PROGRAM_NAME == __FILE__
|
|
117
|
+
root, domain_directory, flag = ARGV
|
|
118
|
+
abort "usage: downstream_model_check.rb <checkout> <domain-directory> [--check]" unless root && domain_directory
|
|
119
|
+
|
|
120
|
+
exit Hecks::Tools::DownstreamModelCheck.main(root: root, domain_directory: domain_directory,
|
|
121
|
+
check: flag == "--check")
|
|
122
|
+
end
|
|
@@ -103,7 +103,7 @@ module Hecks
|
|
|
103
103
|
|
|
104
104
|
# @return [Boolean] true if the block ran and the gates held; false after restoring the
|
|
105
105
|
# snapshots when a gate refused
|
|
106
|
-
def edit_and_gate(word, context, evolve, root, &)
|
|
106
|
+
def edit_and_gate(word, context, evolve, root, &)
|
|
107
107
|
paths = evolve.syntax_paths + [File.join(root, "spec/golden/ir/Bluebook.json")]
|
|
108
108
|
snapshots = paths.to_h { |path| [path, File.read(path)] }
|
|
109
109
|
evolve.restore_on_raise(paths, &)
|
|
@@ -124,7 +124,7 @@ module Hecks
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
# @return [true]
|
|
127
|
-
def status(evolve)
|
|
127
|
+
def status(evolve)
|
|
128
128
|
rows = evolve.keyword_rows
|
|
129
129
|
moving = rows.reject { |row| row[:status] == "admitted" }
|
|
130
130
|
renamed = rows.reject { |row| row[:was].to_s.empty? }
|
|
@@ -3,7 +3,7 @@ require "net/http"
|
|
|
3
3
|
require "uri"
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
|
-
module
|
|
6
|
+
module Tools
|
|
7
7
|
# Compares a running host's reported era (`GET /version`) against an
|
|
8
8
|
# allow-list file of eras that should be running, for use after a roll. It is the HTTP side of
|
|
9
9
|
# `hecks check_era`, which the `HostHttp` adapter runs; the runtime never calls it.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require_relative "../projection_files"
|
|
4
4
|
|
|
5
5
|
module Hecks
|
|
6
|
-
module
|
|
6
|
+
module Tools
|
|
7
7
|
# The command behind `hecks project_expression_tables`: projects the expression machinery's
|
|
8
8
|
# operator and normalisation tables from the grammar bluebook into
|
|
9
9
|
# `lib/hecks/bluebook/expression/projection.json`.
|
|
@@ -5,7 +5,7 @@ require "optparse"
|
|
|
5
5
|
require_relative "../../hecks"
|
|
6
6
|
|
|
7
7
|
module Hecks
|
|
8
|
-
module
|
|
8
|
+
module Tools
|
|
9
9
|
# The command behind `hecks follow`: live-tails a domain's persisted event log as JSON lines.
|
|
10
10
|
#
|
|
11
11
|
# Events are one table per domain, so this polls the first repository that answers `:events`
|
|
@@ -9,21 +9,24 @@ module Hecks
|
|
|
9
9
|
# The command line of a sweep: its options, and what the chosen adapter needs.
|
|
10
10
|
module Options
|
|
11
11
|
# The options that take a whole number, and the key each fills.
|
|
12
|
-
INTEGER_OPTIONS = { "--seeds" => :seeds, "--steps" => :steps, "--workers" => :workers
|
|
12
|
+
INTEGER_OPTIONS = { "--seeds" => :seeds, "--steps" => :steps, "--workers" => :workers,
|
|
13
|
+
"--list-shards" => :list_shards }.freeze
|
|
13
14
|
|
|
14
15
|
# The most children a Postgres sweep runs at once unless `--workers` says otherwise.
|
|
15
16
|
POSTGRES_WORKERS = 4
|
|
16
17
|
|
|
17
18
|
# @param args [Array<String>] the command line, consumed
|
|
18
|
-
# @return [Hash, nil] `seeds`, `steps`, `workers`, `adapter`, `persist
|
|
19
|
-
#
|
|
19
|
+
# @return [Hash, nil] `seeds`, `steps`, `workers`, `adapter`, `persist`, `domain`, `shard`
|
|
20
|
+
# (the shard's number and the shard count) and `list_shards` (how many shards to list);
|
|
21
|
+
# nil after a refusal
|
|
20
22
|
def parse(args)
|
|
21
|
-
options = { seeds: 20, steps: 30, workers: nil, adapter: :memory, domain: nil, persist: false
|
|
23
|
+
options = { seeds: 20, steps: 30, workers: nil, adapter: :memory, domain: nil, persist: false,
|
|
24
|
+
shard: nil, list_shards: nil }
|
|
22
25
|
until args.empty?
|
|
23
26
|
apply_option(options, args.shift, args)
|
|
24
27
|
return nil unless adapter_known?(options[:adapter])
|
|
25
28
|
end
|
|
26
|
-
options
|
|
29
|
+
settle_shards(options)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
# Records one command-line word in `options`, taking its value from `rest` when it has one.
|
|
@@ -31,10 +34,42 @@ module Hecks
|
|
|
31
34
|
if (key = INTEGER_OPTIONS[arg]) then options[key] = Integer(rest.shift)
|
|
32
35
|
elsif arg == "--persist-regressions" then options[:persist] = true
|
|
33
36
|
elsif arg == "--adapter" then options[:adapter] = adapter_name(rest.shift)
|
|
37
|
+
elsif arg == "--shard" then options[:shard] = rest.shift.to_s
|
|
34
38
|
else options[:domain] = arg
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
|
|
42
|
+
# Turns `--shard I/N` into the pair it names, and refuses the shard options that do not fit
|
|
43
|
+
# together or with what they split.
|
|
44
|
+
#
|
|
45
|
+
# @param options [Hash] the options as typed
|
|
46
|
+
# @return [Hash, nil] the options with `shard` parsed, or nil after a refusal
|
|
47
|
+
def settle_shards(options)
|
|
48
|
+
return options if options.values_at(:shard, :list_shards).none?
|
|
49
|
+
return nil unless shard_choice_clear?(options)
|
|
50
|
+
|
|
51
|
+
options[:shard] &&= Shards.parse_shard(options[:shard])
|
|
52
|
+
options.values_at(:shard, :list_shards).any? ? options : nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [Boolean] whether the shard options name one split of the corpus; warns why not
|
|
56
|
+
def shard_choice_clear?(options)
|
|
57
|
+
reason = shard_conflict(options)
|
|
58
|
+
warn reason if reason
|
|
59
|
+
reason.nil?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @return [String, nil] why the shard options cannot be used together, or nil when they can
|
|
63
|
+
def shard_conflict(options)
|
|
64
|
+
if options[:shard] && options[:list_shards]
|
|
65
|
+
"--shard sweeps one shard and --list-shards lists them all; use one"
|
|
66
|
+
elsif options[:domain]
|
|
67
|
+
"shards split every domain of the checkout, so no domain can be named"
|
|
68
|
+
elsif options[:list_shards] && !options[:list_shards].positive?
|
|
69
|
+
"--list-shards takes a shard count of 1 or more"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
38
73
|
# @param word [String, nil] the word after `--adapter`
|
|
39
74
|
# @return [Symbol] the adapter it names, lowercased
|
|
40
75
|
def adapter_name(word) = word.to_s.downcase.to_sym
|
|
@@ -16,16 +16,27 @@ module Hecks
|
|
|
16
16
|
# @yieldparam domain [String] a domain directory
|
|
17
17
|
# @yieldreturn [Boolean] whether it was clean
|
|
18
18
|
# @return [Boolean] true if every domain's child exited 0, false if any exited non-zero
|
|
19
|
-
def fuzz_in_pool(domains, workers, &)
|
|
19
|
+
def fuzz_in_pool(domains, workers, &)
|
|
20
20
|
results = run_children(domains, workers, &)
|
|
21
21
|
slowest = results.max_by(5) { |_, (_, _, seconds)| seconds }
|
|
22
22
|
.map { |index, (_, _, seconds)| "#{File.basename(domains[index])} #{seconds.round}s" }
|
|
23
23
|
warn "slowest domains: #{slowest.join(", ")}"
|
|
24
|
+
warn "domain seconds: #{seconds_by_domain(domains, results)}"
|
|
24
25
|
replay_outputs(results).all?
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
private
|
|
28
29
|
|
|
30
|
+
# Every domain's wall seconds, so a cost table can be read off one run's log.
|
|
31
|
+
#
|
|
32
|
+
# @return [String] `directory seconds` for each domain, in domain order, the directory
|
|
33
|
+
# relative to the working directory when it lies under it
|
|
34
|
+
def seconds_by_domain(domains, results)
|
|
35
|
+
results.sort.map do |index, (_, _, seconds)|
|
|
36
|
+
"#{domains[index].delete_prefix("#{Dir.pwd}/")} #{seconds.round(1)}"
|
|
37
|
+
end.join(", ")
|
|
38
|
+
end
|
|
39
|
+
|
|
29
40
|
# @return [Hash{Integer => Array}] by domain index: whether the child succeeded, its output
|
|
30
41
|
# file, and its seconds
|
|
31
42
|
def run_children(domains, workers, &)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../tools"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Tools
|
|
7
|
+
module FuzzSweep
|
|
8
|
+
# Splits the domains of a sweep into `n` shards, so `n` jobs together sweep every domain once.
|
|
9
|
+
#
|
|
10
|
+
# The split is a pure function of the domain list, `n` and the committed cost table: no clock,
|
|
11
|
+
# no discovery order and no run history reach it, so every job computes the same partition.
|
|
12
|
+
# Domains are dealt, dearest first, to whichever shard holds the least cost so far, which
|
|
13
|
+
# keeps the shards near one another in cost; a domain the table does not name costs the
|
|
14
|
+
# table's median, and an absent table costs every domain the same.
|
|
15
|
+
module Shards
|
|
16
|
+
# What `--shard` takes: the shard's number, a slash, and how many shards there are.
|
|
17
|
+
SHARD_WORD = %r{\A([1-9]\d*)/([1-9]\d*)\z}
|
|
18
|
+
|
|
19
|
+
# Where the committed cost table is read from, relative to the checkout: one
|
|
20
|
+
# `directory:seconds` line for each domain, `#` lines being notes.
|
|
21
|
+
COST_TABLE = "spec/fuzzing/fuzz_runtime_baseline.log"
|
|
22
|
+
|
|
23
|
+
# What a domain costs when no table says: every domain alike.
|
|
24
|
+
FLAT_COST = 1.0
|
|
25
|
+
|
|
26
|
+
# A split that left a domain out or put one in two shards.
|
|
27
|
+
class NotAPartition < StandardError; end
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# @param word [String, nil] the word after `--shard`
|
|
32
|
+
# @return [Array(Integer, Integer), nil] the shard's number and the shard count, or nil when
|
|
33
|
+
# the word is not `I/N` with `I` between 1 and `N`; warns what is accepted
|
|
34
|
+
def parse_shard(word)
|
|
35
|
+
match = SHARD_WORD.match(word.to_s)
|
|
36
|
+
return [match[1].to_i, match[2].to_i] if match && match[1].to_i <= match[2].to_i
|
|
37
|
+
|
|
38
|
+
warn "unknown --shard #{word.inspect} — use I/N with I from 1 to N, such as 1/2, 2/2 or 3/4"
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param domains [Array<String>] the domain directories, each unique
|
|
43
|
+
# @param shards [Integer] how many shards to split into
|
|
44
|
+
# @param costs [Hash{String => Float}] each domain directory's cost, perhaps lacking some
|
|
45
|
+
# @return [Array<Array<String>>] the domains of each shard, each in the order `domains` has
|
|
46
|
+
def partition(domains, shards, costs = {})
|
|
47
|
+
price = prices(domains, costs)
|
|
48
|
+
order = domains.each_index.sort_by { |index| [-price[index], domains[index]] }
|
|
49
|
+
deal(order, price, shards).map { |indexes| indexes.sort.map { |index| domains[index] } }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param order [Array<Integer>] the domain positions, in the order to deal them
|
|
53
|
+
# @param price [Array<Float>] each position's cost
|
|
54
|
+
# @param shards [Integer] how many shards to deal into
|
|
55
|
+
# @return [Array<Array<Integer>>] the positions each shard took, each to the lightest shard
|
|
56
|
+
# so far, the lowest numbered when they tie
|
|
57
|
+
def deal(order, price, shards)
|
|
58
|
+
loads = Array.new(shards, 0.0)
|
|
59
|
+
order.each_with_object(Array.new(shards) { [] }) do |index, taken|
|
|
60
|
+
lightest = loads.each_index.min_by { |shard| [loads[shard], shard] }
|
|
61
|
+
loads[lightest] += price[index]
|
|
62
|
+
taken[lightest] << index
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @param domains [Array<String>] the domain directories
|
|
67
|
+
# @param number [Integer] the shard wanted, from 1
|
|
68
|
+
# @param shards [Integer] how many shards there are
|
|
69
|
+
# @param costs [Hash{String => Float}] each domain directory's cost
|
|
70
|
+
# @return [Array<String>] the domains that shard sweeps
|
|
71
|
+
def select(domains, number, shards, costs = {}) = partition(domains, shards, costs).fetch(number - 1)
|
|
72
|
+
|
|
73
|
+
# The assignment as data: one line for each domain, `I/N<TAB>cost<TAB>directory`, shard by
|
|
74
|
+
# shard. A split that left a domain out or put one in two shards is refused, since a job
|
|
75
|
+
# that reads this list would then trust a sweep that covers less than it says.
|
|
76
|
+
#
|
|
77
|
+
# @param domains [Array<String>] the domain directories
|
|
78
|
+
# @param shards [Integer] how many shards to split into
|
|
79
|
+
# @param costs [Hash{String => Float}] each domain directory's cost
|
|
80
|
+
# @param root [String] the checkout the directories are shown relative to
|
|
81
|
+
# @return [Array<String>] the lines
|
|
82
|
+
# @raise [NotAPartition] when the shards are not a partition of `domains`
|
|
83
|
+
def listing(domains, shards, costs, root)
|
|
84
|
+
split = partition(domains, shards, costs)
|
|
85
|
+
raise NotAPartition, "the shards are not a partition of the domains" unless split.flatten.sort == domains.sort
|
|
86
|
+
|
|
87
|
+
price = domains.zip(prices(domains, costs)).to_h
|
|
88
|
+
split.each_with_index.flat_map do |members, index|
|
|
89
|
+
members.map { |domain| row("#{index + 1}/#{shards}", price[domain], domain.delete_prefix("#{root}/")) }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def row(shard, price, directory) = "#{shard}\t#{price.round(1)}\t#{directory}"
|
|
94
|
+
|
|
95
|
+
# Every discoverable domain, or the share of them `--shard I/N` asks for, which a pool
|
|
96
|
+
# starts dearest first so the longest domain is never the last one left running.
|
|
97
|
+
#
|
|
98
|
+
# @param options [Hash] the parsed options: `shard`, perhaps
|
|
99
|
+
# @param root [String] the checkout
|
|
100
|
+
# @return [Array<String>] the domain directories this sweep covers
|
|
101
|
+
def domains_for(options, root)
|
|
102
|
+
domains = Hecks::Corpus.fuzzable_domains(root)
|
|
103
|
+
return domains unless options[:shard]
|
|
104
|
+
|
|
105
|
+
number, shards = options[:shard]
|
|
106
|
+
puts "shard #{number}/#{shards}"
|
|
107
|
+
costs = costs_from(root)
|
|
108
|
+
dearest_first(select(domains, number, shards, costs), costs)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param domains [Array<String>] the domain directories
|
|
112
|
+
# @param costs [Hash{String => Float}] each domain directory's cost
|
|
113
|
+
# @return [Array<String>] the same domains, dearest first, ties in path order
|
|
114
|
+
def dearest_first(domains, costs)
|
|
115
|
+
price = domains.zip(prices(domains, costs)).to_h
|
|
116
|
+
domains.sort_by { |domain| [-price[domain], domain] }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Prints the listing of every domain of the checkout, and sweeps nothing.
|
|
120
|
+
#
|
|
121
|
+
# @param shards [Integer] how many shards to split into
|
|
122
|
+
# @param root [String] the checkout
|
|
123
|
+
# @return [Integer] 0 once printed
|
|
124
|
+
def print_listing(shards, root)
|
|
125
|
+
puts listing(Hecks::Corpus.fuzzable_domains(root), shards, costs_from(root), root)
|
|
126
|
+
0
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @param root [String] the checkout
|
|
130
|
+
# @return [Hash{String => Float}] seconds by absolute domain directory, from the committed
|
|
131
|
+
# table; empty when the table is absent
|
|
132
|
+
def costs_from(root)
|
|
133
|
+
path = File.join(root, COST_TABLE)
|
|
134
|
+
return {} unless File.file?(path)
|
|
135
|
+
|
|
136
|
+
File.readlines(path, chomp: true).reject { |line| line.strip.empty? || line.start_with?("#") }
|
|
137
|
+
.to_h { |line| line.split(":", 2).then { |dir, seconds| [File.join(root, dir), Float(seconds)] } }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @return [Array<Float>] each domain's cost, a missing one at the table's median
|
|
141
|
+
def prices(domains, costs)
|
|
142
|
+
fallback = median(costs.values) || FLAT_COST
|
|
143
|
+
domains.map { |domain| costs.fetch(domain, fallback) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def median(values)
|
|
147
|
+
return nil if values.empty?
|
|
148
|
+
|
|
149
|
+
ranked = values.sort
|
|
150
|
+
(ranked[(ranked.size - 1) / 2] + ranked[ranked.size / 2]) / 2.0
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -8,6 +8,7 @@ require_relative "fuzz_sweep/options"
|
|
|
8
8
|
require_relative "fuzz_sweep/findings"
|
|
9
9
|
require_relative "fuzz_sweep/reporting"
|
|
10
10
|
require_relative "fuzz_sweep/pool"
|
|
11
|
+
require_relative "fuzz_sweep/shards"
|
|
11
12
|
|
|
12
13
|
module Hecks
|
|
13
14
|
module Tools
|
|
@@ -15,11 +16,13 @@ module Hecks
|
|
|
15
16
|
# properties, then shrinks each distinct finding and saves it under `tmp/fuzz-failures/`.
|
|
16
17
|
#
|
|
17
18
|
# hecks fuzz [domain] [--seeds N] [--steps N] [--workers N] [--adapter memory|sqlite|postgres]
|
|
18
|
-
# [--persist-regressions]
|
|
19
|
+
# [--persist-regressions] [--shard I/N | --list-shards N]
|
|
19
20
|
#
|
|
20
21
|
# The sweep is single-runtime on purpose; the cross-runtime differential is
|
|
21
22
|
# `spec/rust_conformance_fuzz_spec.rb`. Without a domain it sweeps every domain
|
|
22
|
-
# `Hecks::Corpus.fuzzable_domains` finds, one forked child per core.
|
|
23
|
+
# `Hecks::Corpus.fuzzable_domains` finds, one forked child per core. `--shard I/N` sweeps only
|
|
24
|
+
# shard I of N (see `Shards`), so N jobs together sweep every domain once; `--list-shards N`
|
|
25
|
+
# prints which shard each domain falls in and sweeps nothing.
|
|
23
26
|
module FuzzSweep
|
|
24
27
|
# How many seeds are drawn for each seed that must execute.
|
|
25
28
|
DRAW_LIMIT = 5
|
|
@@ -57,13 +60,16 @@ module Hecks
|
|
|
57
60
|
# argument is refused
|
|
58
61
|
def main(argv, root: Tools::ROOT)
|
|
59
62
|
require "hecks"
|
|
60
|
-
require "hecks/fuzzing"
|
|
61
63
|
options = parse(argv.dup)
|
|
62
|
-
return 1 unless options
|
|
64
|
+
return 1 unless options
|
|
65
|
+
return Shards.print_listing(options[:list_shards], root) if options[:list_shards]
|
|
66
|
+
|
|
67
|
+
require "hecks/fuzzing"
|
|
68
|
+
return 1 unless adapter_ready?(options)
|
|
63
69
|
|
|
64
70
|
# Every discoverable domain, so one added anywhere is swept without a list. Paths the sweep
|
|
65
71
|
# cannot boot are routed by Hecks::Corpus::ROUTES to the check that owns them.
|
|
66
|
-
domains = options[:domain] ? [options[:domain]] :
|
|
72
|
+
domains = options[:domain] ? [options[:domain]] : Shards.domains_for(options, root)
|
|
67
73
|
ok = sweep(domains, worker_count(options), options, root)
|
|
68
74
|
|
|
69
75
|
puts(ok ? "CLEAN — no generated sequence broke a property or the interpreter." : "FUZZ FOUND SOMETHING.")
|
data/lib/hecks/tools/gate.rb
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
require "open3"
|
|
4
4
|
require "hecks/vocabulary"
|
|
5
5
|
require_relative "../tools"
|
|
6
|
+
require_relative "stage_progress"
|
|
7
|
+
require_relative "gate_memo/session"
|
|
8
|
+
require_relative "gate_report"
|
|
6
9
|
|
|
7
10
|
module Hecks
|
|
8
11
|
module Tools
|
|
@@ -14,10 +17,17 @@ module Hecks
|
|
|
14
17
|
# hecks gate --list # the stages and their checks
|
|
15
18
|
#
|
|
16
19
|
# A green stage prints which checks passed; a red one prints each failing check's whole output
|
|
17
|
-
# and what its failure means, and answers status 1.
|
|
20
|
+
# and what its failure means, and answers status 1. A check whose inputs are unchanged since its
|
|
21
|
+
# last green run is not run: it is printed as skipped, and the verdict counts it as skipped, not
|
|
22
|
+
# passed (see GateMemo).
|
|
18
23
|
module Gate
|
|
19
24
|
USAGE = "usage: hecks gate <stage> [only=a,b] | hecks gate --list"
|
|
20
25
|
|
|
26
|
+
# RuboCop keys its cache by file content, so one directory shared by every worktree lets each
|
|
27
|
+
# reuse the others' results. It is set here, in the gate's child environment, and not in
|
|
28
|
+
# .rubocop.yml, so CI and a bare `rubocop` keep the defaults (ADR 0091).
|
|
29
|
+
RUBOCOP_CACHE_ROOT = File.join(Dir.home, ".cache", "hecks", "rubocop")
|
|
30
|
+
|
|
21
31
|
module_function
|
|
22
32
|
|
|
23
33
|
# @return [Hash{String => Hash}] each stage by name: its `env` and its `checks`, in order,
|
|
@@ -45,8 +55,9 @@ module Hecks
|
|
|
45
55
|
|
|
46
56
|
# @param argv [Array<String>] a stage name and optionally `only=a,b`, or `--list`
|
|
47
57
|
# @param root [String] the checkout the checks run in
|
|
58
|
+
# @param progress [StageProgress] where each check's start and end lines go
|
|
48
59
|
# @return [Integer] 0 when every check passed, 1 when one failed, 2 on bad usage
|
|
49
|
-
def main(argv, root: Tools::ROOT, **)
|
|
60
|
+
def main(argv, root: Tools::ROOT, progress: StageProgress.new, **)
|
|
50
61
|
stages = self.stages
|
|
51
62
|
return list(stages) if argv == ["--list"]
|
|
52
63
|
|
|
@@ -57,7 +68,17 @@ module Hecks
|
|
|
57
68
|
checks = select(stage.fetch("checks"), only)
|
|
58
69
|
return unknown(stage, only) if checks.nil?
|
|
59
70
|
|
|
60
|
-
|
|
71
|
+
run_planned(name, stage, checks, root, progress)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Runs the checks the memo does not skip, records the green ones, and reports the stage.
|
|
75
|
+
#
|
|
76
|
+
# @return [Integer] the verdict of `report`
|
|
77
|
+
def run_planned(name, stage, checks, root, progress)
|
|
78
|
+
session = GateMemo::Session.new(root: root, env: stage.fetch("env", {}))
|
|
79
|
+
plan = session.plan(checks)
|
|
80
|
+
results = run_all(stage, plan.run, root, progress)
|
|
81
|
+
GateReport.report(name, plan, results, session.record(results))
|
|
61
82
|
end
|
|
62
83
|
|
|
63
84
|
# @param argv [Array<String>] the command line words
|
|
@@ -83,18 +104,30 @@ module Hecks
|
|
|
83
104
|
# @param stage [Hash] the stage: its `env` and `checks`
|
|
84
105
|
# @param checks [Array<Hash>] the checks to run
|
|
85
106
|
# @param root [String] the directory they run in
|
|
107
|
+
# @param progress [StageProgress] told when each check starts and ends
|
|
86
108
|
# @return [Hash{String => Array}] each check's id, and its output and whether it passed
|
|
87
|
-
def run_all(stage, checks, root)
|
|
109
|
+
def run_all(stage, checks, root, progress)
|
|
88
110
|
env = stage.fetch("env", {}).reject { |key, _| ENV.key?(key) }
|
|
89
111
|
threads = checks.map do |check|
|
|
90
|
-
|
|
112
|
+
progress.start(check["id"])
|
|
113
|
+
Thread.new { [check["id"], run_timed(check, env, root, progress)] }
|
|
91
114
|
end
|
|
92
115
|
threads.to_h(&:value)
|
|
93
116
|
end
|
|
94
117
|
|
|
118
|
+
# @return [Array(String, Boolean)] what the check printed, and whether it exited 0; the end
|
|
119
|
+
# line is written as the check finishes
|
|
120
|
+
def run_timed(check, env, root, progress)
|
|
121
|
+
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
122
|
+
output, passed = run_one(check, env, root)
|
|
123
|
+
progress.finish(check["id"], passed, Process.clock_gettime(Process::CLOCK_MONOTONIC) - started)
|
|
124
|
+
[output, passed]
|
|
125
|
+
end
|
|
126
|
+
|
|
95
127
|
# @return [Array(String, Boolean)] what the check printed, and whether it exited 0
|
|
96
128
|
def run_one(check, env, root)
|
|
97
129
|
argv = check.fetch("run").map { |word| word.to_s.sub("{workers}", workers.to_s) }
|
|
130
|
+
env = { "RUBOCOP_CACHE_ROOT" => RUBOCOP_CACHE_ROOT }.merge(ENV.slice("RUBOCOP_CACHE_ROOT")).merge(env)
|
|
98
131
|
output, status = Open3.capture2e(env, *argv, chdir: root)
|
|
99
132
|
[output, status.success?]
|
|
100
133
|
rescue SystemCallError => e
|
|
@@ -108,30 +141,6 @@ module Hecks
|
|
|
108
141
|
[Etc.nprocessors / 2, 1].max
|
|
109
142
|
end
|
|
110
143
|
|
|
111
|
-
# @param name [String] the stage name
|
|
112
|
-
# @param checks [Array<Hash>] the checks that ran
|
|
113
|
-
# @param results [Hash{String => Array}] each check's output and whether it passed
|
|
114
|
-
# @return [Integer] 0 when every check passed, 1 otherwise
|
|
115
|
-
def report(name, checks, results)
|
|
116
|
-
failed = checks.reject { |check| results.fetch(check["id"]).last }
|
|
117
|
-
failed.each { |check| print_failure(name, check, results.fetch(check["id"]).first) }
|
|
118
|
-
return summary(name, "red", failed, 1) unless failed.empty?
|
|
119
|
-
|
|
120
|
-
summary(name, "green", checks, 0)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# @return [Integer] the given status, after printing the stage's verdict and its check ids
|
|
124
|
-
def summary(name, verdict, checks, status)
|
|
125
|
-
puts "[gate #{name}] #{verdict}: #{checks.map { |check| check["id"] }.join(", ")}"
|
|
126
|
-
status
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# @return [void] prints a failing check's output and what its failure means
|
|
130
|
-
def print_failure(name, check, output)
|
|
131
|
-
puts "\n[gate #{name}] #{check["title"]}\n\n#{output}"
|
|
132
|
-
puts "\n[gate #{name}] BLOCKED: #{check["blocked"]}\n"
|
|
133
|
-
end
|
|
134
|
-
|
|
135
144
|
def list(stages)
|
|
136
145
|
stages.each do |name, stage|
|
|
137
146
|
puts "#{name}: #{stage.fetch("checks").map { |check| check["id"] }.join(", ")}"
|