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,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Translation
|
|
7
|
+
# Carries out an admitted `Reconcile` plan on the translations directory, and puts the files
|
|
8
|
+
# back when the audit of what was written refuses.
|
|
9
|
+
module ReconcileFiles
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
# Writes the plan's composed edge and deletes the edge files it supersedes.
|
|
13
|
+
#
|
|
14
|
+
# @param plan [Reconcile::Plan] a plan with status `:write`
|
|
15
|
+
# @return [Hash{String => String, nil}] each touched path with the text it held, nil if absent
|
|
16
|
+
def write!(plan)
|
|
17
|
+
originals = [plan.write_path, *plan.removals].compact.to_h { |path| [path, read_if_present(path)] }
|
|
18
|
+
File.write(plan.write_path, plan.text) if plan.write_path
|
|
19
|
+
plan.removals.each { |path| FileUtils.rm_f(path) }
|
|
20
|
+
originals
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Puts each touched file back as `write!` found it.
|
|
24
|
+
#
|
|
25
|
+
# @param originals [Hash{String => String, nil}] what `write!` returned
|
|
26
|
+
def restore!(originals)
|
|
27
|
+
originals.each do |path, text|
|
|
28
|
+
text ? File.write(path, text) : FileUtils.rm_f(path)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def read_if_present(path) = File.exist?(path) ? File.read(path) : nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative "../../storage_shape"
|
|
2
|
+
require_relative "../../projected_bluebook"
|
|
2
3
|
require_relative "path_diff"
|
|
3
4
|
|
|
4
5
|
module Hecks
|
|
@@ -9,14 +10,19 @@ module Hecks
|
|
|
9
10
|
module Differ
|
|
10
11
|
include PathDiff
|
|
11
12
|
|
|
12
|
-
# Diffs two
|
|
13
|
+
# Diffs two storage shapes into the edge's declarations. Either side is a storage shape, a
|
|
14
|
+
# `Runtime::ProjectedBluebook` over one, or a declared bluebook, which is projected first.
|
|
13
15
|
#
|
|
14
|
-
# @param held_bluebook [Bluebook::Declaration] the era
|
|
15
|
-
#
|
|
16
|
+
# @param held_bluebook [Hash, Runtime::ProjectedBluebook, Bluebook::Declaration] the era
|
|
17
|
+
# being translated from
|
|
18
|
+
# @param current_bluebook [Hash, Runtime::ProjectedBluebook, Bluebook::Declaration] the era
|
|
19
|
+
# being translated to
|
|
16
20
|
# @return [Hash{Symbol => Object}] `:aggregates` (Array<Scaffold::ScaffoldedAggregate>),
|
|
17
21
|
# `:retired` (Array<String>, vanished names with no successor), `:unclaimed`
|
|
18
22
|
# (Array<String>, vanished names left ambiguous)
|
|
19
23
|
def diff(held_bluebook, current_bluebook)
|
|
24
|
+
held_bluebook = Runtime::ProjectedBluebook.wrap(held_bluebook)
|
|
25
|
+
current_bluebook = Runtime::ProjectedBluebook.wrap(current_bluebook)
|
|
20
26
|
held_shapes = projections(held_bluebook)
|
|
21
27
|
current_shapes = projections(current_bluebook)
|
|
22
28
|
|
|
@@ -40,9 +46,11 @@ module Hecks
|
|
|
40
46
|
ScaffoldedAggregate.new(name: aggregate.name, was: was, rules: rules)
|
|
41
47
|
end
|
|
42
48
|
|
|
43
|
-
#
|
|
49
|
+
# A side's storage shape, its aggregates indexed by name: a view's stored shape as it is, a
|
|
50
|
+
# declared bluebook's as `StorageShape.project` answers it.
|
|
44
51
|
def projections(bluebook)
|
|
45
|
-
Runtime::StorageShape.project(bluebook)
|
|
52
|
+
shape = bluebook.is_a?(Runtime::ProjectedBluebook) ? bluebook.projection : Runtime::StorageShape.project(bluebook)
|
|
53
|
+
shape["aggregates"].to_h { |aggregate| [aggregate["name"], aggregate] }
|
|
46
54
|
end
|
|
47
55
|
|
|
48
56
|
# Pairs vanished aggregates with new ones whose full shape reappears under exactly one
|
|
@@ -7,5 +7,10 @@ end
|
|
|
7
7
|
|
|
8
8
|
require_relative "translation/rule_compiler"
|
|
9
9
|
require_relative "translation/scaffold"
|
|
10
|
+
require_relative "translation/implicit_edge"
|
|
10
11
|
require_relative "translation/audit"
|
|
12
|
+
require_relative "translation/compose"
|
|
13
|
+
require_relative "translation/edge_files"
|
|
14
|
+
require_relative "translation/reconcile"
|
|
15
|
+
require_relative "translation/reconcile_files"
|
|
11
16
|
require_relative "translation/reattest"
|
|
@@ -43,7 +43,7 @@ module Hecks
|
|
|
43
43
|
# @param bind [Bluebook::Bind] the bind naming the adapter
|
|
44
44
|
# @param settings_verb [String] the verb whose settings configure the adapter
|
|
45
45
|
# @return [Hash] the declared settings, under the adapter's own declared defaults, plus
|
|
46
|
-
# the domain, resolved era and
|
|
46
|
+
# the domain, resolved era, superseding era and whether the shape is unminted
|
|
47
47
|
def adapter_settings(registry, domain, aggregate, bind, settings_verb)
|
|
48
48
|
registry.check_verb(bind)
|
|
49
49
|
settings = registry.binding_settings(domain, settings_verb, bind.adapter)
|
|
@@ -52,8 +52,16 @@ module Hecks
|
|
|
52
52
|
settings = registry.with_adapter_defaults(bind.adapter, aggregate, settings)
|
|
53
53
|
# domain, resolved era and superseding era ride along outside the declared
|
|
54
54
|
# settings: a lineage adapter needs them to journal per domain, per-era.
|
|
55
|
-
settings.merge(
|
|
56
|
-
|
|
55
|
+
settings.merge(boot_marks(registry, domain))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# The per-domain marks the boot gate left on the registry, merged into an adapter's settings.
|
|
59
|
+
#
|
|
60
|
+
# @return [Hash] the domain, resolved era, superseding era and whether the shape is unminted
|
|
61
|
+
def boot_marks(registry, domain)
|
|
62
|
+
name = domain.to_s
|
|
63
|
+
{ domain: name, era: registry.resolved_eras[name], superseded_by: registry.superseded_eras[name],
|
|
64
|
+
unminted: registry.unminted_eras.key?(name) }
|
|
57
65
|
end
|
|
58
66
|
end
|
|
59
67
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative "../../runtime/errors"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Ports
|
|
5
|
+
module Persistence
|
|
6
|
+
# Refuses the boot that would store an aggregate in a new, empty table beside rows an earlier
|
|
7
|
+
# name still holds. A renamed aggregate's rows are found by its `stored_as`; if that line is
|
|
8
|
+
# missing or wrong, the adapter would create the empty table the new name implies and the
|
|
9
|
+
# rows would seem gone. This names the table the rows are in instead, and creates nothing.
|
|
10
|
+
module StoredNameGuard
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
# @param aggregate [Bluebook::Aggregate] the aggregate about to be stored
|
|
14
|
+
# @param row_count [#call] given a table's base name, the rows it holds (0 when absent)
|
|
15
|
+
# @return [void]
|
|
16
|
+
# @raise [Runtime::WiringError] when the aggregate's own table holds no rows and a prior
|
|
17
|
+
# name's table does
|
|
18
|
+
def check!(aggregate, row_count:)
|
|
19
|
+
return if row_count.call(aggregate.storage_name).positive?
|
|
20
|
+
|
|
21
|
+
held = aggregate.prior_storage_names.to_h { |name| [name, row_count.call(name)] }.select { |_, rows| rows.positive? }
|
|
22
|
+
return if held.empty?
|
|
23
|
+
|
|
24
|
+
raise Runtime::WiringError, refusal(aggregate, held)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def refusal(aggregate, held)
|
|
28
|
+
name, rows = held.first
|
|
29
|
+
"cannot boot #{aggregate.name}: it would be stored in #{aggregate.storage_name.inspect}, which holds no rows, " \
|
|
30
|
+
"but #{name.inspect} holds rows (#{rows}) from an earlier name. Point the world at them with " \
|
|
31
|
+
"`stored_as #{aggregate.name}: #{name.inspect}`, or move the rows first. Nothing was created."
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -2,6 +2,8 @@ require_relative "persistence/constants"
|
|
|
2
2
|
require_relative "persistence/binding_policy"
|
|
3
3
|
require_relative "persistence/plugin"
|
|
4
4
|
require_relative "persistence/repository_factory"
|
|
5
|
+
require_relative "persistence/mint_door"
|
|
6
|
+
require_relative "persistence/stored_name_guard"
|
|
5
7
|
require_relative "persistence/append_only"
|
|
6
8
|
require_relative "persistence/execution"
|
|
7
9
|
require_relative "persistence/remote_runtime"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tree"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Projections
|
|
7
|
+
module CiPipeline
|
|
8
|
+
class Table
|
|
9
|
+
# What no single row can show: a workflow nothing starts, secrets no caller can pass, a
|
|
10
|
+
# shard count that is not one a matrix can have, jobs that wait on one another in a circle,
|
|
11
|
+
# and a command that names a shard total its job does not have.
|
|
12
|
+
class Checks
|
|
13
|
+
# The text a step's command writes where its job's shard total belongs.
|
|
14
|
+
SHARD_TOKEN = "%{shard_total}"
|
|
15
|
+
|
|
16
|
+
# One scope of a job's `permissions:` line: a scope, a colon and what is allowed.
|
|
17
|
+
PERMISSION = /\A[a-z-]+: (read|write|none)\z/
|
|
18
|
+
|
|
19
|
+
# A command that begins with whitespace, which a literal block cannot carry.
|
|
20
|
+
LEADING_SPACE = /\A\s/
|
|
21
|
+
|
|
22
|
+
# @param workflows [Array<Tree::Workflow>] the joined workflows
|
|
23
|
+
# @param vocabulary [Hash{Symbol => Object}] the closed sets and patterns
|
|
24
|
+
# @param problems [Array<String>] collects each problem found, one line each
|
|
25
|
+
def initialize(workflows, vocabulary, problems)
|
|
26
|
+
@workflows = workflows
|
|
27
|
+
@vocabulary = vocabulary
|
|
28
|
+
@problems = problems
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [void]
|
|
32
|
+
def call
|
|
33
|
+
@workflows.each do |workflow|
|
|
34
|
+
check_workflow(workflow)
|
|
35
|
+
workflow.jobs.each { |job| check_job(job) }
|
|
36
|
+
check_cycles(workflow)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def check_workflow(workflow)
|
|
43
|
+
events = @vocabulary.fetch(:trigger)
|
|
44
|
+
problem(workflow, "has no Trigger row; an event is one of #{events.join(", ")}") if workflow.triggers.empty?
|
|
45
|
+
if workflow.secrets.any? && !workflow.triggers.include?("workflow_call")
|
|
46
|
+
problem(workflow, "has Secret rows but no workflow_call Trigger; only a called workflow takes secrets")
|
|
47
|
+
end
|
|
48
|
+
return unless workflow.cancel_in_progress && workflow.concurrency_group.empty?
|
|
49
|
+
|
|
50
|
+
problem(workflow, "cancels in progress without a concurrency_group to cancel within")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def check_job(job)
|
|
54
|
+
check_time_limit(job)
|
|
55
|
+
check_shard_total(job)
|
|
56
|
+
check_shard_axis(job)
|
|
57
|
+
check_shard_token(job)
|
|
58
|
+
check_permissions(job)
|
|
59
|
+
job.steps.select { |step| step.run.match?(LEADING_SPACE) }.each do |step|
|
|
60
|
+
problem(step, "starts its command with whitespace, which a block scalar cannot carry")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def check_time_limit(job)
|
|
65
|
+
return if job.timeout_minutes.to_i.positive?
|
|
66
|
+
|
|
67
|
+
problem(job, "has timeout_minutes #{job.timeout_minutes.inspect}; a job has a positive time limit")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def check_shard_total(job)
|
|
71
|
+
return unless job.shard_total < 1
|
|
72
|
+
|
|
73
|
+
problem(job, "has shard_total #{job.shard_total}; a sharded job has at least one shard")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def check_shard_axis(job)
|
|
77
|
+
if job.shard_total > 1 && job.shard_axis.empty?
|
|
78
|
+
problem(job, "has shard_total #{job.shard_total} and no shard_axis; the matrix needs a name")
|
|
79
|
+
elsif job.shard_total <= 1 && !job.shard_axis.empty?
|
|
80
|
+
problem(job, "has shard_axis #{job.shard_axis.inspect} but shard_total #{job.shard_total}; " \
|
|
81
|
+
"a job with one shard has no matrix")
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def check_shard_token(job)
|
|
86
|
+
return if job.shard_total > 1
|
|
87
|
+
|
|
88
|
+
job.steps.select { |step| step.run.include?(SHARD_TOKEN) }.each do |step|
|
|
89
|
+
problem(step, "writes #{SHARD_TOKEN} but its job has no shards")
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def check_permissions(job)
|
|
94
|
+
scopes = job.permissions.split(", ")
|
|
95
|
+
scopes.grep_v(PERMISSION).each do |scope|
|
|
96
|
+
problem(job, "has permissions scope #{scope.inspect}; a scope is `<name>: read`, `write` or `none`, " \
|
|
97
|
+
"separated by a comma and a space")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Each cycle among a workflow's jobs, named once from the first job in it.
|
|
102
|
+
def check_cycles(workflow)
|
|
103
|
+
needs = needs_among(workflow)
|
|
104
|
+
reported = []
|
|
105
|
+
needs.each_key do |name|
|
|
106
|
+
cycle = cycle_from(name, needs) or next
|
|
107
|
+
next if reported.include?(cycle.sort)
|
|
108
|
+
|
|
109
|
+
reported << cycle.sort
|
|
110
|
+
problem(workflow, "has jobs that need each other in a circle: #{[*cycle, cycle.first].join(" -> ")}")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @return [Hash{String => Array<String>}] each job's name to the declared jobs it needs
|
|
115
|
+
def needs_among(workflow)
|
|
116
|
+
names = workflow.jobs.map(&:name)
|
|
117
|
+
workflow.jobs.to_h { |job| [job.name, job.needs & names] }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @return [Array<String>, nil] the jobs of a cycle that begins and ends at `start`
|
|
121
|
+
def cycle_from(start, needs, path = [start])
|
|
122
|
+
needs.fetch(path.last).each do |next_job|
|
|
123
|
+
return path if next_job == start
|
|
124
|
+
next if path.include?(next_job)
|
|
125
|
+
|
|
126
|
+
found = cycle_from(start, needs, [*path, next_job])
|
|
127
|
+
return found if found
|
|
128
|
+
end
|
|
129
|
+
nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def problem(row, text) = @problems << "#{row.label} #{text}"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Projections
|
|
5
|
+
module CiPipeline
|
|
6
|
+
class Table
|
|
7
|
+
# How a row finds what it belongs to: the workflow, job and step its fields name, and the
|
|
8
|
+
# refusal, naming what is declared, when there is none. Mixed into `Rows`, which holds the
|
|
9
|
+
# joined workflows in `@workflows` and the problems in `@problems`.
|
|
10
|
+
module Lookup
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def workflow_of(row)
|
|
14
|
+
found = @workflows.find { |workflow| workflow.name == row[:workflow] }
|
|
15
|
+
return found if found
|
|
16
|
+
|
|
17
|
+
problem(row, "names workflow #{row[:workflow].inspect}, which no Workflow row declares; " \
|
|
18
|
+
"its workflows are #{@workflows.map(&:name).join(", ")}")
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def job_of(row)
|
|
23
|
+
workflow = workflow_of(row) or return
|
|
24
|
+
found = workflow.jobs.find { |job| job.name == row[:job] }
|
|
25
|
+
return found if found
|
|
26
|
+
|
|
27
|
+
problem(row, "names job #{row[:job].inspect}, which workflow #{row[:workflow]} does not declare; " \
|
|
28
|
+
"its jobs are #{workflow.jobs.map(&:name).join(", ")}")
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def step_of(job, row)
|
|
33
|
+
found = job.steps.find { |candidate| candidate.name == row[:step] }
|
|
34
|
+
return found if found
|
|
35
|
+
|
|
36
|
+
problem(row, "names step #{row[:step].inspect}, which job #{row[:job]} does not declare; " \
|
|
37
|
+
"its steps are #{job.steps.map(&:name).join(", ")}")
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def check_pattern(row, pattern, field, reason)
|
|
42
|
+
regexp = @vocabulary.fetch(:patterns).fetch(pattern)
|
|
43
|
+
return if row[field].is_a?(String) && regexp.match?(row[field])
|
|
44
|
+
|
|
45
|
+
problem(row, "has #{field} #{row[field].inspect}; #{reason}, matching #{regexp.source}")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def twice(row, declared)
|
|
49
|
+
return unless declared
|
|
50
|
+
|
|
51
|
+
problem(row, "is declared twice")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def problem(row, text) = @problems << "#{row.fetch(:label)} #{text}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Projections
|
|
5
|
+
module CiPipeline
|
|
6
|
+
class Table
|
|
7
|
+
# The refusals a row earns from the bluebook's closed sets and from what its job declares,
|
|
8
|
+
# each naming the row and listing what is valid. Mixed into `Rows`, which holds the
|
|
9
|
+
# vocabulary in `@vocabulary` and the problems in `@problems`.
|
|
10
|
+
module Refusals
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def refuse_event(row)
|
|
14
|
+
events = @vocabulary.fetch(:trigger)
|
|
15
|
+
return if events.include?(row[:event])
|
|
16
|
+
|
|
17
|
+
problem(row, "has event #{row[:event].inspect}; an event is one of #{events.join(", ")}")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def refuse_unknown_need(row)
|
|
21
|
+
names = workflow_of(row).jobs.map(&:name)
|
|
22
|
+
return if names.include?(row[:needs])
|
|
23
|
+
|
|
24
|
+
problem(row, "names job #{row[:needs].inspect}, which workflow #{row[:workflow]} does not declare; " \
|
|
25
|
+
"its jobs are #{names.join(", ")}")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# A step uses an action or runs a command, and an action is one the bluebook admits.
|
|
29
|
+
def refuse_uses(row)
|
|
30
|
+
uses = row[:uses]
|
|
31
|
+
refuse_both(row) unless uses.empty? || row[:run].empty?
|
|
32
|
+
refuse_neither(row) if uses.empty? && row[:run].empty?
|
|
33
|
+
refuse_action(row) unless uses.empty?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def refuse_both(row)
|
|
37
|
+
problem(row, "has both uses and run; a step uses an action or runs a command, not both")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def refuse_neither(row)
|
|
41
|
+
problem(row, "has neither uses nor run; a step uses an action or runs a command")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def refuse_action(row)
|
|
45
|
+
actions = @vocabulary.fetch(:uses)
|
|
46
|
+
return if actions.include?(row[:uses])
|
|
47
|
+
|
|
48
|
+
problem(row, "has uses #{row[:uses].inspect}; uses is one of #{actions.join(", ")}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def refuse_input_of_command(row)
|
|
52
|
+
problem(row, "names a step that runs a command; only a step that uses an action takes inputs")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tree"
|
|
4
|
+
require_relative "typing"
|
|
5
|
+
require_relative "lookup"
|
|
6
|
+
require_relative "refusals"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module Projections
|
|
10
|
+
module CiPipeline
|
|
11
|
+
class Table
|
|
12
|
+
# Joins the declared member rows into a tree of workflows, jobs and steps: each row is
|
|
13
|
+
# joined to its workflow and job by name, and each closed-set value is checked against
|
|
14
|
+
# the CiPipeline bluebook's vocabulary. A row that names what is not declared is refused,
|
|
15
|
+
# with what is declared listed.
|
|
16
|
+
class Rows
|
|
17
|
+
include Lookup
|
|
18
|
+
include Refusals
|
|
19
|
+
|
|
20
|
+
# The bluebook value objects whose pattern a field's text must match, by name.
|
|
21
|
+
PATTERNS = { workflow: %w[Workflow WorkflowName], secret: %w[Workflow SecretName],
|
|
22
|
+
env: %w[JobSpec EnvName], output: %w[JobSpec OutputKey], step_id: %w[JobSpec StepId],
|
|
23
|
+
shard_axis: %w[JobSpec ShardAxis] }.freeze
|
|
24
|
+
|
|
25
|
+
# The row objects in the order they are joined, each with the method that joins one row.
|
|
26
|
+
JOINS = { "Trigger" => :join_trigger, "Secret" => :join_secret, "Job" => :join_job,
|
|
27
|
+
"Need" => :join_need, "Output" => :join_output, "Env" => :join_env,
|
|
28
|
+
"Step" => :join_step, "StepInput" => :join_input }.freeze
|
|
29
|
+
|
|
30
|
+
# @return [Array<Tree::Workflow>] the workflows, in the order declared
|
|
31
|
+
attr_reader :workflows
|
|
32
|
+
|
|
33
|
+
# @param rows [Hash{String => Array<Hash{Symbol => Object}>}] each object's declared rows
|
|
34
|
+
# @param vocabulary [Hash{Symbol => Object}] the closed sets and patterns
|
|
35
|
+
# @param problems [Array<String>] collects each problem found, one line each
|
|
36
|
+
def initialize(rows, vocabulary, problems)
|
|
37
|
+
@vocabulary = vocabulary
|
|
38
|
+
@problems = problems
|
|
39
|
+
@typed = type_all(rows, Typing.new(problems))
|
|
40
|
+
@workflows = []
|
|
41
|
+
@typed.fetch("Workflow").each { |row| @workflows << build_workflow(row) }
|
|
42
|
+
JOINS.each { |object, join| @typed.fetch(object).each { |row| send(join, row) } }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def type_all(rows, typing)
|
|
48
|
+
rows.to_h { |object, members| [object, members.each_with_index.map { |row, i| typing.call(object, row, i) }] }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def build_workflow(row)
|
|
52
|
+
check_pattern(row, :workflow, :name, "a workflow is named by its file")
|
|
53
|
+
twice(row, @workflows.any? { |workflow| workflow.name == row[:name] })
|
|
54
|
+
fields = row.slice(:label, :name, :display_name, :note, :concurrency_group, :cancel_in_progress)
|
|
55
|
+
Tree::Workflow.new(**fields, triggers: [], secrets: [], jobs: [])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def join_trigger(row)
|
|
59
|
+
workflow = workflow_of(row) or return
|
|
60
|
+
refuse_event(row)
|
|
61
|
+
twice(row, workflow.triggers.include?(row[:event]))
|
|
62
|
+
workflow.triggers << row[:event]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def join_secret(row)
|
|
66
|
+
workflow = workflow_of(row) or return
|
|
67
|
+
check_pattern(row, :secret, :name, "a secret is named in capitals")
|
|
68
|
+
twice(row, workflow.secrets.any? { |secret| secret.name == row[:name] })
|
|
69
|
+
workflow.secrets << Tree::Secret.new(row[:name], row[:required])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def join_job(row)
|
|
73
|
+
workflow = workflow_of(row) or return
|
|
74
|
+
twice(row, workflow.jobs.any? { |job| job.name == row[:name] })
|
|
75
|
+
check_pattern(row, :shard_axis, :shard_axis, "a matrix is named in lower case") unless row[:shard_axis].empty?
|
|
76
|
+
fields = row.slice(:label, :name, :runner, :timeout_minutes, :permissions, :condition, :shard_total,
|
|
77
|
+
:shard_axis, :note)
|
|
78
|
+
workflow.jobs << Tree::Job.new(**fields, needs: [], outputs: [], env: [], steps: [])
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def join_need(row)
|
|
82
|
+
job = job_of(row) or return
|
|
83
|
+
refuse_unknown_need(row)
|
|
84
|
+
twice(row, job.needs.include?(row[:needs]))
|
|
85
|
+
job.needs << row[:needs]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def join_output(row) = join_pair(row, :output, :outputs, "an output is named by a key")
|
|
89
|
+
|
|
90
|
+
def join_env(row) = join_pair(row, :env, :env, "a variable is named in capitals")
|
|
91
|
+
|
|
92
|
+
def join_pair(row, pattern, list, reason)
|
|
93
|
+
job = job_of(row) or return
|
|
94
|
+
check_pattern(row, pattern, :key, reason)
|
|
95
|
+
twice(row, job[list].any? { |pair| pair.key == row[:key] })
|
|
96
|
+
job[list] << Tree::Pair.new(row[:key], row[:value])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def join_step(row)
|
|
100
|
+
job = job_of(row) or return
|
|
101
|
+
twice(row, job.steps.any? { |step| step.name == row[:name] })
|
|
102
|
+
check_pattern(row, :step_id, :id, "an id is lower case") unless row[:id].empty?
|
|
103
|
+
refuse_uses(row)
|
|
104
|
+
fields = row.slice(:label, :name, :title, :id, :uses, :run, :condition, :note)
|
|
105
|
+
job.steps << Tree::Step.new(**fields, inputs: [])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def join_input(row)
|
|
109
|
+
job = job_of(row) or return
|
|
110
|
+
step = step_of(job, row) or return
|
|
111
|
+
twice(row, step.inputs.any? { |pair| pair.key == row[:key] })
|
|
112
|
+
refuse_input_of_command(row) if step.uses.empty?
|
|
113
|
+
step.inputs << Tree::Pair.new(row[:key], row[:value])
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Projections
|
|
5
|
+
module CiPipeline
|
|
6
|
+
class Table
|
|
7
|
+
# The workflows a table of rows joins into: each workflow holds its triggers, secrets and
|
|
8
|
+
# jobs, each job its needs, outputs, environment and steps, each step its `with:` inputs.
|
|
9
|
+
module Tree
|
|
10
|
+
# One workflow file with the rows that belong to it.
|
|
11
|
+
Workflow = Struct.new(:label, :name, :display_name, :note, :concurrency_group, :cancel_in_progress,
|
|
12
|
+
:triggers, :secrets, :jobs, keyword_init: true)
|
|
13
|
+
|
|
14
|
+
# One secret a called workflow takes.
|
|
15
|
+
Secret = Struct.new(:name, :required)
|
|
16
|
+
|
|
17
|
+
# One job with the rows that belong to it.
|
|
18
|
+
Job = Struct.new(:label, :name, :runner, :timeout_minutes, :permissions, :condition, :shard_total,
|
|
19
|
+
:shard_axis, :note, :needs, :outputs, :env, :steps, keyword_init: true)
|
|
20
|
+
|
|
21
|
+
# One step with its `with:` inputs.
|
|
22
|
+
Step = Struct.new(:label, :name, :title, :id, :uses, :run, :condition, :note, :inputs, keyword_init: true)
|
|
23
|
+
|
|
24
|
+
# A key and its value: a job output, an environment variable or a step input.
|
|
25
|
+
Pair = Struct.new(:key, :value)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Projections
|
|
5
|
+
module CiPipeline
|
|
6
|
+
class Table
|
|
7
|
+
# Checks the fields of each declared row and their types, and fills the defaults, so a row
|
|
8
|
+
# reaches the join as a hash of every field its object may carry.
|
|
9
|
+
class Typing
|
|
10
|
+
# The fields a row of each object may carry, with the Ruby class each takes (`:bool` is
|
|
11
|
+
# true or false). The order is the order the objects are joined in.
|
|
12
|
+
SHAPES = {
|
|
13
|
+
"Workflow" => { name: String, display_name: String, note: String, concurrency_group: String,
|
|
14
|
+
cancel_in_progress: :bool },
|
|
15
|
+
"Trigger" => { workflow: String, event: String },
|
|
16
|
+
"Secret" => { workflow: String, name: String, required: :bool },
|
|
17
|
+
"Job" => { workflow: String, name: String, runner: String, timeout_minutes: Integer,
|
|
18
|
+
permissions: String, condition: String, shard_total: Integer, shard_axis: String,
|
|
19
|
+
note: String },
|
|
20
|
+
"Need" => { workflow: String, job: String, needs: String },
|
|
21
|
+
"Output" => { workflow: String, job: String, key: String, value: String },
|
|
22
|
+
"Env" => { workflow: String, job: String, key: String, value: String },
|
|
23
|
+
"Step" => { workflow: String, job: String, name: String, title: String, id: String, uses: String,
|
|
24
|
+
run: String, condition: String, note: String },
|
|
25
|
+
"StepInput" => { workflow: String, job: String, step: String, key: String, value: String }
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
# The fields a row must name; every other field has a default.
|
|
29
|
+
REQUIRED = {
|
|
30
|
+
"Workflow" => %i[name display_name], "Trigger" => %i[workflow event],
|
|
31
|
+
"Secret" => %i[workflow name], "Job" => %i[workflow name runner timeout_minutes],
|
|
32
|
+
"Need" => %i[workflow job needs], "Output" => %i[workflow job key value],
|
|
33
|
+
"Env" => %i[workflow job key value], "Step" => %i[workflow job name],
|
|
34
|
+
"StepInput" => %i[workflow job step key value]
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
# The shard total of a job that is not split into legs.
|
|
38
|
+
UNSHARDED = 1
|
|
39
|
+
|
|
40
|
+
# The fields whose values name the row, in the order a label lists them.
|
|
41
|
+
IDENTITY = %i[workflow job step name event needs key].freeze
|
|
42
|
+
|
|
43
|
+
# @param problems [Array<String>] collects each problem found, one line each
|
|
44
|
+
def initialize(problems)
|
|
45
|
+
@problems = problems
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param object [String] the row object's name, such as `Step`
|
|
49
|
+
# @param member [Hash{Symbol => Object}] the declared fields of one row
|
|
50
|
+
# @param index [Integer] the row's position, for a label when the row names nothing
|
|
51
|
+
# @return [Hash{Symbol => Object}] the row's `:label`, and each field, defaults filled
|
|
52
|
+
def call(object, member, index)
|
|
53
|
+
label = label_of(object, member, index)
|
|
54
|
+
shape = SHAPES.fetch(object)
|
|
55
|
+
refuse(label, member, shape, REQUIRED.fetch(object))
|
|
56
|
+
fields = shape.to_h { |key, type| [key, member.fetch(key) { default(object, key, type) }] }
|
|
57
|
+
{ label: label, **fields }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def refuse(label, member, shape, required)
|
|
63
|
+
(member.keys - shape.keys).each do |key|
|
|
64
|
+
problem(label, "has no field #{key}; fields are #{shape.keys.join(", ")}")
|
|
65
|
+
end
|
|
66
|
+
member.slice(*shape.keys).each { |key, value| check_type(label, key, value, shape.fetch(key)) }
|
|
67
|
+
(required - member.keys).each { |key| problem(label, "has no #{key}") }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def label_of(object, member, index)
|
|
71
|
+
identity = member.values_at(*IDENTITY).compact
|
|
72
|
+
"#{object} #{identity.empty? ? "row #{index + 1}" : identity.join("/")}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def default(object, key, type)
|
|
76
|
+
return UNSHARDED if object == "Job" && key == :shard_total
|
|
77
|
+
|
|
78
|
+
{ String => "", Integer => nil, bool: false }.fetch(type)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def check_type(label, key, value, expected)
|
|
82
|
+
return if expected == :bool ? [true, false].include?(value) : value.is_a?(expected)
|
|
83
|
+
|
|
84
|
+
problem(label, "has #{key} #{value.inspect}; #{key} is #{expected == :bool ? "true or false" : "a #{expected}"}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def problem(label, text) = @problems << "#{label} #{text}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|