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,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/git_commit"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "GitCommit" do
|
|
6
|
+
port "Committing"
|
|
7
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "git_worktrees"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
# The `Committing` port's adapter for `Commit`: stages the named paths, then commits what is
|
|
8
|
+
# staged under the message, on the branch the checkout is on.
|
|
9
|
+
#
|
|
10
|
+
# It never pushes, never amends, never forces, and never commits onto `main`: that goes through
|
|
11
|
+
# `Landing`, and a push goes through `PushTrain`. A commit with nothing staged is declined.
|
|
12
|
+
class GitCommit
|
|
13
|
+
include GitWorktrees
|
|
14
|
+
|
|
15
|
+
# Accepts the arguments every driven adapter is built with and keeps none of them.
|
|
16
|
+
#
|
|
17
|
+
# @param aggregate [Object, nil] unused
|
|
18
|
+
# @param settings [Hash] unused
|
|
19
|
+
# @param root [String, nil] unused
|
|
20
|
+
def initialize(aggregate: nil, settings: {}, root: nil)
|
|
21
|
+
@git = Git.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Commits what is staged in a checkout, after staging the named paths when there are some.
|
|
25
|
+
#
|
|
26
|
+
# @param held [Hash] the `Commit` record: `checkout` (a directory inside the worktree; the
|
|
27
|
+
# current directory when absent), `message`, and `paths` (whitespace-separated, optional)
|
|
28
|
+
# @return [Hash{Symbol => Hash}] `sha:` the commit made, `report:` what it says
|
|
29
|
+
# @raise [ConsoleCapture::Failure] on an empty message, a commit onto `main`, nothing staged,
|
|
30
|
+
# or a directory outside a repository
|
|
31
|
+
def commit(**held)
|
|
32
|
+
settle(held)
|
|
33
|
+
message = plain(held[:message]).to_s.strip
|
|
34
|
+
raise ConsoleCapture::Failure, "a commit needs a message" if message.empty?
|
|
35
|
+
|
|
36
|
+
branch = current_branch
|
|
37
|
+
raise ConsoleCapture::Failure, "a commit onto main goes through Landing" if branch == "main"
|
|
38
|
+
|
|
39
|
+
stage(plain(held[:paths]))
|
|
40
|
+
refuse_nothing_staged
|
|
41
|
+
read("commit", "-m", message)
|
|
42
|
+
sha = read("rev-parse", "--short", "HEAD")
|
|
43
|
+
{ sha: { value: sha }, report: { value: "committed #{sha} on #{branch}" } }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# Stages each named path; `--` keeps a path from being read as an option.
|
|
49
|
+
def stage(paths)
|
|
50
|
+
names = paths.to_s.split
|
|
51
|
+
read("add", "--", *names) unless names.empty?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def refuse_nothing_staged
|
|
55
|
+
return unless read("diff", "--cached", "--name-only").empty?
|
|
56
|
+
|
|
57
|
+
raise ConsoleCapture::Failure, "nothing is staged to commit"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../git_worktrees"
|
|
4
|
+
require_relative "../git_main_pull"
|
|
5
|
+
require_relative "../shell"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
class GitLanding
|
|
10
|
+
# The steps before a landing that an agent used to run by hand: refuse unsaved work, rebase the
|
|
11
|
+
# branch onto local `main`, and run the quick gate in the branch's worktree.
|
|
12
|
+
#
|
|
13
|
+
# Each step refuses by name at the first failure, with the reason, and leaves the branch as it
|
|
14
|
+
# was: a rebase that conflicts is aborted. The landing itself and the tidy after it are
|
|
15
|
+
# {GitLanding#merge}'s.
|
|
16
|
+
class Finisher
|
|
17
|
+
include GitWorktrees
|
|
18
|
+
include GitMainPull
|
|
19
|
+
|
|
20
|
+
# The command that runs the seconds-long checks in a worktree.
|
|
21
|
+
GATE = %w[exe/hecks gate_run.gate! stage=quick --wait].freeze
|
|
22
|
+
|
|
23
|
+
# What a completed gate run prints.
|
|
24
|
+
COMPLETED = /"status":\s*"completed"/
|
|
25
|
+
|
|
26
|
+
# @param git [Git] the adapter every git call goes through
|
|
27
|
+
# @param checkout [String] the worktree the branch is checked out in
|
|
28
|
+
# @param branch [String] the branch to finish
|
|
29
|
+
# @param onto [String] the branch to rebase onto
|
|
30
|
+
# @param gate [#call] answers the {Shell::Result} of the quick gate run in a directory
|
|
31
|
+
def initialize(git, checkout, branch:, onto:, gate: nil)
|
|
32
|
+
@git = git
|
|
33
|
+
@checkout = checkout
|
|
34
|
+
@branch = ref(branch)
|
|
35
|
+
@onto = ref(onto)
|
|
36
|
+
@gate = gate || ->(dir) { Shell.new.capture(*GATE, chdir: dir) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Refuses unsaved work, pulls `main` when it is the target, rebases and runs the gate.
|
|
40
|
+
#
|
|
41
|
+
# @return [void]
|
|
42
|
+
# @raise [ConsoleCapture::Failure] naming the step that failed: unsaved work, conflict or
|
|
43
|
+
# gate red
|
|
44
|
+
def prepare
|
|
45
|
+
refuse_unsaved
|
|
46
|
+
pull_main if @onto == "main"
|
|
47
|
+
rebase
|
|
48
|
+
run_gate
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def refuse_unsaved
|
|
54
|
+
changed = dirty(@checkout)
|
|
55
|
+
raise ConsoleCapture::Failure, "unsaved work: #{@checkout} holds #{changed.join(", ")}" unless changed.empty?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def rebase
|
|
59
|
+
result = @git.capture("rebase", @onto, chdir: @checkout)
|
|
60
|
+
return if result.ok?
|
|
61
|
+
|
|
62
|
+
conflicts = @git.capture("diff", "--name-only", "--diff-filter=U", chdir: @checkout).out.split
|
|
63
|
+
@git.capture("rebase", "--abort", chdir: @checkout)
|
|
64
|
+
raise ConsoleCapture::Failure,
|
|
65
|
+
"conflict: rebasing #{@branch} onto #{@onto} conflicts in #{conflicts.join(", ")}; nothing changed"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def run_gate
|
|
69
|
+
result = @gate.call(@checkout)
|
|
70
|
+
return if result.ok? && result.out.match?(COMPLETED)
|
|
71
|
+
|
|
72
|
+
raise ConsoleCapture::Failure, "gate red: the quick gate failed in #{@checkout}: #{tail(result)}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def tail(result)
|
|
76
|
+
lines = result.out.lines.last(5)
|
|
77
|
+
lines.join.strip
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "open3"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
class GitLanding
|
|
9
|
+
# A landing in flight that holds no ticket: the shell lock directory old briefs make with
|
|
10
|
+
# `mkdir`, and the claim file landers of an older build write.
|
|
11
|
+
#
|
|
12
|
+
# The head of the line waits for either to go. A directory has no wake-up event, so this is
|
|
13
|
+
# the
|
|
14
|
+
# one place a wait looks again on a timer. A shell lock that one of the caller's own ancestor
|
|
15
|
+
# processes names on its command line is the caller's, so it never blocks the call that
|
|
16
|
+
# holds it.
|
|
17
|
+
class ForeignHold
|
|
18
|
+
# Seconds between looks at the lock.
|
|
19
|
+
LOOK = 2
|
|
20
|
+
|
|
21
|
+
# The shell lock directories that guard landings in a repository: the one the world names,
|
|
22
|
+
# and
|
|
23
|
+
# the job's own `land.lock`, which guards only the repository this code runs from.
|
|
24
|
+
#
|
|
25
|
+
# @param git_dir [String] the main checkout's git directory of the repository being landed
|
|
26
|
+
# in
|
|
27
|
+
# @param named [String, nil] the world's `shell_lock`
|
|
28
|
+
# @return [Array<String>] the directories to honour
|
|
29
|
+
def self.locks(git_dir, named)
|
|
30
|
+
job = ENV.fetch("CLAUDE_JOB_DIR", "")
|
|
31
|
+
own = File.join(job, "tmp", "land.lock") if !job.empty? && home?(git_dir)
|
|
32
|
+
[named, own].compact
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Boolean] whether a git directory is the repository this code is checked out from
|
|
36
|
+
def self.home?(git_dir)
|
|
37
|
+
out, status = Open3.capture2("git", "rev-parse", "--path-format=absolute", "--git-common-dir", chdir: __dir__)
|
|
38
|
+
status.success? && File.realpath(out.strip) == File.realpath(git_dir)
|
|
39
|
+
rescue SystemCallError
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param legacy [String] the claim file the front ticket feeds
|
|
44
|
+
# @param locks [Array<String>] shell lock directories
|
|
45
|
+
# @param stale [Numeric] seconds after which either is taken to be abandoned
|
|
46
|
+
# @param mine [#call] answers whether a lock path is the caller's own
|
|
47
|
+
def initialize(legacy, locks:, stale:, mine: method(:ancestor_names?))
|
|
48
|
+
@legacy = legacy
|
|
49
|
+
@locks = locks
|
|
50
|
+
@stale = stale
|
|
51
|
+
@mine = mine
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @param token [String] the name of the caller's own ticket, whose claim file it fed itself
|
|
55
|
+
# @return [String, nil] a sentence naming what holds the landing, nil when nothing does
|
|
56
|
+
def holder(token)
|
|
57
|
+
lock = @locks.find { |path| fresh?(path) && !@mine.call(path) }
|
|
58
|
+
return "the shell lock #{lock}" if lock
|
|
59
|
+
|
|
60
|
+
claim = fresh_claim(token)
|
|
61
|
+
"#{claim["branch"]}, landing by an older build" if claim
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Looks every few seconds until nothing holds the landing, or the budget runs out.
|
|
65
|
+
#
|
|
66
|
+
# @param token [String] the caller's ticket
|
|
67
|
+
# @param budget [#call] seconds the caller may still wait
|
|
68
|
+
# @param say [#call] told what is being waited for, once
|
|
69
|
+
# @return [Boolean] false when the budget ran out first
|
|
70
|
+
def clears_within?(token, budget, say)
|
|
71
|
+
said = nil
|
|
72
|
+
while (held = holder(token))
|
|
73
|
+
return false if budget.call <= 0
|
|
74
|
+
|
|
75
|
+
say.call("waiting for #{held}") unless said == held
|
|
76
|
+
said = held
|
|
77
|
+
sleep([LOOK, budget.call].min)
|
|
78
|
+
end
|
|
79
|
+
true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def fresh?(path) = File.exist?(path) && Time.now - File.mtime(path) < @stale
|
|
85
|
+
|
|
86
|
+
def fresh_claim(token)
|
|
87
|
+
return unless fresh?(@legacy)
|
|
88
|
+
|
|
89
|
+
claim = JSON.parse(File.read(@legacy))
|
|
90
|
+
claim unless claim["token"] == token
|
|
91
|
+
rescue JSON::ParserError
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Whether a process above this one has the path on its command line.
|
|
96
|
+
def ancestor_names?(path)
|
|
97
|
+
pid = Process.ppid
|
|
98
|
+
40.times do
|
|
99
|
+
out, = Open3.capture2("ps", "-o", "ppid=,command=", "-p", pid.to_s)
|
|
100
|
+
parent, command = out.strip.split(" ", 2)
|
|
101
|
+
return true if command.to_s.include?(path)
|
|
102
|
+
return false if parent.to_i <= 1
|
|
103
|
+
|
|
104
|
+
pid = parent.to_i
|
|
105
|
+
end
|
|
106
|
+
false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
require_relative "ticket"
|
|
6
|
+
require_relative "numbering"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Adapters
|
|
10
|
+
class GitLanding
|
|
11
|
+
# The landing line of one repository: ticket files in `queue/` under the main checkout's git
|
|
12
|
+
# directory, numbered by a counter that only grows, so first come is first served across
|
|
13
|
+
# processes. The ticket at the front holds the one place to land.
|
|
14
|
+
#
|
|
15
|
+
# Every read or change of the line happens inside an `flock` on a guard file. The front
|
|
16
|
+
# ticket
|
|
17
|
+
# feeds the legacy claim file, which landers that still read it keep honouring.
|
|
18
|
+
class Line
|
|
19
|
+
# What a look at the line finds ahead of a ticket.
|
|
20
|
+
#
|
|
21
|
+
# @!attribute [r] ahead
|
|
22
|
+
# @return [Array<Ticket>] the live tickets in front, in order
|
|
23
|
+
# @!attribute [r] notes
|
|
24
|
+
# @return [Array<String>] the abandoned tickets removed on the way
|
|
25
|
+
Standing = Struct.new(:ahead, :notes)
|
|
26
|
+
|
|
27
|
+
# The minutes without a heartbeat after which a ticket is abandoned, when no setting names
|
|
28
|
+
# another.
|
|
29
|
+
DEFAULT_STALE_MINUTES = 30
|
|
30
|
+
|
|
31
|
+
# @param git_dir [String] the main checkout's git directory
|
|
32
|
+
# @param stale_minutes [Numeric, nil] the heartbeat window; the default when nil
|
|
33
|
+
# @param clock [#call] answers the current Time
|
|
34
|
+
# @param heartbeat [Numeric] seconds between a holder's heartbeats
|
|
35
|
+
def initialize(git_dir, stale_minutes: nil, clock: -> { Time.now }, heartbeat: 15)
|
|
36
|
+
@git_dir = git_dir
|
|
37
|
+
@root = File.join(git_dir, "hecks-landing")
|
|
38
|
+
@dir = File.join(@root, "queue")
|
|
39
|
+
@stale = (stale_minutes || DEFAULT_STALE_MINUTES).to_f * 60
|
|
40
|
+
@clock = clock
|
|
41
|
+
@heartbeat = heartbeat
|
|
42
|
+
@numbers = Numbering.new(@dir, @root)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Takes the next place in the line.
|
|
46
|
+
#
|
|
47
|
+
# @param branch [String] the branch the ticket stands for
|
|
48
|
+
# @param jump [Boolean] take the place right behind the front ticket, ahead of those
|
|
49
|
+
# waiting
|
|
50
|
+
# @param details [Hash] more for the ticket to record: `checkout`, `onto`, `ready`
|
|
51
|
+
# @return [Ticket] the ticket, locked and beating
|
|
52
|
+
def join(branch, jump: false, **details)
|
|
53
|
+
guarded do
|
|
54
|
+
record = details.merge(branch: branch, pid: Process.pid, at: now.to_f)
|
|
55
|
+
ticket = Ticket.create(@numbers.path(tickets, branch, jump, now), record)
|
|
56
|
+
ticket.beat(now)
|
|
57
|
+
ticket.beat_every(@heartbeat, @clock)
|
|
58
|
+
ticket
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Looks at the tickets in front of one, removing any that were abandoned: its process is
|
|
63
|
+
# gone,
|
|
64
|
+
# or it holds the lock but has not beaten for the stale window.
|
|
65
|
+
#
|
|
66
|
+
# @param ticket [Ticket] the ticket asking
|
|
67
|
+
# @return [Standing] the live tickets ahead and the sentences about the abandoned ones
|
|
68
|
+
def standing(ticket)
|
|
69
|
+
guarded do
|
|
70
|
+
ahead = tickets.select { |other| other.sequence < ticket.sequence }.map { |other| [other, lapse(other)] }
|
|
71
|
+
notes = ahead.filter_map { |other, why| supersede(other, why) if why }
|
|
72
|
+
Standing.new(ahead.reject { |_, why| why }.map(&:first), notes)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Makes a ticket the holder: stamps the time it began and feeds the legacy claim.
|
|
77
|
+
#
|
|
78
|
+
# @param ticket [Ticket] the ticket at the front
|
|
79
|
+
# @return [void]
|
|
80
|
+
def promote(ticket)
|
|
81
|
+
guarded do
|
|
82
|
+
ticket.update(turn_at: now.to_f)
|
|
83
|
+
File.write(legacy, JSON.generate(token: ticket.name, branch: ticket.data[:branch], pid: Process.pid, at: now.to_f))
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Gives a ticket up: closes it, deletes its files, and clears the legacy claim when it fed
|
|
88
|
+
# it.
|
|
89
|
+
#
|
|
90
|
+
# @param ticket [Ticket] the ticket
|
|
91
|
+
# @return [void]
|
|
92
|
+
def leave(ticket)
|
|
93
|
+
guarded do
|
|
94
|
+
File.delete(legacy) if fed_by?(ticket)
|
|
95
|
+
ticket.close
|
|
96
|
+
ticket.remove
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# The next ticket behind one that declared itself ready and has not been settled yet.
|
|
101
|
+
#
|
|
102
|
+
# @param ticket [Ticket] the holder
|
|
103
|
+
# @return [Ticket, nil] the first such ticket
|
|
104
|
+
def next_ready(ticket)
|
|
105
|
+
guarded do
|
|
106
|
+
tickets.find { |other| other.sequence > ticket.sequence && waiting_ready?(other) }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @param data [Hash] a ticket's record
|
|
111
|
+
# @return [String] its branch and how long it has been at the front
|
|
112
|
+
def wording(data)
|
|
113
|
+
minutes = ((now.to_f - data.fetch(:turn_at) { data[:at] }.to_f) / 60).floor
|
|
114
|
+
"#{data[:branch]} (landing for #{minutes} minute#{"s" unless minutes == 1})"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @return [Float] seconds until the soonest of some tickets would go stale, at least a
|
|
118
|
+
# second
|
|
119
|
+
def stale_in(tickets)
|
|
120
|
+
[tickets.map { |held| @stale - held.silence(now) }.min.to_f, 1].max
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# @return [String] the legacy claim file
|
|
124
|
+
def legacy = File.join(@git_dir, "hecks-landing.claim")
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def now = @clock.call
|
|
129
|
+
|
|
130
|
+
def fed_by?(ticket)
|
|
131
|
+
File.exist?(legacy) && JSON.parse(File.read(legacy))["token"] == ticket.name
|
|
132
|
+
rescue JSON::ParserError
|
|
133
|
+
false
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Why a ticket is abandoned, or nil while it is alive and beating.
|
|
137
|
+
def lapse(ticket)
|
|
138
|
+
return "its process is gone" unless ticket.held?
|
|
139
|
+
|
|
140
|
+
quiet = ticket.silence(now)
|
|
141
|
+
"no heartbeat for #{(quiet / 60).floor} minutes" if quiet > @stale
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def supersede(ticket, why)
|
|
145
|
+
sentence = "superseded the abandoned landing of #{wording(ticket.data)} (#{why})"
|
|
146
|
+
File.delete(legacy) if fed_by?(ticket)
|
|
147
|
+
ticket.remove
|
|
148
|
+
sentence
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def tickets
|
|
152
|
+
names = Dir.children(@dir).grep(/#{Ticket::SUFFIX}\z/o)
|
|
153
|
+
names.sort.map { |name| Ticket.new(File.join(@dir, name)) }
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def waiting_ready?(ticket)
|
|
157
|
+
held = ticket.data
|
|
158
|
+
held[:ready] && !held[:handled] && ticket.held?
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def guarded
|
|
162
|
+
FileUtils.mkdir_p(@dir)
|
|
163
|
+
File.open(File.join(@root, "guard"), File::RDWR | File::CREAT) do |file|
|
|
164
|
+
file.flock(File::LOCK_EX)
|
|
165
|
+
yield
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "line"
|
|
4
|
+
require_relative "waiting"
|
|
5
|
+
require_relative "foreign_hold"
|
|
6
|
+
require_relative "train"
|
|
7
|
+
require_relative "../console_capture"
|
|
8
|
+
require_relative "../../../indifferent_key"
|
|
9
|
+
|
|
10
|
+
module Hecks
|
|
11
|
+
module Adapters
|
|
12
|
+
class GitLanding
|
|
13
|
+
# A landing's way through the line: a ticket in order, a wait for the front, the landing
|
|
14
|
+
# itself,
|
|
15
|
+
# then the ticket given back; or a train that settles the tickets behind it.
|
|
16
|
+
#
|
|
17
|
+
# The limits come from the world's `landing "Queue", stale_minutes: n, wait_minutes: n`; the
|
|
18
|
+
# `tune` hash overrides any of them (`stale_minutes`, `wait_minutes`, `heartbeat`, `clock`,
|
|
19
|
+
# `say`,
|
|
20
|
+
# `locks`, `mine`, `gate`).
|
|
21
|
+
class Lineup
|
|
22
|
+
# The minutes a landing waits for its turn, when no setting names another.
|
|
23
|
+
DEFAULT_WAIT_MINUTES = 40
|
|
24
|
+
|
|
25
|
+
# @param git_dir [String] the main checkout's git directory
|
|
26
|
+
# @param setting [Hash, nil] the world's `landing` setting
|
|
27
|
+
# @param tune [Hash] overrides of the limits and the collaborators
|
|
28
|
+
def initialize(git_dir, setting: nil, **tune)
|
|
29
|
+
@tune = { stale_minutes: read(setting, :stale_minutes), wait_minutes: read(setting, :wait_minutes),
|
|
30
|
+
locks: ForeignHold.locks(git_dir, read(setting, :shell_lock)) }.compact.merge(tune)
|
|
31
|
+
@line = Line.new(git_dir, stale_minutes: @tune[:stale_minutes], clock: @tune.fetch(:clock) { -> { Time.now } },
|
|
32
|
+
heartbeat: @tune.fetch(:heartbeat, 15))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Takes a place, waits for the front, and runs the block there; or, when a train settled
|
|
36
|
+
# the
|
|
37
|
+
# branch while it waited, answers what the train answered and runs nothing.
|
|
38
|
+
#
|
|
39
|
+
# @param branch [String] the branch to land
|
|
40
|
+
# @param onto [String] the branch it lands on
|
|
41
|
+
# @param checkout [String] the worktree it lands from
|
|
42
|
+
# @yieldparam note [String, nil] what the wait was: the place, the holder, what was
|
|
43
|
+
# superseded
|
|
44
|
+
# @return [Hash] the landing answer
|
|
45
|
+
# @raise [ConsoleCapture::Failure] when the wait runs out, or the train refused the branch
|
|
46
|
+
def stand(branch, onto:, checkout:)
|
|
47
|
+
ticket = @line.join(branch, checkout: checkout, onto: onto, ready: true)
|
|
48
|
+
turn = waiting(ticket).run
|
|
49
|
+
turn.verdict ? carried(turn) : yield(turn.note)
|
|
50
|
+
rescue Waiting::Expired => e
|
|
51
|
+
raise ConsoleCapture::Failure, "queue busy: #{branch} is not landed: #{e.message}; land again when the line clears"
|
|
52
|
+
ensure
|
|
53
|
+
@line.leave(ticket) if ticket
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Takes the front place and lands every ready branch behind it.
|
|
57
|
+
#
|
|
58
|
+
# @param git [Git] the adapter every git call goes through
|
|
59
|
+
# @param checkout [String] the repository's top level
|
|
60
|
+
# @param onto [String] the branch the train lands on
|
|
61
|
+
# @param land [#call] `(checkout, branch, onto)` lands one branch
|
|
62
|
+
# @return [String] the train's report, opened by what the wait was
|
|
63
|
+
def convoy(git, checkout, onto:, land:)
|
|
64
|
+
ticket = @line.join("train", jump: true, checkout: checkout, onto: onto, ready: false)
|
|
65
|
+
turn = waiting(ticket).run
|
|
66
|
+
crew = Train::Crew.new(@line, ticket, land, @tune.fetch(:gate, Train::QUICK_GATE))
|
|
67
|
+
[Train.new(git, checkout, crew, onto: onto).run, turn.note].compact.join("; ")
|
|
68
|
+
ensure
|
|
69
|
+
@line.leave(ticket) if ticket
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def waiting(ticket)
|
|
75
|
+
Waiting.new(@line, ticket, patience: @tune.fetch(:wait_minutes, DEFAULT_WAIT_MINUTES).to_f * 60,
|
|
76
|
+
say: @tune.fetch(:say) { ->(text) { warn(text) } }, foreign: foreign)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def foreign
|
|
80
|
+
stale = (@tune[:stale_minutes] || Line::DEFAULT_STALE_MINUTES).to_f * 60
|
|
81
|
+
options = { locks: @tune.fetch(:locks, []), stale: stale }
|
|
82
|
+
options[:mine] = @tune[:mine] if @tune[:mine]
|
|
83
|
+
ForeignHold.new(@line.legacy, **options)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def carried(turn)
|
|
87
|
+
verdict = turn.verdict
|
|
88
|
+
raise ConsoleCapture::Failure, verdict[:refused] if verdict[:refused]
|
|
89
|
+
|
|
90
|
+
said = verdict[:landed][:report][:value]
|
|
91
|
+
verdict[:landed].merge(report: { value: "#{said}; landed by the train, #{turn.note}" })
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def read(setting, key) = setting && IndifferentKey.read(setting, key)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -76,7 +76,7 @@ module Hecks
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def answer(outcome, landed, report)
|
|
79
|
-
{ outcome: { value: outcome }, checkout: { value:
|
|
79
|
+
{ outcome: { value: outcome }, checkout: { value: primary.path }, branch: { value: @branch },
|
|
80
80
|
landed: { value: landed }, report: { value: report } }
|
|
81
81
|
end
|
|
82
82
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "ticket"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class GitLanding
|
|
8
|
+
# The numbers the line's tickets are named by: a counter kept in a file that only grows, so a
|
|
9
|
+
# ticket never gets a number an earlier one had, even after the line empties.
|
|
10
|
+
#
|
|
11
|
+
# Ordinary numbers are a thousand apart, so a train can take the place right behind the
|
|
12
|
+
# front.
|
|
13
|
+
class Numbering
|
|
14
|
+
# The distance between two ordinary ticket numbers.
|
|
15
|
+
GAP = 1000
|
|
16
|
+
|
|
17
|
+
# What a branch name loses before it goes into a file name.
|
|
18
|
+
UNSAFE = /[^A-Za-z0-9._-]/
|
|
19
|
+
|
|
20
|
+
# @param dir [String] the directory the tickets live in
|
|
21
|
+
# @param root [String] the directory the counter lives in
|
|
22
|
+
def initialize(dir, root)
|
|
23
|
+
@dir = dir
|
|
24
|
+
@counter = File.join(root, "sequence")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param tickets [Array<Ticket>] the tickets in the line, in order
|
|
28
|
+
# @param branch [String] the branch the new ticket stands for
|
|
29
|
+
# @param jump [Boolean] take the place right behind the front ticket
|
|
30
|
+
# @param now [Time] the current time
|
|
31
|
+
# @return [String] the path of the new ticket's file
|
|
32
|
+
def path(tickets, branch, jump, now)
|
|
33
|
+
number = jump && tickets.first ? behind(tickets) : bump
|
|
34
|
+
name = "#{number.to_s.rjust(10, "0")}-#{branch.gsub(UNSAFE, "_")}-#{Process.pid}-#{now.to_i}#{Ticket::SUFFIX}"
|
|
35
|
+
File.join(@dir, name)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def behind(tickets)
|
|
41
|
+
taken = tickets.map(&:sequence)
|
|
42
|
+
first = tickets.first.sequence + 1
|
|
43
|
+
(first..).find { |number| !taken.include?(number) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def bump
|
|
47
|
+
count = (File.exist?(@counter) ? File.read(@counter).to_i : 0) + GAP
|
|
48
|
+
File.write(@counter, count.to_s)
|
|
49
|
+
count
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../git_worktrees"
|
|
4
|
+
require_relative "../area_overlap"
|
|
5
|
+
require_relative "../started_work"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
class GitLanding
|
|
10
|
+
# The started Work rows that hold ground a branch changes. A branch is landed for its own Work
|
|
11
|
+
# row, the one keyed by the branch name, so that row is never a rival; a landing with no row
|
|
12
|
+
# has none to clash with.
|
|
13
|
+
class Rivals
|
|
14
|
+
include GitWorktrees
|
|
15
|
+
|
|
16
|
+
# @param git [Git] the adapter every git call goes through
|
|
17
|
+
# @param checkout [String] the repository's top level
|
|
18
|
+
# @param registry [Runtime::Registry, nil] where the Work rows are read from
|
|
19
|
+
def initialize(git, checkout, registry)
|
|
20
|
+
@git = git
|
|
21
|
+
@checkout = checkout
|
|
22
|
+
@registry = registry
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param branch [String] the branch to land
|
|
26
|
+
# @param onto [String] the branch it lands on
|
|
27
|
+
# @return [String, nil] the refusal naming the row and the files, nil when none clash
|
|
28
|
+
def refusal(branch, onto)
|
|
29
|
+
files = changed(branch, onto)
|
|
30
|
+
StartedWork.rows(@registry).each do |row|
|
|
31
|
+
next if row[:key] == branch
|
|
32
|
+
|
|
33
|
+
clash = files.select { |file| claims?(row, file) }
|
|
34
|
+
return wording(branch, row, clash) unless clash.empty?
|
|
35
|
+
end
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def claims?(row, file)
|
|
42
|
+
row[:area].any? { |area| AreaOverlap.overlap?(area, file, root: @checkout, file: true) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def wording(branch, row, clash)
|
|
46
|
+
"#{branch} changes #{clash.join(", ")}, in the area of #{row[:key]} (#{row[:area].join(", ")})"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def changed(branch, onto)
|
|
50
|
+
result = @git.capture("diff", "--no-renames", "--name-only", "-z", "#{ref(onto)}...#{ref(branch)}",
|
|
51
|
+
chdir: @checkout)
|
|
52
|
+
raise ConsoleCapture::Failure, "git diff failed in #{@checkout}: #{result.err.strip}" unless result.ok?
|
|
53
|
+
|
|
54
|
+
result.out.split("\0").reject(&:empty?)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|