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
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# The CiPipeline bluebook, bound so it boots standing alone (a behaviors or model_check boot of
|
|
2
|
+
# this directory). The ports it shares with every attaching hecksagon are in
|
|
3
|
+
# ci_pipeline.ports.hecksagon.
|
|
4
|
+
Hecks.hecksagon "CiPipeline" do
|
|
5
|
+
attaches "Governance"
|
|
6
|
+
persisted_by "Memory"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# The anti-corruption layer for Governance, which the bluebook's roles are checked against.
|
|
10
|
+
Hecks.hecksagon "Governance" do
|
|
11
|
+
persisted_by "Memory"
|
|
12
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# The ports CiPipeline declares, for every hecksagon that attaches the bluebook. The bluebook
|
|
2
|
+
# names the questions it asks of its runner and its cache, and never says how they are
|
|
3
|
+
# answered; an adapter binds each port. Declared only: no adapter lives in this bluebook yet.
|
|
4
|
+
Hecks.hecksagon "CiPipeline" do
|
|
5
|
+
# The runner answers what happened in a build, and the critical path through it. GitHub
|
|
6
|
+
# Actions and a local run are each an adapter behind this port.
|
|
7
|
+
CiPipeline::CiRun.port "Runner" do
|
|
8
|
+
answers_query "Reading"
|
|
9
|
+
answers_query "CriticalPath"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# The cache answers whether it holds the corpus for a key.
|
|
13
|
+
CiPipeline::Corpus.port "Cache" do
|
|
14
|
+
answers_query "Lookup"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Binds the `CiReader` port to `CiReader`, which answers `Run`'s `Reading` query with one main CI run as GitHub reports it.
|
|
2
|
+
# Required by name, not relative, so a copy of this directory shares the one implementation loaded.
|
|
3
|
+
require "hecks/ci_speed/adapters/ci_reader"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "CiReader" do
|
|
6
|
+
port "CiReader"
|
|
7
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "time"
|
|
6
|
+
require "hecks/runtime/errors"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
# The `CiReader` port's adapter: answers `Run`'s `Reading` query with one CI run as GitHub
|
|
11
|
+
# reports it, read through `gh`. A run's cache state is read off the jobs: GitHub lists a
|
|
12
|
+
# composite action as one step, so the generated-rust action's regeneration cannot be seen on
|
|
13
|
+
# its own. A cache hit restores in seconds and a miss regenerates the corpus, so a run where any
|
|
14
|
+
# job spent the threshold on that one step is a miss.
|
|
15
|
+
class CiReader
|
|
16
|
+
# The step a job that materializes the generated Rust shows for its composite action.
|
|
17
|
+
GENERATED_RUST_STEP = "Run ./.github/actions/generated-rust"
|
|
18
|
+
|
|
19
|
+
# Seconds on that step beyond which the cache missed.
|
|
20
|
+
MISS_THRESHOLD_SECONDS = 60
|
|
21
|
+
|
|
22
|
+
# @param aggregate [Object, nil] unused
|
|
23
|
+
# @param settings [Hash] unused
|
|
24
|
+
# @param root [String, nil] the checkout `gh` runs in; this repository when nil
|
|
25
|
+
def initialize(aggregate: nil, settings: {}, root: nil)
|
|
26
|
+
@root = root || File.expand_path("../../../..", __dir__)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Reads remote CI's verdict on one commit of a repository's main. Every run GitHub reports
|
|
30
|
+
# for the commit on main must have settled, and every job of each must have passed or been
|
|
31
|
+
# skipped.
|
|
32
|
+
#
|
|
33
|
+
# @param commit [Hash, String] the full commit hash
|
|
34
|
+
# @param repo [Hash, String] `owner/name`
|
|
35
|
+
# @return [Hash] `text:` a JSON document: `color` (`green` or `red`) and `failing_jobs`, the
|
|
36
|
+
# failing job names joined by commas, empty when green
|
|
37
|
+
# @raise [Runtime::GivenNotMet] when no run exists for the commit or a run has not settled
|
|
38
|
+
def head(commit:, repo:)
|
|
39
|
+
sha = named(commit)
|
|
40
|
+
slug = named(repo)
|
|
41
|
+
runs = head_runs(sha, slug)
|
|
42
|
+
settled!(runs, sha)
|
|
43
|
+
failing = runs.flat_map { |run| failing_jobs(run, slug) }
|
|
44
|
+
{ text: JSON.generate(commit: sha, color: failing.empty? ? "green" : "red", failing_jobs: failing.join(",")) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @param run_id [Hash, String, Integer] the GitHub run to read
|
|
48
|
+
# @return [Hash] `text:` a JSON document: the run's commit, wall seconds, conclusion, cache
|
|
49
|
+
# state, longest pole and each job's seconds
|
|
50
|
+
# @raise [Runtime::GivenNotMet] when `gh` cannot read the run
|
|
51
|
+
def reading(run_id:)
|
|
52
|
+
id = run_id.is_a?(Hash) ? run_id.values.first : run_id
|
|
53
|
+
{ text: JSON.generate(document(JSON.parse(view(id.to_s)))) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Refuses a commit with no run on main, and one with a run still going.
|
|
59
|
+
def settled!(runs, sha)
|
|
60
|
+
raise Runtime::GivenNotMet, "no CI run for #{sha[0, 7]} on main" if runs.empty?
|
|
61
|
+
|
|
62
|
+
still = runs.reject { |run| run["status"] == "completed" }
|
|
63
|
+
raise Runtime::GivenNotMet, "CI for #{sha[0, 7]} is still running" if still.any?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def named(value) = value.is_a?(Hash) ? value.values.first.to_s : value.to_s
|
|
67
|
+
|
|
68
|
+
def head_runs(sha, slug)
|
|
69
|
+
out, err, status = Open3.capture3("gh", "run", "list", "--repo", slug, "--commit", sha,
|
|
70
|
+
"--branch", "main", "--limit", "100",
|
|
71
|
+
"--json", "databaseId,status,conclusion,workflowName", chdir: @root)
|
|
72
|
+
raise Runtime::GivenNotMet, "gh could not list runs for #{sha[0, 7]}: #{first_line(err)}" unless status.success?
|
|
73
|
+
|
|
74
|
+
JSON.parse(out)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
PASSING_JOB_CONCLUSIONS = %w[success skipped].freeze
|
|
78
|
+
private_constant :PASSING_JOB_CONCLUSIONS
|
|
79
|
+
|
|
80
|
+
# Everything up to the first line break.
|
|
81
|
+
FIRST_LINE = /[^\n]*/
|
|
82
|
+
private_constant :FIRST_LINE
|
|
83
|
+
|
|
84
|
+
# The failing jobs of one run; the workflow's name stands in when no job is named failed.
|
|
85
|
+
def failing_jobs(run, slug)
|
|
86
|
+
return [] if run["conclusion"] == "success"
|
|
87
|
+
|
|
88
|
+
failed = jobs_of(run, slug).reject { |job| PASSING_JOB_CONCLUSIONS.include?(job["conclusion"]) }
|
|
89
|
+
failed.empty? ? [run.fetch("workflowName")] : failed.map { |job| job.fetch("name") }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def jobs_of(run, slug)
|
|
93
|
+
id = run.fetch("databaseId").to_s
|
|
94
|
+
out, err, status = Open3.capture3("gh", "run", "view", id, "--repo", slug, "--json", "jobs", chdir: @root)
|
|
95
|
+
raise Runtime::GivenNotMet, "gh could not read run #{id}: #{first_line(err)}" unless status.success?
|
|
96
|
+
|
|
97
|
+
JSON.parse(out).fetch("jobs")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# The first line of a command's error output, or the empty string.
|
|
101
|
+
def first_line(text) = text.to_s[FIRST_LINE].to_s
|
|
102
|
+
|
|
103
|
+
def view(id)
|
|
104
|
+
out, err, status = Open3.capture3("gh", "run", "view", id, "--json",
|
|
105
|
+
"headSha,conclusion,createdAt,updatedAt,jobs", chdir: @root)
|
|
106
|
+
raise Runtime::GivenNotMet, "gh could not read run #{id}: #{err.lines.first&.strip}" unless status.success?
|
|
107
|
+
|
|
108
|
+
out
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def document(run)
|
|
112
|
+
jobs = timed(run.fetch("jobs"))
|
|
113
|
+
pole = jobs.max_by { |job| job[:seconds] }
|
|
114
|
+
{ commit: run.fetch("headSha"), conclusion: run.fetch("conclusion"),
|
|
115
|
+
wall_seconds: seconds(run.fetch("createdAt"), run.fetch("updatedAt")),
|
|
116
|
+
cache_state: cache_state(run.fetch("jobs")), longest_pole: pole&.fetch(:name), jobs: jobs }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def timed(jobs)
|
|
120
|
+
jobs.select { |job| job["startedAt"] && job["completedAt"] }
|
|
121
|
+
.map { |job| { name: job.fetch("name"), seconds: seconds(job["startedAt"], job["completedAt"]) } }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def cache_state(jobs)
|
|
125
|
+
regenerated = jobs.any? do |job|
|
|
126
|
+
job.fetch("steps", []).any? { |step| regenerating?(step) }
|
|
127
|
+
end
|
|
128
|
+
regenerated ? "miss" : "hit"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def regenerating?(step)
|
|
132
|
+
step["name"] == GENERATED_RUST_STEP && step["startedAt"] && step["completedAt"] &&
|
|
133
|
+
seconds(step["startedAt"], step["completedAt"]) > MISS_THRESHOLD_SECONDS
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def seconds(from, to)
|
|
137
|
+
(Time.parse(to) - Time.parse(from)).round
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class LocalRunner
|
|
6
|
+
# What an adapter of the `LocalRunner` port answers with: each field in the shape
|
|
7
|
+
# `Experiment::Complete` takes it, so the bluebook's policy passes it on as it stands.
|
|
8
|
+
module Answer
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
# @param asked [Hash{Symbol => Object}] the experiment's own fields, plain: `lever`,
|
|
12
|
+
# `base_ref` and `candidate_ref`
|
|
13
|
+
# @param definition [String] the definition's name
|
|
14
|
+
# @param verdict [Verdict] what the samples say
|
|
15
|
+
# @param load [Float] the machine's one-minute load average when the experiment started
|
|
16
|
+
# @param unmeasured [Array<String>] a note for each step left out of both sides
|
|
17
|
+
# @return [Hash{Symbol => Hash}] the answer
|
|
18
|
+
def build(asked:, definition:, verdict:, load:, unmeasured:)
|
|
19
|
+
basis = verdict.basis(definition: definition, load: load,
|
|
20
|
+
refs: { base: asked[:base_ref], candidate: asked[:candidate_ref] })
|
|
21
|
+
fields = timings(verdict).merge(load: load.round(2), unmeasured: unmeasured.join("; "),
|
|
22
|
+
verdict: verdict.verdict, basis: basis,
|
|
23
|
+
reestimates: asked[:lever].to_s,
|
|
24
|
+
expected_seconds: verdict.expected_seconds)
|
|
25
|
+
fields.transform_values { |value| wrap(value) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @param verdict [Verdict] what the samples say
|
|
29
|
+
# @return [Hash{Symbol => Float}] each side's time, the spread and the saving
|
|
30
|
+
def timings(verdict)
|
|
31
|
+
{ base_seconds: verdict.base_seconds, candidate_seconds: verdict.candidate_seconds,
|
|
32
|
+
spread_seconds: verdict.spread_seconds, saved_seconds: verdict.saved_seconds }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param value [Object] a field's value
|
|
36
|
+
# @return [Hash{Symbol => Object}] the value in the single-field shape commands take
|
|
37
|
+
def wrap(value) = { value: value }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hecks/ci_speed/adapters/local_runner/refused"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class LocalRunner
|
|
8
|
+
# The experiments the bluebook knows how to run: its `ExperimentDefinition` rows, each with
|
|
9
|
+
# the `ExperimentStep` rows that name it, in the order they are written.
|
|
10
|
+
class Catalog
|
|
11
|
+
# One step: a hecks verb and the `name=value` words it is called with.
|
|
12
|
+
Step = Struct.new(:name, :verb, :arguments, :needs, keyword_init: true) do
|
|
13
|
+
# @return [Array<String>] the launcher words for the verb: a command ends in `!`, and a
|
|
14
|
+
# query is asked with `query`
|
|
15
|
+
def form = verb.end_with?("!") ? [verb] : ["query", verb]
|
|
16
|
+
|
|
17
|
+
# @return [Array<String>] the verb's own arguments
|
|
18
|
+
def words = arguments.to_s.split
|
|
19
|
+
|
|
20
|
+
# @return [Array<String>] the names of the `name=value` arguments, as a usage line
|
|
21
|
+
# lists them; a flag such as `--help` has no name to look up
|
|
22
|
+
def argument_names = words.reject { |word| word.start_with?("-") }.map { |word| word.split("=").first }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# One definition: what it times, and what each sample starts from.
|
|
26
|
+
Definition = Struct.new(:name, :measures, :cache_state, :needs_generated_tree, :steps, keyword_init: true) do
|
|
27
|
+
# @return [Boolean] whether each sample starts from a copy of the generated tree
|
|
28
|
+
def generated_tree? = needs_generated_tree == "yes"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Reads the rows a bluebook declares.
|
|
32
|
+
#
|
|
33
|
+
# @param bluebook [Bluebook::Declaration] the CiSpeed bluebook
|
|
34
|
+
# @return [Catalog] its definitions
|
|
35
|
+
def self.from_bluebook(bluebook)
|
|
36
|
+
new(definitions_of(rows_of(bluebook, "ExperimentDefinition"), rows_of(bluebook, "ExperimentStep")))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param bluebook [Bluebook::Declaration] a bluebook to search
|
|
40
|
+
# @param object [String] the name of the value object whose rows are wanted
|
|
41
|
+
# @return [Array<Hash{Symbol => String}>] its member rows
|
|
42
|
+
def self.rows_of(bluebook, object)
|
|
43
|
+
value_objects_of(bluebook).select { |candidate| candidate.hecks_name == object }.flat_map(&:members)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param bluebook [Bluebook::Declaration] a bluebook to search
|
|
47
|
+
# @return [Array<Bluebook::ValueObject>] every value object of every aggregate
|
|
48
|
+
def self.value_objects_of(bluebook) = bluebook.aggregates.flat_map(&:value_objects)
|
|
49
|
+
private_class_method :value_objects_of
|
|
50
|
+
|
|
51
|
+
# @param definitions [Array<Definition>] the experiments, by their own names
|
|
52
|
+
def initialize(definitions)
|
|
53
|
+
@definitions = definitions.to_h { |definition| [definition.name, definition] }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param name [String] a definition's name
|
|
57
|
+
# @return [Definition] the definition
|
|
58
|
+
# @raise [Refused] when no definition has that name, listing those that do
|
|
59
|
+
def fetch(name)
|
|
60
|
+
@definitions.fetch(name) do
|
|
61
|
+
raise Refused, "no experiment definition is named #{name.inspect}; defined: #{names.join(", ")}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @return [Array<String>] every definition's name
|
|
66
|
+
def names = @definitions.keys
|
|
67
|
+
|
|
68
|
+
# @param definitions [Array<Hash>] `ExperimentDefinition` rows
|
|
69
|
+
# @param steps [Array<Hash>] `ExperimentStep` rows
|
|
70
|
+
# @return [Array<Definition>] each definition with the steps that name it
|
|
71
|
+
def self.definitions_of(definitions, steps)
|
|
72
|
+
definitions.map do |row|
|
|
73
|
+
own = steps.select { |step| step[:definition] == row[:name] }
|
|
74
|
+
Definition.new(name: row[:name], measures: row[:measures], cache_state: row[:cache_state],
|
|
75
|
+
needs_generated_tree: row[:needs_generated_tree], steps: own.map { |step| step_of(step) })
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
private_class_method :definitions_of
|
|
79
|
+
|
|
80
|
+
# @param row [Hash] an `ExperimentStep` row
|
|
81
|
+
# @return [Step] the step, needing nothing unless the row says so
|
|
82
|
+
def self.step_of(row)
|
|
83
|
+
Step.new(name: row[:name], verb: row[:verb], arguments: row[:arguments], needs: row[:needs] || "none")
|
|
84
|
+
end
|
|
85
|
+
private_class_method :step_of
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "tmpdir"
|
|
6
|
+
require "hecks/ci_speed/adapters/local_runner/refused"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
class LocalRunner
|
|
11
|
+
# Two temporary, detached git worktrees of a repository, one for each side of an experiment.
|
|
12
|
+
# They live in a directory made for the run and are removed when the run ends, whatever
|
|
13
|
+
# ended it. The repository's own checkout is only asked about its refs and its generated
|
|
14
|
+
# tree, and is never written.
|
|
15
|
+
class Checkouts
|
|
16
|
+
# Where the generated Rust lives in a checkout, and what a cold checkout lacks.
|
|
17
|
+
GENERATED_TREE = "rust/src/generated"
|
|
18
|
+
|
|
19
|
+
# Makes both checkouts, yields their paths, and removes them afterwards.
|
|
20
|
+
#
|
|
21
|
+
# @param root [String] the repository whose worktrees these are
|
|
22
|
+
# @param shas [Hash{Symbol => String}] the commit each side is checked out at, by side
|
|
23
|
+
# @param scratch [String, nil] a directory to make the run's directory in; the system's
|
|
24
|
+
# temporary directory when nil
|
|
25
|
+
# @yield [paths] the checkouts
|
|
26
|
+
# @yieldparam paths [Hash{Symbol => String}] each side's checkout path, by side
|
|
27
|
+
# @return [Object] what the block answers
|
|
28
|
+
def self.with(root:, shas:, scratch: nil)
|
|
29
|
+
FileUtils.mkdir_p(scratch) if scratch
|
|
30
|
+
directory = Dir.mktmpdir("ci-experiment-", scratch)
|
|
31
|
+
checkouts = new(root, directory)
|
|
32
|
+
yield shas.to_h { |side, sha| [side, checkouts.add(side, sha)] }
|
|
33
|
+
ensure
|
|
34
|
+
checkouts&.remove_all
|
|
35
|
+
FileUtils.remove_entry(directory) if directory && File.exist?(directory)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @param root [String] the repository
|
|
39
|
+
# @param directory [String] where the checkouts are made
|
|
40
|
+
def initialize(root, directory)
|
|
41
|
+
@root = root
|
|
42
|
+
@directory = directory
|
|
43
|
+
@added = []
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param side [Symbol] which side the checkout is for
|
|
47
|
+
# @param sha [String] the commit to check out, detached
|
|
48
|
+
# @return [String] the checkout's path
|
|
49
|
+
# @raise [Refused] when git cannot make the worktree
|
|
50
|
+
def add(side, sha)
|
|
51
|
+
path = File.join(@directory, side.to_s)
|
|
52
|
+
@added << path
|
|
53
|
+
git("worktree", "add", "--detach", path, sha)
|
|
54
|
+
path
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Removes every checkout made, and forgets any whose creation stopped half way.
|
|
58
|
+
#
|
|
59
|
+
# @return [void]
|
|
60
|
+
def remove_all
|
|
61
|
+
@added.each { |path| Open3.capture2e("git", "-C", @root, "worktree", "remove", "--force", path) }
|
|
62
|
+
Open3.capture2e("git", "-C", @root, "worktree", "prune")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Puts a checkout's generated tree back to what a sample starts from: nothing, or a copy of
|
|
66
|
+
# the tree the asking checkout holds.
|
|
67
|
+
#
|
|
68
|
+
# @param checkout [String] a checkout's path
|
|
69
|
+
# @param copy_from [String, nil] the repository whose generated tree is copied in; nil
|
|
70
|
+
# leaves the checkout with none
|
|
71
|
+
# @return [void]
|
|
72
|
+
def self.reset_generated_tree(checkout, copy_from)
|
|
73
|
+
target = File.join(checkout, GENERATED_TREE)
|
|
74
|
+
FileUtils.rm_rf(target)
|
|
75
|
+
FileUtils.cp_r(File.join(copy_from, GENERATED_TREE), target) if copy_from
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def git(*words)
|
|
81
|
+
out, status = Open3.capture2e("git", "-C", @root, *words)
|
|
82
|
+
raise Refused, "git #{words.join(" ")} failed in #{@root}: #{out.strip}" unless status.success?
|
|
83
|
+
|
|
84
|
+
out
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
require "rbconfig"
|
|
5
|
+
require "hecks/ci_speed/adapters/local_runner/refused"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
class LocalRunner
|
|
10
|
+
# Runs hecks verbs through `exe/hecks` of one checkout, as that checkout's own code would
|
|
11
|
+
# run them. A step is only ever a verb call: nothing here takes a shell line.
|
|
12
|
+
class Launcher
|
|
13
|
+
# What every verb runs with: memory persistence, so a measured run writes no journal and
|
|
14
|
+
# reaches no database, whatever this process was started with.
|
|
15
|
+
ENVIRONMENT = { "HECKS_ENVIRONMENT" => "memory", "HECKS_DATABASE" => nil }.freeze
|
|
16
|
+
|
|
17
|
+
# @param checkout [String] a checkout's path
|
|
18
|
+
def initialize(checkout)
|
|
19
|
+
@checkout = checkout
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param step [Catalog::Step] the step to ask about
|
|
23
|
+
# @return [Boolean] whether this checkout's launcher knows the step's verb, and every
|
|
24
|
+
# argument the step gives it
|
|
25
|
+
def knows?(step)
|
|
26
|
+
out, status = run(*step.form, "--help")
|
|
27
|
+
status.success? && step.argument_names.all? { |name| out.include?("#{name}=") }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Runs a step and times it.
|
|
31
|
+
#
|
|
32
|
+
# @param step [Catalog::Step] the step to run
|
|
33
|
+
# @return [Float] the seconds it took, on a monotonic clock
|
|
34
|
+
# @raise [Refused] with everything the verb printed, when it ends badly
|
|
35
|
+
def time(step)
|
|
36
|
+
words = [*step.form, *step.words, *("--wait" if step.verb.end_with?("!"))]
|
|
37
|
+
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
38
|
+
out, status = run(*words)
|
|
39
|
+
seconds = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started
|
|
40
|
+
return seconds if status.success?
|
|
41
|
+
|
|
42
|
+
raise Refused, "step #{step.name} (#{words.join(" ")}) ended with status #{status.exitstatus} " \
|
|
43
|
+
"in #{@checkout}:\n#{out}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# Runs the launcher as the leader of its own process group, so that when this process is
|
|
49
|
+
# interrupted the verb and every process it forked go with it, and none is left running in
|
|
50
|
+
# a checkout that is about to be removed.
|
|
51
|
+
def run(*words)
|
|
52
|
+
launch = [RbConfig.ruby, File.join(@checkout, "exe", "hecks"), *words]
|
|
53
|
+
Open3.popen2e(ENVIRONMENT, *launch, chdir: @checkout, pgroup: true) do |input, output, waiter|
|
|
54
|
+
input.close
|
|
55
|
+
[output.read, waiter.value]
|
|
56
|
+
ensure
|
|
57
|
+
stop(waiter.pid) if waiter.alive?
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def stop(group)
|
|
62
|
+
Process.kill("TERM", -group)
|
|
63
|
+
rescue Errno::ESRCH, Errno::EPERM
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
require "hecks/ci_speed/adapters/local_runner/refused"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
class LocalRunner
|
|
9
|
+
# The machine's one-minute load average, which says how busy the machine was while an
|
|
10
|
+
# experiment ran. Ruby's standard library does not report it, so it is read where the
|
|
11
|
+
# system keeps it: `/proc/loadavg` where there is one, and what `uptime` prints elsewhere.
|
|
12
|
+
module LoadAverage
|
|
13
|
+
# The figure `uptime` prints after `load average:` or `load averages:`.
|
|
14
|
+
UPTIME_FIGURE = /load averages?:\s*([0-9]+(?:[.,][0-9]+)?)/
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# @return [Float] the one-minute load average
|
|
19
|
+
# @raise [Refused] when the system reports none, since a result cannot be read without it
|
|
20
|
+
def now
|
|
21
|
+
return proc_figure if File.readable?("/proc/loadavg")
|
|
22
|
+
|
|
23
|
+
out, status = Open3.capture2e("uptime")
|
|
24
|
+
figure = out[UPTIME_FIGURE, 1] if status.success?
|
|
25
|
+
raise Refused, "cannot read the load average: uptime printed #{out.strip.inspect}" unless figure
|
|
26
|
+
|
|
27
|
+
figure.tr(",", ".").to_f
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Float] the figure `/proc/loadavg` leads with
|
|
31
|
+
def proc_figure
|
|
32
|
+
words = File.read("/proc/loadavg").split
|
|
33
|
+
words.first.to_f
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
require "hecks/ci_speed/adapters/local_runner/refused"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
class LocalRunner
|
|
9
|
+
# Turns the two refs an experiment names into the commits they stand for, in the repository
|
|
10
|
+
# that asked.
|
|
11
|
+
module Refs
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# @param root [String] the repository whose refs these are
|
|
15
|
+
# @param asked [Hash{Symbol => Object}] the experiment's `base_ref` and `candidate_ref`
|
|
16
|
+
# @return [Hash{Symbol => String}] each side's commit
|
|
17
|
+
# @raise [Refused] when a ref names no commit, or both name the same one
|
|
18
|
+
def resolve(root, asked)
|
|
19
|
+
shas = { base: sha_of(root, asked.fetch(:base_ref)), candidate: sha_of(root, asked.fetch(:candidate_ref)) }
|
|
20
|
+
return shas unless shas.values.uniq.one?
|
|
21
|
+
|
|
22
|
+
raise Refused, "base ref #{asked[:base_ref]} and candidate ref #{asked[:candidate_ref]} " \
|
|
23
|
+
"are the same commit, #{shas[:base]}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @param root [String] the repository
|
|
27
|
+
# @param ref [String] a ref git can resolve
|
|
28
|
+
# @return [String] the commit it names
|
|
29
|
+
# @raise [Refused] when it names none
|
|
30
|
+
def sha_of(root, ref)
|
|
31
|
+
out, status = Open3.capture2e("git", "-C", root, "rev-parse", "--verify", "--quiet", "#{ref}^{commit}")
|
|
32
|
+
raise Refused, "#{ref.inspect} names no commit in #{root}" unless status.success?
|
|
33
|
+
|
|
34
|
+
out.strip
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class LocalRunner
|
|
6
|
+
# Why an experiment could not be run. The runtime records the message as the experiment's
|
|
7
|
+
# refusal, so it names what was wrong and what would have been right.
|
|
8
|
+
class Refused < StandardError; end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class LocalRunner
|
|
6
|
+
# What the samples of the two sides say. A side's time is the median of its samples, which one
|
|
7
|
+
# slow sample from a busy machine does not move. The spread is the larger of the two sides'
|
|
8
|
+
# own range, so the saving has to stand out from how much either side varied by itself.
|
|
9
|
+
class Verdict
|
|
10
|
+
# @return [Float] the base side's median seconds
|
|
11
|
+
attr_reader :base_seconds
|
|
12
|
+
|
|
13
|
+
# @return [Float] the candidate side's median seconds
|
|
14
|
+
attr_reader :candidate_seconds
|
|
15
|
+
|
|
16
|
+
# @return [Float] the larger of the two sides' ranges, in seconds
|
|
17
|
+
attr_reader :spread_seconds
|
|
18
|
+
|
|
19
|
+
# @param base [Array<Float>] the base side's samples, in seconds
|
|
20
|
+
# @param candidate [Array<Float>] the candidate side's samples, in seconds
|
|
21
|
+
def initialize(base:, candidate:)
|
|
22
|
+
@base = base
|
|
23
|
+
@candidate = candidate
|
|
24
|
+
@base_seconds = median(base).round(3)
|
|
25
|
+
@candidate_seconds = median(candidate).round(3)
|
|
26
|
+
@spread_seconds = [range(base), range(candidate)].max.round(3)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [Float] the base time less the candidate time: negative for a slower candidate
|
|
30
|
+
def saved_seconds = (base_seconds - candidate_seconds).round(3)
|
|
31
|
+
|
|
32
|
+
# @return [String] `faster` or `slower` when the saving is larger than the spread, else
|
|
33
|
+
# `inconclusive`
|
|
34
|
+
def verdict
|
|
35
|
+
return "faster" if saved_seconds > spread_seconds
|
|
36
|
+
return "slower" if (saved_seconds + spread_seconds).negative?
|
|
37
|
+
|
|
38
|
+
"inconclusive"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Integer] what a lever is told it is worth: the saving in whole seconds when
|
|
42
|
+
# conclusively faster, else zero
|
|
43
|
+
def expected_seconds = verdict == "faster" ? saved_seconds.round : 0
|
|
44
|
+
|
|
45
|
+
# @param definition [String] the definition's name
|
|
46
|
+
# @param refs [Hash{Symbol => String}] each side's ref as the experiment named it
|
|
47
|
+
# @param load [Float] the machine's one-minute load average at the start
|
|
48
|
+
# @return [String] one sentence saying what the numbers rest on
|
|
49
|
+
def basis(definition:, refs:, load:)
|
|
50
|
+
"#{definition} on this machine at load #{load.round(2)}, samples interleaved: " \
|
|
51
|
+
"base #{refs.fetch(:base)} took #{show(@base)}, candidate #{refs.fetch(:candidate)} took #{show(@candidate)}; " \
|
|
52
|
+
"the saving of #{saved_seconds}s against a spread of #{spread_seconds}s is #{verdict}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def show(samples)
|
|
58
|
+
"#{median(samples).round(3)}s median (#{samples.map { |sample| sample.round(3) }.join(", ")})"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def median(samples)
|
|
62
|
+
sorted = samples.sort
|
|
63
|
+
middle = sorted.size / 2
|
|
64
|
+
sorted.size.odd? ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2.0
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def range(samples) = samples.max - samples.min
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Binds the `LocalRunner` port to `LocalRunner`, which times an experiment's steps in two temporary checkouts of the refs it names.
|
|
2
|
+
# Required by name, not relative, so a copy of this directory shares the one implementation loaded.
|
|
3
|
+
require "hecks/ci_speed/adapters/local_runner"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "LocalRunner" do
|
|
6
|
+
port "LocalRunner"
|
|
7
|
+
end
|