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,183 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "qa_era_mint"
|
|
4
|
+
require_relative "../../adapters/driven/postgres_era/lineage_manager/mint_decision"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Adapters
|
|
8
|
+
# The auto-mint rule the Maintenance mint enforces. A mint runs without the owner's confirm only
|
|
9
|
+
# when
|
|
10
|
+
# the edge leaving the held era is empty, every change in the shape diff is additive, and the
|
|
11
|
+
# rehearsal
|
|
12
|
+
# refused nothing. The rule is declared as `AutoMintAdditive` in quality_control.bluebook; this
|
|
13
|
+
# module
|
|
14
|
+
# is its check. The stranded-marker and watermark guards stay in `MainMaintenance#mint`.
|
|
15
|
+
module QaAutoMint
|
|
16
|
+
# The edge file's opening line and its closing line, with nothing between them when it is
|
|
17
|
+
# empty.
|
|
18
|
+
EDGE_HEADER = /\AHecks\.data_translation\s+"[^"]*",\s+from:\s+"[^"]*",\s+to:\s+"[^"]*"\s+do\z/
|
|
19
|
+
|
|
20
|
+
module_function
|
|
21
|
+
|
|
22
|
+
# The facts the rule reads from a ledger: its live watermark, the edge leaving its held era
|
|
23
|
+
# and that edge's text, and the verdict the shared mint decision reaches for the held era.
|
|
24
|
+
#
|
|
25
|
+
# @param ledger [String] the bluebook directory of the ledger
|
|
26
|
+
# @return [Hash] `watermark`, `from`, `to`, `edge_text`, `verdict`, `held` and `current`
|
|
27
|
+
def facts(ledger)
|
|
28
|
+
held = JournalStore::HeldDomain.open(ledger, mode: :translated)
|
|
29
|
+
registry = held.registry
|
|
30
|
+
latest, watermark = latest_era(held)
|
|
31
|
+
verdict = PostgresEra::LineageManager::MintDecision.decide_latest(
|
|
32
|
+
latest, bluebook: held.bluebook, translations: registry.translations, directory: ledger, watermark: watermark
|
|
33
|
+
)
|
|
34
|
+
{ watermark: watermark, held: held_bluebook(latest), current: held.bluebook, verdict: verdict }
|
|
35
|
+
.merge(edge_facts(held, ledger, latest[:label]))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Array(Hash, Integer)] the latest held era and the live watermark, read from its
|
|
39
|
+
# database
|
|
40
|
+
def latest_era(held)
|
|
41
|
+
db = PostgresEra.connect_for(held.domain_name, held.settings)
|
|
42
|
+
lineage = PostgresEra::Lineage.new(db, held.domain_name)
|
|
43
|
+
[lineage.eras.last, lineage.last_ordinal]
|
|
44
|
+
ensure
|
|
45
|
+
db&.close
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Runtime::ProjectedBluebook] the held era's stored storage shape, as a bluebook view
|
|
49
|
+
def held_bluebook(latest) = PostgresEra::LineageManager.held_bluebook(latest)
|
|
50
|
+
|
|
51
|
+
# The bluebook directory a mint is for: the one the request names, or the QualityControl
|
|
52
|
+
# ledger.
|
|
53
|
+
#
|
|
54
|
+
# @return [String]
|
|
55
|
+
def ledger_for(root, requested) = requested || File.join(root, QaEraMint::LEDGER)
|
|
56
|
+
|
|
57
|
+
# The ledger a mint is for, refused by name when its world declares it disposable: its boot
|
|
58
|
+
# holds every shape change itself, so there is no era to mint.
|
|
59
|
+
#
|
|
60
|
+
# @return [String] the bluebook directory
|
|
61
|
+
# @raise [Runtime::WiringError] if the ledger is disposable
|
|
62
|
+
def mintable_ledger_for(root, requested)
|
|
63
|
+
ledger = ledger_for(root, requested)
|
|
64
|
+
raise Runtime::WiringError, QaEraMint::DISPOSABLE if QaEraMint.disposable?(ledger)
|
|
65
|
+
|
|
66
|
+
ledger
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The journal rows the run's own `Maintenance` record wrote above the rehearsed watermark: the
|
|
70
|
+
# mint command saves that record before its entry point runs, so it is the one change the
|
|
71
|
+
# rehearsal could not have read.
|
|
72
|
+
#
|
|
73
|
+
# @param ledger [String] the bluebook directory of the ledger
|
|
74
|
+
# @param run [String] the run key, which is the record's id
|
|
75
|
+
# @param rehearsed [Integer] the watermark the rehearsal read
|
|
76
|
+
# @return [Integer]
|
|
77
|
+
def own_rows_after(ledger, run, rehearsed)
|
|
78
|
+
held = JournalStore::HeldDomain.open(ledger, mode: :translated)
|
|
79
|
+
db = PostgresEra.connect_for(held.domain_name, held.settings)
|
|
80
|
+
PostgresEra::Lineage.new(db, held.domain_name).rows_of_after(rehearsed, "maintenance", run)
|
|
81
|
+
ensure
|
|
82
|
+
db&.close
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Why a rehearsed watermark is stale at the live one: the ledger moved by something other than
|
|
86
|
+
# the run's own record, which `commands` counts in the journal now.
|
|
87
|
+
#
|
|
88
|
+
# @param commands [#own_rows_after] reads the journal
|
|
89
|
+
# @param ledger [String] the bluebook directory of the ledger
|
|
90
|
+
# @param run [String] the run key
|
|
91
|
+
# @param rehearsed [Integer] the watermark the rehearsal read
|
|
92
|
+
# @param live [Integer] the live watermark
|
|
93
|
+
# @return [String, nil]
|
|
94
|
+
def stale_for(commands, ledger, run, rehearsed, live)
|
|
95
|
+
stale_watermark(rehearsed, live, own_rows: commands.own_rows_after(ledger, run, rehearsed))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# A watermark is stale when the ledger moved by anything but the run's own record.
|
|
99
|
+
#
|
|
100
|
+
# @param own_rows [Integer] the rows that record wrote above the rehearsed watermark
|
|
101
|
+
# @return [String, nil] the reason the live watermark moved from the rehearsed one, or nil
|
|
102
|
+
def stale_watermark(rehearsed, live, own_rows: 0)
|
|
103
|
+
return if rehearsed == live - own_rows
|
|
104
|
+
|
|
105
|
+
"the ledger watermark moved from #{rehearsed} to #{live} since the rehearsal; rehearse again"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Why a mint waits for the owner: never when confirmed, else the reason the rule holds it.
|
|
109
|
+
#
|
|
110
|
+
# @param confirm [Boolean, nil] the owner's confirmation
|
|
111
|
+
# @return [String, nil]
|
|
112
|
+
def hold_reason(facts, confirm, refusal_total)
|
|
113
|
+
held_reason(facts, refusal_total: refusal_total) unless confirm == true
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Why the auto-mint rule holds a mint for the owner, or nil when it lets the mint run
|
|
117
|
+
# unconfirmed. With no edge file, the implicit empty edge stands in for an empty edge when
|
|
118
|
+
# the shape change qualifies for one.
|
|
119
|
+
#
|
|
120
|
+
# @param facts [Hash] what `facts` read from the ledger
|
|
121
|
+
# @param refusal_total [Integer, nil] the rehearsal's refusal count
|
|
122
|
+
# @return [String, nil] the reason the owner must approve, or nil when the rule holds
|
|
123
|
+
def held_reason(facts, refusal_total:)
|
|
124
|
+
edge_reason(facts) || additive_reason(facts) || rehearsal_reason(refusal_total)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @return [String, nil] why the edge leaving the held era does not stand in for an empty one
|
|
128
|
+
def edge_reason(facts)
|
|
129
|
+
return "no translation edge leaves #{facts[:from]}" if facts[:edge_text].nil? && !implicit?(facts)
|
|
130
|
+
return "the edge from #{facts[:from]} is not empty" if facts[:edge_text] && !empty_edge?(facts[:edge_text])
|
|
131
|
+
|
|
132
|
+
nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @return [String, nil] why the shared decision does not take the shape change as additive
|
|
136
|
+
def additive_reason(facts)
|
|
137
|
+
case facts[:verdict].reason
|
|
138
|
+
when :non_qualifying then "the shape change is not additive"
|
|
139
|
+
when :unrecorded then "the move from #{facts[:from]} to #{facts[:to]} is not recorded"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @return [String, nil] why the rehearsal refused rows
|
|
144
|
+
def rehearsal_reason(refusal_total)
|
|
145
|
+
return if refusal_total.is_a?(Integer) && refusal_total.zero?
|
|
146
|
+
|
|
147
|
+
"the rehearsal refused #{refusal_total.inspect} rows"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Whether an edge file declares nothing: its header and its `end`, with no line between them.
|
|
151
|
+
#
|
|
152
|
+
# @param text [String] the edge file's text
|
|
153
|
+
# @return [Boolean]
|
|
154
|
+
def empty_edge?(text)
|
|
155
|
+
body = text.lines.map(&:strip).reject { |line| line.empty? || line.start_with?("#") }
|
|
156
|
+
body.size == 2 && EDGE_HEADER.match?(body.first) && body.last == "end"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Whether no edge file is needed: the shared decision takes the implicit empty edge.
|
|
160
|
+
#
|
|
161
|
+
# @return [Boolean]
|
|
162
|
+
def implicit?(facts) = facts[:verdict].verdict == "would_mint" && facts[:verdict].source == "implicit"
|
|
163
|
+
|
|
164
|
+
# @return [Hash] the edge leaving the held era's label for the current shape's label, and its
|
|
165
|
+
# text
|
|
166
|
+
def edge_facts(held, ledger, from)
|
|
167
|
+
to = Runtime::StorageShape.mint_hash(held.bluebook)[0, Runtime::StorageShape::LABEL_LENGTH]
|
|
168
|
+
{ from: from, to: to, edge_text: edge_text(File.join(ledger, "translations"), from, to) }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# The text of the edge that leads from `from` to `to`, found by its header.
|
|
172
|
+
#
|
|
173
|
+
# @return [String, nil]
|
|
174
|
+
def edge_text(dir, from, to)
|
|
175
|
+
header = %(from: "#{from}", to: "#{to}")
|
|
176
|
+
Dir.glob(File.join(dir, "*.bluebook")).map { |path| File.read(path) }.find { |text| header_of(text).include?(header) }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# @return [String] the first line of an edge file, where its source and target are named
|
|
180
|
+
def header_of(text) = text.lines.first.to_s
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../hecks/adapters/journal_store/held_domain"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
# The mint of the QualityControl ledger's next era, run by the Maintenance mint. The era check
|
|
8
|
+
# of the ledger the QA world names runs once with the mint command's request. The world keeps
|
|
9
|
+
# `mint_eras false`; this one check's settings carry `mint_eras true` and the request, which is
|
|
10
|
+
# the one-mint permission the world's comment describes.
|
|
11
|
+
module QaEraMint
|
|
12
|
+
# The ledger's bluebook directory, under the repository root.
|
|
13
|
+
LEDGER = "qa/bluebook"
|
|
14
|
+
|
|
15
|
+
# What a mint of a disposable ledger answers: its boot holds every shape change itself.
|
|
16
|
+
DISPOSABLE = "disposable, no mint needed: the ledger's world declares disposable_ledger true, " \
|
|
17
|
+
"so its boot brings the shape up to date without an era"
|
|
18
|
+
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
# Whether a ledger's world declares `disposable_ledger true`, so it needs no mint.
|
|
22
|
+
#
|
|
23
|
+
# @param ledger [String, JournalStore::HeldDomain] the bluebook directory, or the opened one
|
|
24
|
+
# @return [Boolean]
|
|
25
|
+
def disposable?(ledger)
|
|
26
|
+
held = ledger.is_a?(String) ? JournalStore::HeldDomain.open(ledger, mode: :translated) : ledger
|
|
27
|
+
PostgresEra::LineageManager::DisposableLedger.declared?(held.settings)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Mints the next era of the ledger, or refuses by name.
|
|
31
|
+
#
|
|
32
|
+
# @param root [String] the repository root holding `qa/bluebook`
|
|
33
|
+
# @param domain [String] the domain the mint is for; the ledger must hold it
|
|
34
|
+
# @param era [Integer] the ordinal the mint is for; it must be the era the ledger would mint
|
|
35
|
+
# next
|
|
36
|
+
# @param request [Hash] the mint command's request: `confirm` (a boolean), `verdict` (the
|
|
37
|
+
# rehearsal's verdict) and `watermark` (the ledger watermark the rehearsal read)
|
|
38
|
+
# @param ledger [String, nil] the bluebook directory of the ledger; the QualityControl ledger
|
|
39
|
+
# under `root` when nil
|
|
40
|
+
# @return [Array(String, Boolean)] the minted era's label or the refusal, and whether it
|
|
41
|
+
# minted
|
|
42
|
+
def call(root, domain:, era:, request:, ledger: nil)
|
|
43
|
+
held = JournalStore::HeldDomain.open(ledger || File.join(root, LEDGER), mode: :translated)
|
|
44
|
+
return [DISPOSABLE, false] if disposable?(held)
|
|
45
|
+
|
|
46
|
+
settings = held.settings.merge(mint_eras: true, mint_request: request)
|
|
47
|
+
refuse_wrong_mint!(held, settings, domain, era)
|
|
48
|
+
mint!(held, settings) ? [Runtime::StorageShape.mint_label(held.bluebook), true] : [unminted, false]
|
|
49
|
+
rescue Runtime::WiringError, Runtime::NotFound => e
|
|
50
|
+
[e.message, false]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Refuses a mint that names another domain, or an era other than the one the ledger would mint
|
|
54
|
+
# next.
|
|
55
|
+
#
|
|
56
|
+
# @return [void]
|
|
57
|
+
# @raise [Runtime::WiringError] naming the mismatch
|
|
58
|
+
def refuse_wrong_mint!(held, settings, domain, era)
|
|
59
|
+
name = held.domain_name
|
|
60
|
+
raise Runtime::WiringError, "the ledger holds #{name}, not #{domain}" unless name == domain
|
|
61
|
+
|
|
62
|
+
next_era = next_era_of(settings, name)
|
|
63
|
+
return if next_era == era
|
|
64
|
+
|
|
65
|
+
raise Runtime::WiringError, "the mint names era #{era}, but the ledger's next era is #{next_era}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @return [Integer] the ordinal the ledger would mint next: one past its latest held era
|
|
69
|
+
def next_era_of(settings, name)
|
|
70
|
+
db = PostgresEra.connect_for(name, settings)
|
|
71
|
+
latest = PostgresEra::Lineage.new(db, name).eras.last
|
|
72
|
+
latest ? latest[:ordinal] + 1 : 1
|
|
73
|
+
ensure
|
|
74
|
+
db&.close
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Runs the era check with the request. It mints when the shape drifted, and answers false when
|
|
78
|
+
# the shape is already the ledger's current one.
|
|
79
|
+
#
|
|
80
|
+
# @return [Integer, nil] the ordinal minted, or nil when nothing minted
|
|
81
|
+
def mint!(held, settings)
|
|
82
|
+
text = Runtime::EraCheck.source_text_for(held.bluebook, held.directory, registry: held.registry) ||
|
|
83
|
+
Runtime::EraCheck.refuse_missing_source!(held.bluebook, held.directory)
|
|
84
|
+
held.registry.adapter_class(held.adapter_name).era_check!(
|
|
85
|
+
registry: held.registry, bluebook: held.bluebook, current_text: text, settings: settings,
|
|
86
|
+
directory: held.directory
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @return [String] the refusal for a mint that found nothing to mint
|
|
91
|
+
def unminted = "the ledger already holds the current shape; no era was minted"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "time"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Adapters
|
|
9
|
+
# The marker file that quiets QA for a mint window. While a fresh marker exists, `hecks
|
|
10
|
+
# quality_control sweep.tick` refuses to start any step (it prints `quiesced: skipped
|
|
11
|
+
# <step>` and exits 0), so nothing writes to the QA ledger and its watermark holds still
|
|
12
|
+
# between a rehearsal and the mint. The tick reads the marker before each step, so a tick
|
|
13
|
+
# already running notices it too.
|
|
14
|
+
#
|
|
15
|
+
# The marker is one JSON file beside the stranded-mint record (`~/.claude/hecks-dev/quiesce`,
|
|
16
|
+
# `HECKS_QUIESCE_STATE` moves it) holding its owner, reason and time. A marker older than the
|
|
17
|
+
# staleness window (two hours) is ignored and reported, so a crashed mint cannot freeze QA
|
|
18
|
+
# for good. It touches no ledger and no git state, and the mint itself never requires it.
|
|
19
|
+
class QaQuiesceMarker
|
|
20
|
+
# Raised when a hold or release is refused; the message is the reason.
|
|
21
|
+
class Refused < RuntimeError; end
|
|
22
|
+
|
|
23
|
+
# Where the marker lives.
|
|
24
|
+
PATH = ENV.fetch("HECKS_QUIESCE_STATE", File.expand_path("~/.claude/hecks-dev/quiesce")).freeze
|
|
25
|
+
|
|
26
|
+
# How long a marker holds before it counts as left behind by a crash.
|
|
27
|
+
STALE_AFTER = Integer(ENV.fetch("HECKS_QUIESCE_STALE_SECONDS", 2 * 60 * 60))
|
|
28
|
+
|
|
29
|
+
# What a marker says: who holds the window, why and since when.
|
|
30
|
+
Hold = Struct.new(:owner, :reason, :held_at, keyword_init: true)
|
|
31
|
+
|
|
32
|
+
# @param path [String] the marker file
|
|
33
|
+
# @param stale_after [Integer] seconds after which a marker is ignored
|
|
34
|
+
# @param clock [#call] answers the current Time
|
|
35
|
+
def initialize(path: PATH, stale_after: STALE_AFTER, clock: -> { Time.now })
|
|
36
|
+
@path = path
|
|
37
|
+
@stale_after = stale_after
|
|
38
|
+
@clock = clock
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Hold, nil] the marker's content, fresh or stale, or nil when there is none
|
|
42
|
+
def read
|
|
43
|
+
return unless File.exist?(@path)
|
|
44
|
+
|
|
45
|
+
data = JSON.parse(File.read(@path))
|
|
46
|
+
Hold.new(owner: data["owner"].to_s, reason: data["reason"].to_s, held_at: Time.iso8601(data["held_at"]))
|
|
47
|
+
rescue JSON::ParserError, ArgumentError, TypeError
|
|
48
|
+
Hold.new(owner: "unknown", reason: "unreadable marker", held_at: File.mtime(@path))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [Hold, nil] the marker when it is present and not stale
|
|
52
|
+
def active
|
|
53
|
+
hold = read
|
|
54
|
+
hold if hold && !stale?(hold)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @return [Hold, nil] the marker when it is present and past the staleness window
|
|
58
|
+
def stale
|
|
59
|
+
hold = read
|
|
60
|
+
hold if hold && stale?(hold)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Writes the marker. A fresh marker of another owner is refused unless forced; the same
|
|
64
|
+
# owner's hold is refreshed, and a stale one is replaced.
|
|
65
|
+
#
|
|
66
|
+
# @return [Hold] what was written
|
|
67
|
+
# @raise [Refused] when another owner holds a fresh marker and `force` is false
|
|
68
|
+
def hold!(owner:, reason:, force: false)
|
|
69
|
+
current = active
|
|
70
|
+
if current && current.owner != owner && !force
|
|
71
|
+
raise Refused, "already held by #{current.owner} (#{describe(current)}); release it, or hold with force"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
write(Hold.new(owner: owner, reason: reason, held_at: @clock.call))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Removes the marker. Another owner's fresh marker stays unless forced.
|
|
78
|
+
#
|
|
79
|
+
# @return [Hold, nil] the marker removed, or nil when there was none
|
|
80
|
+
# @raise [Refused] when another owner holds a fresh marker and `force` is false
|
|
81
|
+
def release!(owner:, force: false)
|
|
82
|
+
current = read
|
|
83
|
+
return unless current
|
|
84
|
+
if current.owner != owner && !force && !stale?(current)
|
|
85
|
+
raise Refused, "held by #{current.owner} (#{describe(current)}), not #{owner}; release with force to remove it"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
FileUtils.rm_f(@path)
|
|
89
|
+
current
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @return [String] a sentence on the marker: owner, reason and age, or that QA is not quiesced
|
|
93
|
+
def status
|
|
94
|
+
hold = read
|
|
95
|
+
return "not quiesced: no marker at #{@path}" unless hold
|
|
96
|
+
|
|
97
|
+
"#{stale?(hold) ? "stale (ignored)" : "quiesced"}: #{describe(hold)}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @return [String] "owner, reason, held 12 minutes ago"
|
|
101
|
+
def describe(hold)
|
|
102
|
+
"owner #{hold.owner}, reason #{hold.reason.inspect}, held #{age(hold)} ago (since #{hold.held_at.utc.iso8601})"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def stale?(hold) = (@clock.call - hold.held_at) > @stale_after
|
|
108
|
+
|
|
109
|
+
def age(hold)
|
|
110
|
+
seconds = (@clock.call - hold.held_at).to_i
|
|
111
|
+
return "#{seconds}s" if seconds < 120
|
|
112
|
+
return "#{seconds / 60}m" if seconds < 7200
|
|
113
|
+
|
|
114
|
+
"#{seconds / 3600}h"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def write(hold)
|
|
118
|
+
FileUtils.mkdir_p(File.dirname(@path))
|
|
119
|
+
temp = "#{@path}.#{Process.pid}"
|
|
120
|
+
File.write(temp, JSON.generate(owner: hold.owner, reason: hold.reason, held_at: hold.held_at.utc.iso8601))
|
|
121
|
+
File.rename(temp, @path)
|
|
122
|
+
hold
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
# The keys of the `RedSpec` rows a run reader files. A key is a readable slug of what is red
|
|
8
|
+
# and a digest of the exact text, so two spec paths never share a key: separators stay distinct
|
|
9
|
+
# (`__`), and paths differing only in case or punctuation differ in the digest.
|
|
10
|
+
module RunKeys
|
|
11
|
+
# The `.rb` ending of a spec path, left off its key.
|
|
12
|
+
RUBY_SUFFIX = ".rb"
|
|
13
|
+
|
|
14
|
+
# Runs of characters a Work key does not hold.
|
|
15
|
+
KEY_BREAK = /[^a-zA-Z0-9_]+/
|
|
16
|
+
|
|
17
|
+
# Hex digits of the exact text's digest a key ends with.
|
|
18
|
+
DIGEST_LENGTH = 10
|
|
19
|
+
|
|
20
|
+
module_function
|
|
21
|
+
|
|
22
|
+
# @param path [String] a spec path such as `spec/a/b_spec.rb`
|
|
23
|
+
# @return [String] `red-<readable slug>-<digest>`
|
|
24
|
+
def spec(path) = build(path.delete_suffix(RUBY_SUFFIX).gsub("/", "__"), path)
|
|
25
|
+
|
|
26
|
+
# @param job [String] the name of a spec job that failed with no failing example in its log
|
|
27
|
+
# @return [String] `red-job-<readable slug>-<digest>`
|
|
28
|
+
def job(job) = build("job-#{job}", job)
|
|
29
|
+
|
|
30
|
+
# @return [String] the key for a readable slug and the exact text it stands for
|
|
31
|
+
def build(slug, exact)
|
|
32
|
+
"red-#{slug.gsub(KEY_BREAK, "-").downcase}-#{Digest::SHA256.hexdigest(exact)[0, DIGEST_LENGTH]}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Binds the `Reader` port to `RunReader`, which reads a CI run of main for the spec files it failed.
|
|
2
|
+
# Required by name, not relative, so a copy of this directory shares the one implementation loaded.
|
|
3
|
+
require "hecks/quality_control/adapters/run_reader"
|
|
4
|
+
|
|
5
|
+
Hecks.adapter "RunReader" do
|
|
6
|
+
port "Reader"
|
|
7
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "time"
|
|
6
|
+
require "hecks/quality_control/adapters/run_keys"
|
|
7
|
+
require "hecks/runtime/asking"
|
|
8
|
+
require "hecks/runtime/errors"
|
|
9
|
+
require "hecks/runtime/row_sweep"
|
|
10
|
+
require "hecks/runtime/dispatcher"
|
|
11
|
+
|
|
12
|
+
module Hecks
|
|
13
|
+
module Adapters
|
|
14
|
+
# The `Reader` port's adapter: reads one CI run of main (`gh run view`, job logs) for the spec
|
|
15
|
+
# files it failed, and reports each to `RedSpec` through the boot whose `MainRun` asked. A file
|
|
16
|
+
# already red is updated, never opened twice. It answers the commit and whether the run settled,
|
|
17
|
+
# which the bluebook's policies use to clear the files the run did not fail.
|
|
18
|
+
#
|
|
19
|
+
# `gh` is the one thing it reaches for besides the clock; a spec stubs `Open3` with a fake run.
|
|
20
|
+
class RunReader
|
|
21
|
+
# A line of RSpec's "Failed examples:" summary as a job log prints it: the file, then the
|
|
22
|
+
# example's description.
|
|
23
|
+
# The path is read up to its `.rb` and the location that follows (`:12` or `[1:2]`), so a
|
|
24
|
+
# path with a space in it still matches; RSpec may quote it or escape the space.
|
|
25
|
+
FAILED_EXAMPLE = %r{rspec ['"]?(\./spec/.+?\.rb)(?:\[[^\]]*\]|:\d+)['"]?\s*(?:#\s*(.*))?$}
|
|
26
|
+
|
|
27
|
+
# Where a path's escaped space is unescaped.
|
|
28
|
+
ESCAPED_SPACE = "\\ "
|
|
29
|
+
|
|
30
|
+
# A job whose name says it runs specs.
|
|
31
|
+
SPEC_JOB = /spec/i
|
|
32
|
+
|
|
33
|
+
# The one conclusion that clears a red spec: the job ran its specs and they passed.
|
|
34
|
+
PASSED = "success"
|
|
35
|
+
|
|
36
|
+
# The branch and the event whose runs count: a push to main.
|
|
37
|
+
BRANCH = "main"
|
|
38
|
+
EVENT = "push"
|
|
39
|
+
|
|
40
|
+
# Job conclusions that are no verdict on the specs: the job did not run to an end.
|
|
41
|
+
UNFINISHED = [nil, "", "cancelled", "skipped", "neutral", "stale", "action_required"].freeze
|
|
42
|
+
|
|
43
|
+
# What `gh run view --json` is asked for.
|
|
44
|
+
JSON_FIELDS = "headSha,headBranch,event,createdAt,conclusion,jobs"
|
|
45
|
+
|
|
46
|
+
# Longest text the reader keeps of a failure line or the example list.
|
|
47
|
+
SHORT = 200
|
|
48
|
+
|
|
49
|
+
# @param aggregate [Object, nil] unused
|
|
50
|
+
# @param settings [Hash] unused
|
|
51
|
+
# @param root [String, nil] the checkout `gh` runs in; this repository when nil
|
|
52
|
+
def initialize(aggregate: nil, settings: {}, root: nil)
|
|
53
|
+
@root = root || File.expand_path("../../../..", __dir__)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param path [String] a spec path such as `spec/a/b_spec.rb`
|
|
57
|
+
# @return [String] the key of its row; see `RunKeys`
|
|
58
|
+
def self.key_for(path) = RunKeys.spec(path)
|
|
59
|
+
|
|
60
|
+
# @param run [Hash, String] the GitHub run id
|
|
61
|
+
# @param repo [Hash, String] `owner/name`
|
|
62
|
+
# @return [Hash] `commit:` and `settled:` ("yes" only when every spec job ended `success`)
|
|
63
|
+
# @raise [Runtime::GivenNotMet] when the run is not a push to main
|
|
64
|
+
def read(run:, repo:, **)
|
|
65
|
+
id = named(run)
|
|
66
|
+
view = JSON.parse(gh("run", "view", id, "--repo", named(repo), "--json", JSON_FIELDS))
|
|
67
|
+
refuse_unless_main!(view, id)
|
|
68
|
+
seen = { run: id, commit: view.fetch("headSha") }
|
|
69
|
+
file_failures(failures_in(gh("run", "view", id, "--repo", named(repo), "--log-failed")), view, seen)
|
|
70
|
+
{ commit: { value: seen[:commit] }, settled: { value: green?(view, id) ? "yes" : "no" } }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def green?(view, id) = settled?(view) && !behind_a_row?(id)
|
|
76
|
+
|
|
77
|
+
# Reports each failing file; a failed job whose log named none is reported as a row
|
|
78
|
+
# of its own.
|
|
79
|
+
def file_failures(failures, view, seen)
|
|
80
|
+
failures.each { |path, examples| report(RunKeys.spec(path), path, examples, seen) }
|
|
81
|
+
report_unparsed(view, failures, seen)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def named(value) = value.is_a?(Hash) ? value.values.first.to_s : value.to_s
|
|
85
|
+
|
|
86
|
+
# Only a push to main is read: another branch's run, or a pull request's, says nothing
|
|
87
|
+
# of main.
|
|
88
|
+
def refuse_unless_main!(view, id)
|
|
89
|
+
return if view["headBranch"] == BRANCH && view["event"] == EVENT
|
|
90
|
+
|
|
91
|
+
raise Runtime::GivenNotMet, "run #{id} is #{view["event"].inspect} on #{view["headBranch"].inspect}, " \
|
|
92
|
+
"not a #{EVENT} to #{BRANCH}; only main's own runs are read"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def spec_jobs(view) = view.fetch("jobs", []).select { |job| job["name"].to_s.match?(SPEC_JOB) }
|
|
96
|
+
|
|
97
|
+
# Every job that runs specs ended `success`, and at least one did. A failed job with no
|
|
98
|
+
# failure parsed from its log is not green: the run clears nothing.
|
|
99
|
+
def settled?(view)
|
|
100
|
+
jobs = spec_jobs(view)
|
|
101
|
+
jobs.any? && jobs.all? { |job| job["conclusion"] == PASSED }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# A spec job that failed (or timed out) while the log named no failing example is reported as
|
|
105
|
+
# a row of its own, so the failure stays visible and open.
|
|
106
|
+
def report_unparsed(view, failures, seen)
|
|
107
|
+
return unless failures.empty?
|
|
108
|
+
|
|
109
|
+
spec_jobs(view).reject { |job| UNFINISHED.include?(job["conclusion"]) || job["conclusion"] == PASSED }.each do |job|
|
|
110
|
+
name = job["name"].to_s
|
|
111
|
+
report(RunKeys.job(name), "job #{name}", ["#{name} #{job["conclusion"]}: no failing example in its log"], seen,
|
|
112
|
+
title: "spec job #{name} failed on main with no failing example parsed")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# @return [Hash{String => Array<String>}] each failing spec file to its failing example texts
|
|
117
|
+
def failures_in(log)
|
|
118
|
+
log.each_line(chomp: true).with_object(Hash.new { |h, k| h[k] = [] }) do |line, found|
|
|
119
|
+
match = FAILED_EXAMPLE.match(line)
|
|
120
|
+
found[match[1].delete_prefix("./").gsub(ESCAPED_SPACE, " ")] << match[2].to_s.strip if match
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def report(key, path, examples, seen, title: "#{path} is red on main")
|
|
125
|
+
facts = facts_of(examples, seen[:run], seen[:commit])
|
|
126
|
+
row = row_for(key)
|
|
127
|
+
if row
|
|
128
|
+
dispatch("QualityControl::RedSpec.Update", facts.merge(to: key)) unless older?(seen[:run], row)
|
|
129
|
+
else
|
|
130
|
+
open_or_reopen(key, path, title, facts)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# A file never seen red is opened; one cleared earlier already has its row, which reopens.
|
|
135
|
+
def open_or_reopen(key, path, title, facts)
|
|
136
|
+
facts = facts.merge(title: title, since: Time.now.utc.strftime("%Y-%m-%d"))
|
|
137
|
+
dispatch("QualityControl::RedSpec.Open", facts.merge(spec: key, path: path))
|
|
138
|
+
rescue Runtime::AlreadyExists
|
|
139
|
+
dispatch("QualityControl::RedSpec.Reopen", facts.merge(to: key))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# A run older than the one the row last saw does not overwrite what the row knows.
|
|
143
|
+
def older?(run, row) = run.to_i < last_run_of(row)
|
|
144
|
+
|
|
145
|
+
def last_run_of(row)
|
|
146
|
+
value = row[:last_run]
|
|
147
|
+
(value.respond_to?(:value) ? value.value : value).to_s.to_i
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Whether some red row was last seen by a newer run than this one: GitHub run ids grow, so a
|
|
151
|
+
# run behind a row says nothing of the file's state now and clears nothing.
|
|
152
|
+
def behind_a_row?(run) = open_rows.any? { |row| last_run_of(row) > run.to_i }
|
|
153
|
+
|
|
154
|
+
def facts_of(examples, run, commit)
|
|
155
|
+
count = examples.size
|
|
156
|
+
{ failures: count, first_failure: short(examples.first.to_s), examples: short(examples.first(3).join(" | ")),
|
|
157
|
+
last_run: run, commit: commit,
|
|
158
|
+
detail: short("#{count} failing example#{"s" unless count == 1}; first: #{examples.first}; run #{run}; sha #{commit}") }
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def short(text) = text.length > SHORT ? "#{text[0, SHORT - 3]}..." : text
|
|
162
|
+
|
|
163
|
+
# The spec's row while it is red: a red row is updated, a green or absent one is opened.
|
|
164
|
+
def row_for(key) = open_rows.find { |row| row[:id].to_s == key }
|
|
165
|
+
|
|
166
|
+
def open_rows
|
|
167
|
+
sweep = Runtime::RowSweep.new(registry)
|
|
168
|
+
aggregate = sweep.query_aggregate("QualityControl", "RedSpec", verb: "RedSpec.OnMain")
|
|
169
|
+
sweep.rows("QualityControl", aggregate, "OnMain", {})
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def dispatch(verb, args) = Runtime::Dispatcher.new(registry).dispatch_flat(verb, args)
|
|
173
|
+
|
|
174
|
+
def registry
|
|
175
|
+
Runtime::Asking.registry or raise Runtime::GivenNotMet, "a run is read only when its MainRun asks"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def gh(*args)
|
|
179
|
+
out, err, status = Open3.capture3("gh", *args, chdir: @root)
|
|
180
|
+
raise Runtime::GivenNotMet, "gh #{args.first(3).join(" ")} failed: #{err.lines.first&.strip}" unless status.success?
|
|
181
|
+
|
|
182
|
+
out
|
|
183
|
+
rescue Errno::ENOENT
|
|
184
|
+
raise Runtime::GivenNotMet, "gh is not installed or not on PATH"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -12,6 +12,7 @@ module Hecks
|
|
|
12
12
|
# `hecks/quality_control/cli/<command>`.
|
|
13
13
|
COMMANDS = {
|
|
14
14
|
"qa_tick" => ["QaTick", :argv_root],
|
|
15
|
+
"qa_event_pump" => ["QaEventPump", :argv_root],
|
|
15
16
|
"qa_sweep" => ["QaSweep", :argv_root],
|
|
16
17
|
"qa_pr_check" => ["QaPrCheck", :argv_root],
|
|
17
18
|
"qa_generated_domains" => ["QaGeneratedDomains", :argv_root],
|
|
@@ -86,7 +86,7 @@ module Hecks
|
|
|
86
86
|
"pass --known-path <path> ... to run without the ledger", usage: false
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
JSON.parse(out).filter_map { |row| row
|
|
89
|
+
JSON.parse(out).filter_map { |row| row["path"] }
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
# The sibling directories under `projects_dir`, leaving out this repo (already fully covered
|