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,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "time"
|
|
5
|
+
require_relative "../shell"
|
|
6
|
+
require_relative "../console_capture"
|
|
7
|
+
require_relative "brief_text"
|
|
8
|
+
|
|
9
|
+
module Hecks
|
|
10
|
+
module Adapters
|
|
11
|
+
class Dispatching
|
|
12
|
+
# Starts one chosen row's session by running the launcher's own commands, so each step is the
|
|
13
|
+
# bluebook's command and nothing is written but through one: start the Work row, compose its
|
|
14
|
+
# brief, hand the brief to `AgentRun`. Before any of them, pull main (`LinkedTree.PullMain`),
|
|
15
|
+
# so a session never starts from a stale base. A step that fails yields the row to the plan.
|
|
16
|
+
class Launcher
|
|
17
|
+
# The claimant every dispatched row names.
|
|
18
|
+
CLAIMANT = "dispatch"
|
|
19
|
+
|
|
20
|
+
# The JSON object a command prints after any log lines.
|
|
21
|
+
JSON_OBJECT = /\{.*\}/m
|
|
22
|
+
|
|
23
|
+
# @param repo [String] the checkout whose `exe/hecks` runs the commands and where sessions work
|
|
24
|
+
# @param runner [#call, nil] runs an argument list in `repo` and answers a {Shell::Result}
|
|
25
|
+
def initialize(repo, runner: nil)
|
|
26
|
+
@repo = repo
|
|
27
|
+
@runner = runner || ->(argv) { Shell.new.capture("exe/hecks", *argv, chdir: repo) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param row [Plan::Row] the row to start
|
|
31
|
+
# @param held [Array<String>] a line for each area another started row holds
|
|
32
|
+
# @param frozen [Array<String>] the frozen areas and aggregates
|
|
33
|
+
# @param minutes [Integer] the time budget of the row
|
|
34
|
+
# @param limit [Integer, nil] the most spec files a session runs per call, from the world
|
|
35
|
+
# @return [String] one line: the session started, or why the row went back to the plan
|
|
36
|
+
def launch(row, held:, frozen:, minutes:, limit: nil)
|
|
37
|
+
step(row, "pull main", pull_argv)
|
|
38
|
+
step(row, "start", start_argv(row, minutes))
|
|
39
|
+
text = BriefText.new(composed(row)).render(row.key, area: row.area, held: held, frozen: frozen, limit: limit)
|
|
40
|
+
step(row, "dispatch", dispatch_argv(row, text))
|
|
41
|
+
"started #{row.key}"
|
|
42
|
+
rescue ConsoleCapture::Failure => e
|
|
43
|
+
yield_back(row, e.message)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param key [String] the run, which is also the Work row's key
|
|
47
|
+
# @return [void]
|
|
48
|
+
def check(key) = @runner.call(["AgentRun.check!", "to=#{key}", "--wait"])
|
|
49
|
+
|
|
50
|
+
# @param key [String] the Work row to record as done
|
|
51
|
+
# @return [String] the line that says so
|
|
52
|
+
def finish(key)
|
|
53
|
+
@runner.call(["tickets", "Work.finish!", "to=#{key}", "--wait"])
|
|
54
|
+
"finished #{key}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param key [String] the Work row to send back to the plan
|
|
58
|
+
# @param reason [String] why
|
|
59
|
+
# @return [String] the line that says so
|
|
60
|
+
def yield_back(key, reason)
|
|
61
|
+
key = key.key if key.respond_to?(:key)
|
|
62
|
+
@runner.call(["tickets", "Work.yield!", "to=#{key}", "reason.value=#{reason}", "--wait"])
|
|
63
|
+
"yielded #{key}: #{reason}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def step(row, name, argv)
|
|
69
|
+
result = @runner.call(argv)
|
|
70
|
+
return result if result.ok? && !result.out.include?('"refusal": "')
|
|
71
|
+
|
|
72
|
+
raise ConsoleCapture::Failure, "#{name} of #{row.key} failed: #{said(result)}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def said(result) = (result.err.empty? ? result.out : result.err).strip[0, 300]
|
|
76
|
+
|
|
77
|
+
# Local `main` current before the session starts, so no worktree is cut from a stale base.
|
|
78
|
+
def pull_argv = ["LinkedTree.pull_main!", "checkout.value=#{@repo}", "--wait"]
|
|
79
|
+
|
|
80
|
+
def dispatch_argv(row, text)
|
|
81
|
+
["AgentRun.dispatch!", "run.value=#{row.key}", "repo.value=#{@repo}", "brief.value=#{text}", "--wait"]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def start_argv(row, minutes)
|
|
85
|
+
["tickets", "Work.start!", "to=#{row.key}", "claimed_by.value=#{CLAIMANT}", "claimed_at.value=#{Time.now.utc.iso8601}",
|
|
86
|
+
*row.area.map { |word| "area.value=#{word}" }, "budget_minutes.value=#{minutes}", "--wait"]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def composed(row)
|
|
90
|
+
result = step(row, "compose", ["coder", "Brief.compose!", "work.value=#{row.key}", "outcome.value=#{row.title}",
|
|
91
|
+
"detail.value=#{row.detail}", *row.area.map { |word| "area.value=#{word}" }, "--wait"])
|
|
92
|
+
JSON.parse(result.out[JSON_OBJECT])["state"]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../area_overlap"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class Dispatching
|
|
8
|
+
# Which planned rows start a session now, and why each of the others waits. It decides from the
|
|
9
|
+
# rows it is given and starts nothing.
|
|
10
|
+
#
|
|
11
|
+
# A planned row waits when it sits in a frozen area, when its area overlaps a started row's or an
|
|
12
|
+
# earlier chosen row's (by {AreaOverlap}), or when the machine is loaded or the cap is reached,
|
|
13
|
+
# which also hold back every row after it.
|
|
14
|
+
class Plan
|
|
15
|
+
# A row, as {Rows} reads it.
|
|
16
|
+
Row = Struct.new(:key, :title, :detail, :area, keyword_init: true)
|
|
17
|
+
|
|
18
|
+
# What a name is compared without, so `quality_control` and `QualityControl` meet.
|
|
19
|
+
NOT_ALNUM = /[^a-z0-9]/
|
|
20
|
+
|
|
21
|
+
# A row left waiting, and the reason.
|
|
22
|
+
Skip = Struct.new(:key, :reason)
|
|
23
|
+
|
|
24
|
+
# @return [Array<Row>] the rows to start, in plan order
|
|
25
|
+
attr_reader :chosen
|
|
26
|
+
|
|
27
|
+
# @return [Array<Skip>] the rows left waiting, in plan order
|
|
28
|
+
attr_reader :skipped
|
|
29
|
+
|
|
30
|
+
# @param planned [Array<Row>] the planned rows, in plan order
|
|
31
|
+
# @param started [Array<Row>] the started rows
|
|
32
|
+
# @param limits [Hash] `cap:` (Integer), `load:` and `max_load:` (Float), `frozen:` (Array)
|
|
33
|
+
def initialize(planned, started, **limits)
|
|
34
|
+
@started = started
|
|
35
|
+
@limits = limits
|
|
36
|
+
@chosen = []
|
|
37
|
+
@skipped = []
|
|
38
|
+
planned.each { |row| consider(row) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Array<Row>] the started rows and the chosen ones: whose areas are not to be edited
|
|
42
|
+
def holders = @started + @chosen
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def consider(row)
|
|
47
|
+
reason = stop_reason || frozen_reason(row) || overlap_reason(row)
|
|
48
|
+
reason ? @skipped << Skip.new(row.key, reason) : @chosen << row
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def stop_reason = overloaded || capped
|
|
52
|
+
|
|
53
|
+
def overloaded
|
|
54
|
+
return unless @limits[:load] > @limits[:max_load]
|
|
55
|
+
|
|
56
|
+
"skipped: load #{@limits[:load].round(1)} > #{@limits[:max_load].round(1)}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def capped
|
|
60
|
+
return unless holders.size >= @limits[:cap]
|
|
61
|
+
|
|
62
|
+
"skipped: cap #{@limits[:cap]} reached (#{holders.size} started or chosen)"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def frozen_reason(row)
|
|
66
|
+
hit = @limits[:frozen].find { |name| row.area.any? { |word| squash(word).include?(squash(name)) } }
|
|
67
|
+
"skipped: frozen (#{hit})" if hit
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def overlap_reason(row)
|
|
71
|
+
holders.each do |other|
|
|
72
|
+
pair = AreaOverlap.first_overlap(row.area, other.area)
|
|
73
|
+
return "skipped: #{pair[0]} overlaps #{other.key} at #{pair[1]}" if pair
|
|
74
|
+
end
|
|
75
|
+
nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def squash(text) = text.to_s.downcase.gsub(NOT_ALNUM, "")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../started_work"
|
|
4
|
+
require_relative "plan"
|
|
5
|
+
require_relative "../push_size"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
class Dispatching
|
|
10
|
+
# The Work rows and agent runs of a booted registry, read and never written.
|
|
11
|
+
class Rows
|
|
12
|
+
# @param registry [Runtime::Registry, nil]
|
|
13
|
+
def initialize(registry)
|
|
14
|
+
@registry = registry
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# The key prefix of a row that says main is red; such a row is planned first, and so is the
|
|
18
|
+
# `push-due` row once its title says the push is urgent.
|
|
19
|
+
RED = "red-"
|
|
20
|
+
|
|
21
|
+
# @return [Array<Plan::Row>] the planned rows, red ones first, then in plan order (a row
|
|
22
|
+
# with no step last)
|
|
23
|
+
def planned = rows("planned").sort_by.with_index { |row, index| [red?(row[1]) ? 0 : 1, row[0], index] }.map(&:last)
|
|
24
|
+
|
|
25
|
+
# @return [Array<Plan::Row>] the started rows
|
|
26
|
+
def started = rows("started").map(&:last)
|
|
27
|
+
|
|
28
|
+
# @return [Hash{String => Hash}] each agent run's key with its `status:` and `condition:`
|
|
29
|
+
def runs
|
|
30
|
+
aggregate = find("Hecks", "AgentRun")
|
|
31
|
+
return {} unless aggregate
|
|
32
|
+
|
|
33
|
+
@registry.repository("Hecks", aggregate).all.to_h { |run| [field(run, :run).to_s, state(run)] }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def red?(row) = row.key.start_with?(RED) || (row.key == "push-due" && row.title.start_with?(PushSize::URGENT))
|
|
39
|
+
|
|
40
|
+
def rows(status)
|
|
41
|
+
work = find("Tickets", "Work")
|
|
42
|
+
return [] unless work
|
|
43
|
+
|
|
44
|
+
records = @registry.repository("Tickets", work).all
|
|
45
|
+
records.select { |record| field(record, :status) == status }.map { |record| [step(record), row(record)] }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def row(record)
|
|
49
|
+
Plan::Row.new(key: field(record, :work).to_s, title: field(record, :title).to_s,
|
|
50
|
+
detail: field(record, :detail).to_s, area: StartedWork.words(field(record, :area)))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def state(run) = { status: field(run, :status).to_s, condition: field(run, :condition).to_s }
|
|
54
|
+
|
|
55
|
+
def step(record) = field(record, :step) || Float::INFINITY
|
|
56
|
+
|
|
57
|
+
def find(domain, name)
|
|
58
|
+
bluebook = @registry&.bluebook(domain)
|
|
59
|
+
bluebook&.aggregates&.find { |candidate| candidate.hecks_name == name }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def field(record, name) = StartedWork.value(record, name)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "etc"
|
|
4
|
+
require_relative "../work_limits"
|
|
5
|
+
require_relative "../shell"
|
|
6
|
+
require_relative "../codebase/test_scope"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
class Dispatching
|
|
11
|
+
# What the Tickets world says about filling the queue, and what the machine says about its
|
|
12
|
+
# load. The bluebook never reads the OS, so the load and the CPU count come through here.
|
|
13
|
+
class Settings
|
|
14
|
+
# The world verb naming the areas and aggregates whose persisted shape may not move.
|
|
15
|
+
FREEZE = "frozen_shapes"
|
|
16
|
+
|
|
17
|
+
# The world verb that carries the highest 1-minute load a session may be started under.
|
|
18
|
+
MAX_LOAD = "dispatch_max_load"
|
|
19
|
+
|
|
20
|
+
# The world verb that carries what every session starts with.
|
|
21
|
+
SESSION = "session_environment"
|
|
22
|
+
|
|
23
|
+
# Minutes a started row may run when the caller names no budget.
|
|
24
|
+
BUDGET_MINUTES = 90
|
|
25
|
+
|
|
26
|
+
# What `uptime` prints before the 1-minute load, on macOS and Linux.
|
|
27
|
+
UPTIME_LOAD = /load averages?:\s*([0-9]+[.,][0-9]+)/
|
|
28
|
+
|
|
29
|
+
# @param registry [Runtime::Registry, nil] the booted registry whose Tickets world is read
|
|
30
|
+
# @param load [#call, nil] answers the 1-minute load average; the machine's when nil
|
|
31
|
+
# @param cpus [Integer, nil] the CPU count; the machine's when nil
|
|
32
|
+
def initialize(registry, load: nil, cpus: nil)
|
|
33
|
+
@registry = registry
|
|
34
|
+
@load = load || -> { self.class.uptime_load }
|
|
35
|
+
@cpus = cpus || Etc.nprocessors
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Ruby's `Etc` has no load average, so the 1-minute figure is read from `uptime`.
|
|
39
|
+
#
|
|
40
|
+
# @param text [String, nil] what `uptime` printed; the machine's when nil
|
|
41
|
+
# @return [Float] the 1-minute load, 0.0 when `uptime` says none
|
|
42
|
+
def self.uptime_load(text = nil)
|
|
43
|
+
text ||= Shell.new.capture("uptime").out
|
|
44
|
+
text[UPTIME_LOAD, 1].to_s.tr(",", ".").to_f
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [Array<String>] the frozen areas and aggregates, empty when none is declared
|
|
48
|
+
def frozen = Array(declared(FREEZE)[:areas]).map(&:to_s)
|
|
49
|
+
|
|
50
|
+
# @return [Float] the 1-minute load average now
|
|
51
|
+
def load = @load.call.to_f
|
|
52
|
+
|
|
53
|
+
# @return [Integer] the CPU count
|
|
54
|
+
attr_reader :cpus
|
|
55
|
+
|
|
56
|
+
# @return [Float] the load above which no session is started: the world's, else the CPU count
|
|
57
|
+
def max_load = (declared(MAX_LOAD)[:limit] || @cpus).to_f
|
|
58
|
+
|
|
59
|
+
# @return [Integer] the cap on started rows
|
|
60
|
+
def cap = WorkLimits.cap(@registry)
|
|
61
|
+
|
|
62
|
+
# @return [Integer, nil] the most spec files a session may run per call, from the Hecks
|
|
63
|
+
# world's `test_scope` setting; nil when none is declared
|
|
64
|
+
def spec_files_limit = Codebase::TestScope.limit(@registry)
|
|
65
|
+
|
|
66
|
+
# @return [Hash{String => String}] the environment every dispatched session starts with
|
|
67
|
+
def session_environment
|
|
68
|
+
dir = declared(SESSION)[:cargo_target_dir]
|
|
69
|
+
dir ? { "CARGO_TARGET_DIR" => File.expand_path(dir.to_s) } : {}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @return [Integer, nil] the `nice` increment for a session's processes, nil for none
|
|
73
|
+
def nice = declared(SESSION)[:nice]
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def declared(verb) = @registry&.world("Tickets")&.for_verb(verb) || {}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class Dispatching
|
|
6
|
+
# Settles the started rows whose sessions have ended: asks each running session how it is, then
|
|
7
|
+
# finishes the row of one that ended `done` and yields the row of one that ended any other way,
|
|
8
|
+
# with the condition as the reason. A session still working is left alone.
|
|
9
|
+
class Settler
|
|
10
|
+
# @param rows [Rows] where the started rows and the runs are read
|
|
11
|
+
# @param launcher [Launcher] runs the commands that check, finish and yield
|
|
12
|
+
def initialize(rows, launcher)
|
|
13
|
+
@rows = rows
|
|
14
|
+
@launcher = launcher
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @return [Array<String>] one line for each row settled, empty when none was
|
|
18
|
+
def call
|
|
19
|
+
checkable.each_key { |key| @launcher.check(key) }
|
|
20
|
+
ended.map { |key, run| settle(key, run[:condition]) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def settle(key, condition)
|
|
26
|
+
condition == "done" ? @launcher.finish(key) : @launcher.yield_back(key, "its session ended #{condition}")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def checkable = mine.select { |_key, run| run[:status] == "started" }
|
|
30
|
+
|
|
31
|
+
def ended = mine.select { |_key, run| run[:status] == "finished" }
|
|
32
|
+
|
|
33
|
+
def mine
|
|
34
|
+
started = @rows.started.map(&:key)
|
|
35
|
+
@rows.runs.slice(*started)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Required by name, not relative to this file: a fuzz or model check boots a copy of this directory,
|
|
2
|
+
# and the implementation must load once, from `lib/`, not from the copy.
|
|
3
|
+
require "hecks/hecks/adapters/dispatching"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "Dispatching" do
|
|
6
|
+
port "Dispatching"
|
|
7
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "console_capture"
|
|
4
|
+
require_relative "dispatching/settings"
|
|
5
|
+
require_relative "dispatching/rows"
|
|
6
|
+
require_relative "dispatching/plan"
|
|
7
|
+
require_relative "dispatching/launcher"
|
|
8
|
+
require_relative "dispatching/settler"
|
|
9
|
+
|
|
10
|
+
module Hecks
|
|
11
|
+
module Adapters
|
|
12
|
+
# The `Dispatching` port's adapter for `Dispatch`: reads the Work queue and the machine, says which
|
|
13
|
+
# planned rows would start a session and why each other waits, and with `confirm` starts them.
|
|
14
|
+
#
|
|
15
|
+
# It decides only what the Plan rules decide; whether a row may start is still the bluebook's
|
|
16
|
+
# (the `WorkAreas` and `WorkLimits` ports refuse a start that clashes or goes over the cap). The
|
|
17
|
+
# default is a dry run, which writes nothing.
|
|
18
|
+
class Dispatching
|
|
19
|
+
# @param registry [Runtime::Registry, nil] the booted registry whose rows are read
|
|
20
|
+
# @param aggregate [Object, nil] unused
|
|
21
|
+
# @param settings [Hash] `load:`, `cpus:` and `runner:` stand in for the machine and the launcher
|
|
22
|
+
# @param root [String, nil] unused
|
|
23
|
+
def initialize(registry: nil, aggregate: nil, settings: {}, root: nil)
|
|
24
|
+
@registry = registry
|
|
25
|
+
@standins = settings
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Says which planned rows start now, and starts them when confirmed.
|
|
29
|
+
#
|
|
30
|
+
# @param held [Hash] the `Dispatch` record: `repo`, `budget_minutes`, `confirm`
|
|
31
|
+
# @return [Hash{Symbol => Hash}] `report:` the load, the rows started or that would be, and the
|
|
32
|
+
# rows left waiting with the reason
|
|
33
|
+
def choose(**held)
|
|
34
|
+
plan = plan_for
|
|
35
|
+
lines = [header(plan)] + plan.chosen.map { |row| chosen_line(row) } + plan.skipped.map { |skip| skipped_line(skip) }
|
|
36
|
+
lines += launch(plan, held) if plain(held[:confirm]) == true
|
|
37
|
+
{ report: { value: lines.join("\n") } }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Checks every started session and settles the row of each that ended: done finishes it.
|
|
41
|
+
#
|
|
42
|
+
# @param held [Hash] the `Dispatch` record: `repo`
|
|
43
|
+
# @return [Hash{Symbol => Hash}] `report:` one line per row settled
|
|
44
|
+
def conclude(**held)
|
|
45
|
+
lines = Settler.new(rows, launcher_for(held)).call
|
|
46
|
+
{ report: { value: lines.empty? ? "nothing to settle" : lines.join("\n") } }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def rows = @standins[:rows] || Rows.new(@registry)
|
|
52
|
+
|
|
53
|
+
def machine = Settings.new(@registry, load: @standins[:load], cpus: @standins[:cpus])
|
|
54
|
+
|
|
55
|
+
def launcher_for(held) = Launcher.new(plain(held[:repo]), runner: @standins[:runner])
|
|
56
|
+
|
|
57
|
+
def plan_for
|
|
58
|
+
Plan.new(rows.planned, rows.started, cap: machine.cap, load: machine.load, max_load: machine.max_load,
|
|
59
|
+
frozen: machine.frozen)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def header(plan)
|
|
63
|
+
"#{load_line}; cap #{machine.cap}, #{rows.started.size} started; frozen: #{frozen_line}; #{plan.chosen.size} to start"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def load_line = "load #{machine.load.round(1)} (limit #{machine.max_load.round(1)}, #{machine.cpus} cpus)"
|
|
67
|
+
|
|
68
|
+
def frozen_line = machine.frozen.empty? ? "none" : machine.frozen.join(", ")
|
|
69
|
+
|
|
70
|
+
def chosen_line(row) = "would start #{row.key}: #{BriefText.new("outcome" => row.title).first_line}"
|
|
71
|
+
|
|
72
|
+
def skipped_line(skip) = "#{skip.key} #{skip.reason}"
|
|
73
|
+
|
|
74
|
+
def launch(plan, held)
|
|
75
|
+
launcher = launcher_for(held)
|
|
76
|
+
minutes = plain(held[:budget_minutes]) || Settings::BUDGET_MINUTES
|
|
77
|
+
plan.chosen.each_with_index.map do |row, index|
|
|
78
|
+
launcher.launch(row, held: holding(plan, index), frozen: machine.frozen, minutes: minutes,
|
|
79
|
+
limit: machine.spec_files_limit)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# A line for each other row, started or chosen before this one, that holds an area.
|
|
84
|
+
def holding(plan, index)
|
|
85
|
+
(rows.started + plan.chosen.first(index)).reject { |other| other.area.empty? }.map { |other| held_line(other) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def held_line(row) = "#{row.key}: #{row.title} (#{row.area.join(", ")})"
|
|
89
|
+
|
|
90
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class DoctorReading
|
|
6
|
+
# Formats the checks: one line each, the fix beneath any check that is not ok.
|
|
7
|
+
module Report
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def render(rows)
|
|
11
|
+
lines = rows.map { |name, status, detail, fix| line(name, status, detail, fix) }
|
|
12
|
+
(lines + ["status: #{worst(rows)}"]).join("\n")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def worst(rows)
|
|
16
|
+
statuses = rows.map { |row| row[1] }
|
|
17
|
+
statuses.max_by { |status| %i[ok warn fail].index(status) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def line(name, status, detail, fix)
|
|
21
|
+
head = format("%<state>-5s %<name>-16s %<detail>s", state: status.to_s.upcase, name: name, detail: detail)
|
|
22
|
+
fix ? "#{head}\n fix: #{fix}" : head
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Required by name, not relative to this file: a fuzz or model check boots a copy of this directory,
|
|
2
|
+
# and the implementation must load once, from `lib/`, not from the copy.
|
|
3
|
+
require "hecks/hecks/adapters/doctor_reading"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "DoctorReading" do
|
|
6
|
+
port "Doctor"
|
|
7
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hecks"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "uri"
|
|
6
|
+
require_relative "doctor_reading/report"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
# The `Doctor` port's adapter for `Checkout`: one line per check of whether this copy can run
|
|
11
|
+
# Hecks here, each with the fix when it is not ok. It reads and never writes: it does not boot
|
|
12
|
+
# a domain (a boot can mint an era), write to a store, or call GitHub.
|
|
13
|
+
class DoctorReading
|
|
14
|
+
include Report
|
|
15
|
+
|
|
16
|
+
# The channel a rust-toolchain.toml pins.
|
|
17
|
+
FIRST_LINE = /\A[^\n]*/
|
|
18
|
+
|
|
19
|
+
CHANNEL_PIN = /channel\s*=\s*"([^"]+)"/
|
|
20
|
+
|
|
21
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
22
|
+
#
|
|
23
|
+
# @param aggregate [Object, nil] unused
|
|
24
|
+
# @param settings [Hash] unused
|
|
25
|
+
# @param root [String, nil] unused
|
|
26
|
+
def initialize(aggregate: nil, settings: {}, root: nil); end
|
|
27
|
+
|
|
28
|
+
# @param held [Hash] `domain`, a checkout directory (the current directory when absent)
|
|
29
|
+
# @return [Hash{Symbol => String}] `text:` one line per check and the overall status
|
|
30
|
+
def doctor(**held)
|
|
31
|
+
directory = plain(held[:domain]) || Dir.pwd
|
|
32
|
+
rows = [overlays(directory), worktree(directory), toolchain(directory),
|
|
33
|
+
database(directory), version(directory)]
|
|
34
|
+
{ text: render(rows) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# Each row is [name, status, detail, fix], where status is :ok, :warn or :fail.
|
|
40
|
+
def overlays(directory)
|
|
41
|
+
files = overlay_files(directory)
|
|
42
|
+
bad = files.filter_map { |path| (error = syntax_error(path)) && [File.basename(path), error] }
|
|
43
|
+
return row("overlay files", :ok, "#{files.size} read") if bad.empty?
|
|
44
|
+
|
|
45
|
+
name, error = bad.first
|
|
46
|
+
row("overlay files", :fail, "#{name} does not parse: #{error}", "fix the syntax in #{name}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def overlay_files(directory)
|
|
50
|
+
[directory, Dir.pwd].uniq.flat_map { |where| Dir[File.join(where, "*.local.{world,hecksagon}")] }.uniq
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The first line of a compile error, or nil when the file is valid Ruby. Compiling never runs it.
|
|
54
|
+
def syntax_error(path)
|
|
55
|
+
RubyVM::InstructionSequence.compile(File.read(path), path)
|
|
56
|
+
nil
|
|
57
|
+
rescue SyntaxError => e
|
|
58
|
+
first_line(e)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def worktree(directory)
|
|
62
|
+
out, status = Open3.capture2e("git", "-C", directory, "rev-parse", "--git-dir", "--git-common-dir")
|
|
63
|
+
return row("worktree", :warn, "not a git checkout", "run from a hecks checkout") unless status.success?
|
|
64
|
+
|
|
65
|
+
git_dir, common = out.lines.map(&:strip)
|
|
66
|
+
return row("worktree", :ok, "main checkout") if git_dir == common
|
|
67
|
+
|
|
68
|
+
unseen_overlays(directory, File.dirname(File.expand_path(common, directory)))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def unseen_overlays(directory, main)
|
|
72
|
+
here = Dir[File.join(directory, "lib/hecks/hecks/*.local.*")]
|
|
73
|
+
there = Dir[File.join(main, "lib/hecks/hecks/*.local.*")]
|
|
74
|
+
return row("worktree", :ok, "linked worktree sees the main checkout's overlays") if here.any? || there.empty?
|
|
75
|
+
|
|
76
|
+
row("worktree", :warn, "linked worktree cannot see #{there.size} overlay file(s) in #{main}",
|
|
77
|
+
"run from #{main}")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def toolchain(directory)
|
|
81
|
+
pin = File.read(File.join(directory, "rust-toolchain.toml"))[CHANNEL_PIN, 1]
|
|
82
|
+
installed = rustc_version
|
|
83
|
+
return row("toolchain", :warn, "rustc not on PATH", "install the pinned toolchain with rustup") unless installed
|
|
84
|
+
return row("toolchain", :ok, installed) if pin && installed.include?(pin)
|
|
85
|
+
|
|
86
|
+
row("toolchain", :warn, "installed #{installed}, pinned #{pin || "none"}", "rustup toolchain install #{pin}")
|
|
87
|
+
rescue Errno::ENOENT
|
|
88
|
+
row("toolchain", :warn, "no rust-toolchain.toml here", "run from a hecks checkout")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def rustc_version
|
|
92
|
+
out, status = Open3.capture2e("rustc", "--version")
|
|
93
|
+
status.success? ? out.strip : nil
|
|
94
|
+
rescue Errno::ENOENT
|
|
95
|
+
nil
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# The default store of the domain at this directory, checked without booting it.
|
|
99
|
+
def database(directory)
|
|
100
|
+
registry = Hecks.describe(directory).registry
|
|
101
|
+
store(registry, registry.first_domain_name)
|
|
102
|
+
rescue StandardError, ScriptError => e
|
|
103
|
+
row("store", :warn, "could not be read: #{first_line(e)}", "fix the overlay files first")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# The default store of one domain: Memory, a file store, or a Postgres database to reach.
|
|
107
|
+
def store(registry, name)
|
|
108
|
+
adapter = registry.default_adapter_for(name)
|
|
109
|
+
return row("store", :ok, "Memory") if adapter.nil? || adapter.to_s == "Memory"
|
|
110
|
+
|
|
111
|
+
url = registry.default_database_for(name)
|
|
112
|
+
return reach(url) if url.to_s.start_with?("postgres")
|
|
113
|
+
|
|
114
|
+
file_store(adapter.to_s, url)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A file store is usable when its directory exists; the file itself is made on first write.
|
|
118
|
+
def file_store(adapter, path)
|
|
119
|
+
return row("store", :ok, adapter) if path.nil?
|
|
120
|
+
|
|
121
|
+
dir = File.dirname(path.to_s)
|
|
122
|
+
return row("store", :ok, "#{adapter}, #{path}") if File.directory?(dir)
|
|
123
|
+
|
|
124
|
+
row("store", :fail, "#{adapter} directory #{dir} is missing", "mkdir -p #{dir}")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Postgres reachable, and the role the URL names exists; a read of the catalog, nothing written.
|
|
128
|
+
def reach(url)
|
|
129
|
+
require "pg"
|
|
130
|
+
PG.connect(url, connect_timeout: 3) { |conn| role_row(conn, URI.parse(url).user) }
|
|
131
|
+
rescue LoadError
|
|
132
|
+
row("store", :warn, "pg gem not loaded, so postgres was not tested", "bundle install")
|
|
133
|
+
rescue PG::Error => e
|
|
134
|
+
row("store", :fail, "postgres unreachable: #{first_line(e)}", "start postgres")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def role_row(conn, role)
|
|
138
|
+
exists = conn.exec_params("select 1 from pg_roles where rolname = $1", [role]).ntuples.positive?
|
|
139
|
+
return row("store", :ok, "postgres answers, role #{role} exists") if exists
|
|
140
|
+
|
|
141
|
+
row("store", :fail, "postgres answers, role #{role} is missing", "create the role: createuser #{role}")
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def version(directory)
|
|
145
|
+
ahead, status = Open3.capture2e("git", "-C", directory, "rev-list", "--count", "origin/main..main")
|
|
146
|
+
base = "hecks #{Hecks::VERSION}"
|
|
147
|
+
return row("version", :ok, base) unless status.success? && ahead.to_i.positive?
|
|
148
|
+
|
|
149
|
+
row("version", :warn, "#{base}, local main #{ahead.strip} commit(s) ahead of origin/main", "push when ready")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def row(name, status, detail, fix = nil) = [name, status, detail, fix]
|
|
153
|
+
|
|
154
|
+
def first_line(error)
|
|
155
|
+
error.message[FIRST_LINE].to_s.strip
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -63,7 +63,7 @@ module Hecks
|
|
|
63
63
|
# @param held [Hash] `checkout`; `range` (default: the last 20 commits)
|
|
64
64
|
# @return [Hash{Symbol => String}] `text:` the commits
|
|
65
65
|
# @raise [Runtime::NotFound] when the checkout or the range is not found
|
|
66
|
-
def
|
|
66
|
+
def history(**held)
|
|
67
67
|
answering(held) do
|
|
68
68
|
range = plain(held[:range])
|
|
69
69
|
read("log", "--format=%h %s", *(range ? [checked_range(range)] : ["-n", RECENT.to_s]))
|