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
|
@@ -4,7 +4,6 @@ module Hecks
|
|
|
4
4
|
class Plan
|
|
5
5
|
# One append command: the verb, and the value-object-field -> argument map.
|
|
6
6
|
# `:map` shadows Enumerable#map on purpose; spec/plan_spec.rb asserts on it.
|
|
7
|
-
# rubocop:disable-next Lint/StructNewOverride
|
|
8
7
|
Append = Struct.new(:verb, :map, keyword_init: true)
|
|
9
8
|
|
|
10
9
|
# One setting command. `targets` is target -> argument ; Lifecycle sets two
|
|
@@ -12,7 +11,7 @@ module Hecks
|
|
|
12
11
|
Setter = Struct.new(:verb, :targets, keyword_init: true)
|
|
13
12
|
|
|
14
13
|
Category = Struct.new(:name, :declare, :parent, :parent_key, :fields,
|
|
15
|
-
:appends, :alternates, :setters, :sealers, :references,
|
|
14
|
+
:appends, :alternates, :setters, :sealers, :references, :lists,
|
|
16
15
|
:identity_paths, :entity_owned,
|
|
17
16
|
keyword_init: true) do
|
|
18
17
|
# Every verb this category declares, in declaration order; a verb missing
|
|
@@ -35,6 +34,15 @@ module Hecks
|
|
|
35
34
|
Array(references[verb.to_s]).include?(argument.to_s)
|
|
36
35
|
end
|
|
37
36
|
|
|
37
|
+
# Whether `argument` on `verb` is a list, so each of its items is one value.
|
|
38
|
+
#
|
|
39
|
+
# @param verb [String] the command name declaring `argument`
|
|
40
|
+
# @param argument [String] the argument name to check
|
|
41
|
+
# @return [Boolean] whether `argument` on `verb` is declared as a list
|
|
42
|
+
def list?(verb, argument)
|
|
43
|
+
Array(lists&.dig(verb.to_s)).include?(argument.to_s)
|
|
44
|
+
end
|
|
45
|
+
|
|
38
46
|
# Whether this category has no parent — the root of the containment tree.
|
|
39
47
|
def root? = parent.nil?
|
|
40
48
|
end
|
|
@@ -15,6 +15,15 @@ module Hecks
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
# Which arguments of which verbs are lists, read straight off the IR, so a list
|
|
19
|
+
# argument's items are each wrapped as a value rather than the list as one.
|
|
20
|
+
def lists_in(commands)
|
|
21
|
+
commands.each_with_object({}) do |command, found|
|
|
22
|
+
named = command.attributes.select(&:list?).map { |attribute| attribute.name.to_s }
|
|
23
|
+
found[command.hecks_name] = named unless named.empty?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
18
27
|
# Every reference argument is dropped, not just the parent link:
|
|
19
28
|
# a reference is not a field.
|
|
20
29
|
def declared_fields(declare)
|
|
@@ -126,7 +126,8 @@ module Hecks
|
|
|
126
126
|
sealers: sealers_in(rest),
|
|
127
127
|
# Every command, not `rest` — the creating command carries the parent
|
|
128
128
|
# link, which is the most common reference of all.
|
|
129
|
-
references: references_in(aggregate.commands)
|
|
129
|
+
references: references_in(aggregate.commands),
|
|
130
|
+
lists: lists_in(aggregate.commands)
|
|
130
131
|
}
|
|
131
132
|
end
|
|
132
133
|
|
|
@@ -26,7 +26,9 @@ module Hecks
|
|
|
26
26
|
description: text(row[:description]),
|
|
27
27
|
identified_by: identity_paths(row),
|
|
28
28
|
attributes: Array(row[:attributes]).map { |field| attribute(field, id) }
|
|
29
|
-
}.merge(aggregate_rules(row)).merge(lifecycle: lifecycle(row), provenance: provenance(row)
|
|
29
|
+
}.merge(aggregate_rules(row)).merge(lifecycle: lifecycle(row), provenance: provenance(row),
|
|
30
|
+
formerly_known_as: row[:formerly_known_as],
|
|
31
|
+
created_by: row[:created_by])
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
# The rules and projected fields an aggregate row holds.
|
|
@@ -65,10 +65,17 @@ module Hecks
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
def memberships(row)
|
|
69
|
+
Array(row[:modules]).map do |part|
|
|
70
|
+
{ name: text(part[:name]).to_s, vision: text(part[:vision]).to_s, aggregate: text(part[:aggregate]).to_s }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
68
74
|
# Every cell of the meta-domain is a single-field value object, so a row
|
|
69
75
|
# arrives holding Values rather than Strings.
|
|
70
76
|
def text(cell)
|
|
71
77
|
return nil if cell.nil?
|
|
78
|
+
return cell.map { |held| text(held) } if cell.is_a?(Array)
|
|
72
79
|
return cell.to_h.values.first if cell.respond_to?(:to_h) && !cell.is_a?(String)
|
|
73
80
|
|
|
74
81
|
cell
|
|
@@ -66,11 +66,16 @@ module Hecks
|
|
|
66
66
|
classification: text(@declaration[:classification]),
|
|
67
67
|
formerly_known_as: text(@declaration[:formerly_known_as]),
|
|
68
68
|
namespace: text(@declaration[:namespace]),
|
|
69
|
-
|
|
70
|
-
provides: provisions(@declaration)
|
|
69
|
+
**row_fields(@declaration)
|
|
71
70
|
}
|
|
72
71
|
end
|
|
73
72
|
|
|
73
|
+
# The row-valued fields of the bluebook: its attachments, provisions and module memberships.
|
|
74
|
+
def row_fields(declaration)
|
|
75
|
+
{ attaches_to: attached_contexts(declaration), provides: provisions(declaration),
|
|
76
|
+
modules: memberships(declaration) }
|
|
77
|
+
end
|
|
78
|
+
|
|
74
79
|
def policy(row) = declaration("Policy", row)
|
|
75
80
|
|
|
76
81
|
# A process manager's handlers live inline on its own dispatched state,
|
|
@@ -60,6 +60,9 @@ module Hecks
|
|
|
60
60
|
# `idempotent` is held as text like `expect_undelivered`, and emitted as a boolean.
|
|
61
61
|
def idempotent?(row) = text(row[:idempotent]).to_s == "true"
|
|
62
62
|
|
|
63
|
+
# `mints_era` is held as text like `idempotent`, and emitted as a boolean.
|
|
64
|
+
def mints_era?(row) = text(row[:mints_era]).to_s == "true"
|
|
65
|
+
|
|
63
66
|
# Kept as raw text, not decoded: this feeds `Assembly::Marks#where_clause`,
|
|
64
67
|
# which decodes it via `read` — decoding here first would strip a kwarg
|
|
65
68
|
# reference's colon, indistinguishable after from a same-named literal.
|
|
@@ -47,7 +47,7 @@ module Hecks
|
|
|
47
47
|
# @param touch [Boolean] whether to mark it as used (a shipped file is read-only)
|
|
48
48
|
# @return [Hash, nil] the table
|
|
49
49
|
def load_table(path, touch: false)
|
|
50
|
-
table = Marshal.load(File.binread(path))
|
|
50
|
+
table = Marshal.load(File.binread(path))
|
|
51
51
|
FileUtils.touch(path) if touch
|
|
52
52
|
table
|
|
53
53
|
end
|
|
@@ -23,6 +23,33 @@ module Hecks
|
|
|
23
23
|
bluebook.aggregates.filter_map { |aggregate| large_aggregate_finding(aggregate, limit) }
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# An aggregate with no commands has nothing that changes it and no command surface for a
|
|
27
|
+
# diagram to draw from. Reads are queries; a change needs a command.
|
|
28
|
+
#
|
|
29
|
+
# @param bluebook [Bluebook::Declaration] the assembled bluebook to check
|
|
30
|
+
# @return [Array<Finding>] one :no_command_surface error per aggregate with no commands
|
|
31
|
+
def no_command_surface_findings(bluebook)
|
|
32
|
+
unacknowledged_commandless(bluebook).map do |aggregate|
|
|
33
|
+
Finding.new(kind: :no_command_surface, severity: :error, subject: aggregate.hecks_name,
|
|
34
|
+
message: "declares no commands, so nothing changes it and no command surface can " \
|
|
35
|
+
"be drawn — give it a command")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Array<Bluebook::Aggregate>] the aggregates with no commands that do not acknowledge it
|
|
40
|
+
def unacknowledged_commandless(bluebook)
|
|
41
|
+
commandless = bluebook.aggregates.select { |aggregate| aggregate.commands.empty? }
|
|
42
|
+
commandless.reject { |aggregate| Acknowledgements.held?(aggregate, :no_command_surface) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Every finding about an aggregate's size and its command surface.
|
|
46
|
+
#
|
|
47
|
+
# @param bluebook [Bluebook::Declaration] the assembled bluebook to check
|
|
48
|
+
# @return [Array<Finding>] the size and command-surface findings, in that order
|
|
49
|
+
def aggregate_findings(bluebook)
|
|
50
|
+
[*large_aggregate_findings(bluebook), *no_command_surface_findings(bluebook)]
|
|
51
|
+
end
|
|
52
|
+
|
|
26
53
|
# @return [Finding, nil] the warning for an aggregate heavier than `limit`
|
|
27
54
|
def large_aggregate_finding(aggregate, limit)
|
|
28
55
|
weight = aggregate_weight(aggregate)
|
|
@@ -36,6 +36,31 @@ module Hecks
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
# Flags a query the hecksagon binds to a port's adapter. Only the Ruby runtime asks an
|
|
40
|
+
# adapter for an answer; a Rust host would find nothing behind the query.
|
|
41
|
+
#
|
|
42
|
+
# @param bluebook [Bluebook::Declaration] the assembled bluebook, its hecksagon's ports
|
|
43
|
+
# attached
|
|
44
|
+
# @param rust_target [Boolean] whether this domain has a real Rust target; a domain without
|
|
45
|
+
# one is not checked, since nothing but the Ruby runtime serves it
|
|
46
|
+
# @return [Array<Finding>] one :external_query error per bound query, none off a Rust target
|
|
47
|
+
def external_query_findings(bluebook, rust_target: false)
|
|
48
|
+
return [] unless rust_target
|
|
49
|
+
|
|
50
|
+
bluebook.aggregates.flat_map do |aggregate|
|
|
51
|
+
aggregate.ports.flat_map do |port|
|
|
52
|
+
port.answered_queries.map { |answer| external_query_finding(aggregate, port, answer) }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def external_query_finding(aggregate, port, answer)
|
|
58
|
+
Finding.new(kind: :external_query, severity: :error,
|
|
59
|
+
subject: "#{aggregate.hecks_name}.#{answer.name}",
|
|
60
|
+
message: "the #{port.name} port's adapter answers this query, and only the Ruby " \
|
|
61
|
+
"runtime asks an adapter — the Rust host cannot serve it")
|
|
62
|
+
end
|
|
63
|
+
|
|
39
64
|
private
|
|
40
65
|
|
|
41
66
|
def port_trigger_finding(bluebook, policy)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require_relative "../ask_resolution"
|
|
2
|
+
require_relative "reaction_cycles"
|
|
3
|
+
require_relative "reaction_walk"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Bluebook
|
|
7
|
+
module ModelCheck
|
|
8
|
+
# The reaction graph of one bluebook: which verb emits which event, which policy reacts to
|
|
9
|
+
# it, and which verb that policy dispatches in turn, an `ask` resolved through the
|
|
10
|
+
# hecksagon to its port operation. `from` walks it to the longest chain a verb's events start.
|
|
11
|
+
#
|
|
12
|
+
# A policy already on the path is not followed again: a loop is cut where it closes, so a
|
|
13
|
+
# chain counts each policy once; `cycles` reports the loops themselves. A cross-domain
|
|
14
|
+
# (`across`) policy ends a chain, since the other domain's policies are not in this
|
|
15
|
+
# bluebook. A `where` is not evaluated, so a chain is the deepest one the declarations
|
|
16
|
+
# allow, not one a run is certain to take.
|
|
17
|
+
class ReactionChains
|
|
18
|
+
# One reaction step: the policy that fires and the verb it dispatches.
|
|
19
|
+
Step = Struct.new(:policy, :verb) do
|
|
20
|
+
# @return [String] the policy's name
|
|
21
|
+
def policy_name = policy.name
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param bluebook [Bluebook::Declaration] the assembled bluebook, its hecksagon attached
|
|
25
|
+
def initialize(bluebook)
|
|
26
|
+
@bluebook = bluebook
|
|
27
|
+
@emitted = emitted_by_verb
|
|
28
|
+
@policies = bluebook.policies.reject(&:target_domain)
|
|
29
|
+
@dispatch = @policies.to_h { |policy| [policy, dispatched_by(policy)] }
|
|
30
|
+
@successors = @policies.to_h { |policy| [policy, @dispatch[policy] ? reacting_to(@dispatch[policy]) : []] }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @return [Array<Array<String>>] each verb that emits an event, as split_verb parses it
|
|
34
|
+
def verbs = @emitted.keys
|
|
35
|
+
|
|
36
|
+
# @return [Set<Array>] the verbs some policy dispatches, which a longer chain already covers
|
|
37
|
+
def reaction_targets = @dispatch.values.compact.to_set
|
|
38
|
+
|
|
39
|
+
# @param verb [Array<String>] a verb, as `Naming.split_verb` parses it
|
|
40
|
+
# @return [Array<Step>] the longest chain of reactions the verb's events start, in order
|
|
41
|
+
def from(verb) = walk.longest(reacting_to(verb))
|
|
42
|
+
|
|
43
|
+
# @return [Boolean] whether the last `from` stopped searching, so its chain is a lower bound
|
|
44
|
+
def capped? = walk.capped?
|
|
45
|
+
|
|
46
|
+
# @return [Array<Array>] each loop in the graph, as the policies that reach one another
|
|
47
|
+
def cycles = @cycles ||= ReactionCycles.new(@policies, @successors).groups
|
|
48
|
+
|
|
49
|
+
# @param policy [Object] a policy of this bluebook
|
|
50
|
+
# @return [Step] the policy with the verb it dispatches
|
|
51
|
+
def step(policy) = Step.new(policy, @dispatch[policy])
|
|
52
|
+
|
|
53
|
+
# @param policy [Object] a policy of this bluebook
|
|
54
|
+
# @return [Array] the policies the verb it dispatches starts
|
|
55
|
+
def successors(policy) = @successors.fetch(policy)
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def walk = @walk ||= ReactionWalk.new(self, cycles.flatten)
|
|
60
|
+
|
|
61
|
+
# Policies that react to an event the verb emits.
|
|
62
|
+
def reacting_to(verb)
|
|
63
|
+
events = @emitted.fetch(verb, [])
|
|
64
|
+
@policies.select { |policy| events.any? { |aggregate, event| hears?(policy, aggregate, event) } }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def hears?(policy, aggregate, event)
|
|
68
|
+
return false unless policy.event_name == event
|
|
69
|
+
|
|
70
|
+
qualifier = policy.event_qualifier
|
|
71
|
+
qualifier.nil? || Naming.demodulise(qualifier) == aggregate
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def dispatched_by(policy)
|
|
75
|
+
verb = policy.asks? ? asked_verb(policy) : "#{@bluebook.name}::#{policy.trigger_command}"
|
|
76
|
+
Naming.split_verb(verb) if verb
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The port operation an `ask` resolves to, spelled as a trigger names it, or nil.
|
|
80
|
+
def asked_verb(policy)
|
|
81
|
+
outcome = AskResolution.call(@bluebook, policy)
|
|
82
|
+
"#{@bluebook.name}::#{outcome.verb}" if outcome.resolved?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Each verb the bluebook declares to the `[aggregate, event]` pairs it announces.
|
|
86
|
+
def emitted_by_verb
|
|
87
|
+
@bluebook.aggregates.each_with_object({}) do |aggregate, held|
|
|
88
|
+
commands_of(aggregate).each { |verb, events| held[verb] = events.map { |event| [aggregate.hecks_name, event] } }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def commands_of(aggregate)
|
|
93
|
+
prefix = "#{@bluebook.name}::#{aggregate.hecks_name}"
|
|
94
|
+
[*aggregate.commands.map { |command| ["#{prefix}.#{command.hecks_name}", command.emits] },
|
|
95
|
+
*aggregate.entities.flat_map { |entity| entity_commands(prefix, entity) },
|
|
96
|
+
*aggregate.ports.flat_map { |port| operations(prefix, port) }]
|
|
97
|
+
.to_h { |verb, events| [Naming.split_verb(verb), bare_names(events)] }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def bare_names(events) = Array(events).map { |event| event.to_s.split("::").last }
|
|
101
|
+
|
|
102
|
+
def entity_commands(prefix, entity)
|
|
103
|
+
entity.commands.map { |command| ["#{prefix}.#{entity.hecks_name}.#{command.hecks_name}", command.emits] }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def operations(prefix, port)
|
|
107
|
+
port.operations.map do |operation|
|
|
108
|
+
["#{prefix}.#{port.name}.#{operation.hecks_name}", [*operation.emits, operation.answers, operation.refuses].compact]
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module ModelCheck
|
|
4
|
+
# The loops of a reaction graph: groups of policies that can each reach the others through
|
|
5
|
+
# the commands they dispatch (the strongly connected components with a cycle in them, found
|
|
6
|
+
# with Tarjan's algorithm), whether or not any command outside the group starts them.
|
|
7
|
+
class ReactionCycles
|
|
8
|
+
# @param policies [Array] the graph's nodes, in declaration order
|
|
9
|
+
# @param successors [Hash{Object => Array}] the policies each policy's dispatch can start
|
|
10
|
+
def initialize(policies, successors)
|
|
11
|
+
@policies = policies
|
|
12
|
+
@successors = successors
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [Array<Array>] each loop's policies, in declaration order
|
|
16
|
+
def groups
|
|
17
|
+
@index = {}
|
|
18
|
+
@low = {}
|
|
19
|
+
@stack = []
|
|
20
|
+
@found = []
|
|
21
|
+
@policies.each { |policy| connect(policy) unless @index.key?(policy) }
|
|
22
|
+
@found.select { |group| loop?(group) }.map { |group| group.sort_by { |policy| @policies.index(policy) } }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def loop?(group) = group.size > 1 || @successors.fetch(group.first).include?(group.first)
|
|
28
|
+
|
|
29
|
+
def connect(node)
|
|
30
|
+
@index[node] = @low[node] = @index.size
|
|
31
|
+
@stack.push(node)
|
|
32
|
+
@successors.fetch(node).each { |next_node| visit(node, next_node) }
|
|
33
|
+
@found << pop_group(node) if @low[node] == @index[node]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def visit(node, next_node)
|
|
37
|
+
if @index.key?(next_node)
|
|
38
|
+
@low[node] = [@low[node], @index[next_node]].min if @stack.include?(next_node)
|
|
39
|
+
else
|
|
40
|
+
connect(next_node)
|
|
41
|
+
@low[node] = [@low[node], @low[next_node]].min
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def pop_group(root)
|
|
46
|
+
group = []
|
|
47
|
+
group << @stack.pop until group.last.equal?(root)
|
|
48
|
+
group
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require_relative "reaction_chains"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Bluebook
|
|
5
|
+
module ModelCheck
|
|
6
|
+
# The checks over reaction chains. A command whose events start a chain of policies longer
|
|
7
|
+
# than the dispatcher's reaction limit has the reactions past it refused without anyone
|
|
8
|
+
# being told; a chain of exactly the limit runs whole, in both runtimes. A loop of
|
|
9
|
+
# policies, which no limit on the chain's length can describe, is reported as a loop.
|
|
10
|
+
module ReactionDepthChecks
|
|
11
|
+
# @param bluebook [Bluebook::Declaration] the assembled bluebook, its hecksagon attached
|
|
12
|
+
# @param limit [Integer] the reaction depth limit; the dispatcher's own when not given
|
|
13
|
+
# @return [Array<Finding>] a warning for each entry command whose longest chain exceeds
|
|
14
|
+
# `limit`, for each loop of policies, and for each chain search that gave up
|
|
15
|
+
def reaction_depth_findings(bluebook, limit: Hecks::Runtime::Dispatcher::MAX_REACTION_DEPTH)
|
|
16
|
+
chains = ReactionChains.new(bluebook)
|
|
17
|
+
[*(chains.verbs - chains.reaction_targets.to_a).flat_map { |verb| chain_findings(chains, verb, limit) },
|
|
18
|
+
*chains.cycles.map { |policies| loop_finding(policies, limit) }]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Array<Finding>] the deep-chain warning for the verb, and the search warning if
|
|
22
|
+
# the walk gave up
|
|
23
|
+
def chain_findings(chains, verb, limit)
|
|
24
|
+
chain = chains.from(verb)
|
|
25
|
+
[(deep_chain_finding(verb, chain, limit) if chain.size > limit),
|
|
26
|
+
(capped_search_finding(verb, chain) if chains.capped?)].compact
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [Finding] the warning naming every policy of a loop
|
|
30
|
+
def loop_finding(policies, limit)
|
|
31
|
+
names = policies.map(&:name)
|
|
32
|
+
Finding.new(kind: :unbounded_reaction_loop, severity: :warning, subject: names.join(", "),
|
|
33
|
+
message: "policies #{names.join(", ")} reach one another, so a command that starts " \
|
|
34
|
+
"them reacts until the reaction depth limit of #{limit}, and the " \
|
|
35
|
+
"#{limit + 1}th reaction is refused without anyone being told")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Finding] the warning that the chain found for the verb is a lower bound
|
|
39
|
+
def capped_search_finding(verb, chain)
|
|
40
|
+
Finding.new(kind: :reaction_chain_search_capped, severity: :warning, subject: verb_text(verb),
|
|
41
|
+
message: "the search for the longest chain stopped after " \
|
|
42
|
+
"#{ReactionWalk::WORK_LIMIT} steps; the chain of #{chain.size} reactions is a lower bound")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Finding] the warning naming the entry verb and each policy and verb of its chain
|
|
46
|
+
def deep_chain_finding(verb, chain, limit)
|
|
47
|
+
path = chain.map { |step| "#{step.policy_name} -> #{verb_text(step.verb)}" }.join(" -> ")
|
|
48
|
+
Finding.new(kind: :deep_reaction_chain, severity: :warning, subject: verb_text(verb),
|
|
49
|
+
message: "starts a chain of #{chain.size} reactions, past the reaction depth " \
|
|
50
|
+
"limit of #{limit}: the #{limit + 1}th and any after it are refused: " \
|
|
51
|
+
"#{verb_text(verb)} -> #{path}")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def verb_text(verb) = "#{verb[0]}::#{verb[1]}.#{verb[2]}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module ModelCheck
|
|
4
|
+
# The longest chain of reactions a policy starts, counting each policy once per chain. A
|
|
5
|
+
# policy that reaches no loop has one longest chain whatever path led to it, so those are
|
|
6
|
+
# remembered; the rest are searched path by path, and the search stops after `WORK_LIMIT`
|
|
7
|
+
# steps per chain, which `capped?` reports.
|
|
8
|
+
class ReactionWalk
|
|
9
|
+
# Policies visited by one search before it gives up and answers the best chain so far.
|
|
10
|
+
WORK_LIMIT = 10_000
|
|
11
|
+
|
|
12
|
+
# @param graph [ReactionChains] answers `step(policy)` and `successors(policy)`
|
|
13
|
+
# @param looping [Array] the policies that lie on a loop
|
|
14
|
+
def initialize(graph, looping)
|
|
15
|
+
@graph = graph
|
|
16
|
+
@looping = looping.to_set
|
|
17
|
+
@settled = {}
|
|
18
|
+
@reaches = {}
|
|
19
|
+
@work = 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @param starts [Array] the policies the first event reaches
|
|
23
|
+
# @return [Array<ReactionChains::Step>] the longest chain, in order
|
|
24
|
+
def longest(starts)
|
|
25
|
+
@work = 0
|
|
26
|
+
@capped = false
|
|
27
|
+
starts.map { |policy| search(policy, []) }.max_by(&:size) || []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Boolean] whether the last `longest` gave up, so its chain is a lower bound
|
|
31
|
+
def capped? = @capped
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def search(policy, path)
|
|
36
|
+
return settled(policy) unless reaches_loop?(policy)
|
|
37
|
+
return give_up if (@work += 1) > WORK_LIMIT
|
|
38
|
+
|
|
39
|
+
open = @graph.successors(policy) - path - [policy]
|
|
40
|
+
[@graph.step(policy)] + (open.map { |next_policy| search(next_policy, [*path, policy]) }.max_by(&:size) || [])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def give_up
|
|
44
|
+
@capped = true
|
|
45
|
+
[]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def settled(policy)
|
|
49
|
+
@settled[policy] ||= [@graph.step(policy)] +
|
|
50
|
+
(@graph.successors(policy).map { |next_policy| settled(next_policy) }.max_by(&:size) || [])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def reaches_loop?(policy)
|
|
54
|
+
@reaches.fetch(policy) do
|
|
55
|
+
onward = @graph.successors(policy)
|
|
56
|
+
@reaches[policy] = @looping.include?(policy) || onward.any? { |next_policy| reaches_loop?(next_policy) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -7,6 +7,7 @@ require_relative "model_check/policy_checks"
|
|
|
7
7
|
require_relative "model_check/context_checks"
|
|
8
8
|
require_relative "model_check/context_map_checks"
|
|
9
9
|
require_relative "model_check/ask_checks"
|
|
10
|
+
require_relative "model_check/reaction_depth_checks"
|
|
10
11
|
require_relative "model_check/reference_checks"
|
|
11
12
|
require_relative "model_check/orphan_checks"
|
|
12
13
|
require_relative "model_check/one_of_checks"
|
|
@@ -41,6 +42,7 @@ module Hecks
|
|
|
41
42
|
extend PolicyChecks
|
|
42
43
|
extend ContextChecks
|
|
43
44
|
extend AskChecks
|
|
45
|
+
extend ReactionDepthChecks
|
|
44
46
|
extend ReferenceChecks
|
|
45
47
|
extend OrphanChecks
|
|
46
48
|
extend OneOfChecks
|
|
@@ -78,10 +80,11 @@ module Hecks
|
|
|
78
80
|
[
|
|
79
81
|
*bluebook.aggregates.flat_map { |aggregate| aggregate_lifecycle_findings(aggregate) },
|
|
80
82
|
*reference_findings(bluebook),
|
|
81
|
-
*
|
|
83
|
+
*aggregate_findings(bluebook),
|
|
82
84
|
*bluebook.process_managers.flat_map { |process_manager| saga_findings(bluebook, process_manager) },
|
|
83
85
|
*reaction_findings(bluebook, options),
|
|
84
|
-
*unused_ask_findings(bluebook)
|
|
86
|
+
*unused_ask_findings(bluebook),
|
|
87
|
+
*reaction_depth_findings(bluebook)
|
|
85
88
|
]
|
|
86
89
|
end
|
|
87
90
|
|
|
@@ -112,31 +115,6 @@ module Hecks
|
|
|
112
115
|
aggregate.entities.flat_map { |entity| lifecycle_findings(aggregate, entity) }
|
|
113
116
|
end
|
|
114
117
|
|
|
115
|
-
# Flags a query the hecksagon binds to a port's adapter. Only the Ruby runtime asks an
|
|
116
|
-
# adapter for an answer; a Rust host would find nothing behind the query.
|
|
117
|
-
#
|
|
118
|
-
# @param bluebook [Bluebook::Declaration] the assembled bluebook, its hecksagon's ports
|
|
119
|
-
# attached
|
|
120
|
-
# @param rust_target [Boolean] whether this domain has a real Rust target; a domain without
|
|
121
|
-
# one is not checked, since nothing but the Ruby runtime serves it
|
|
122
|
-
# @return [Array<Finding>] one :external_query error per bound query, none off a Rust target
|
|
123
|
-
def external_query_findings(bluebook, rust_target: false)
|
|
124
|
-
return [] unless rust_target
|
|
125
|
-
|
|
126
|
-
bluebook.aggregates.flat_map do |aggregate|
|
|
127
|
-
aggregate.ports.flat_map do |port|
|
|
128
|
-
port.answered_queries.map { |answer| external_query_finding(aggregate, port, answer) }
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def external_query_finding(aggregate, port, answer)
|
|
134
|
-
Finding.new(kind: :external_query, severity: :error,
|
|
135
|
-
subject: "#{aggregate.hecks_name}.#{answer.name}",
|
|
136
|
-
message: "the #{port.name} port's adapter answers this query, and only the Ruby " \
|
|
137
|
-
"runtime asks an adapter — the Rust host cannot serve it")
|
|
138
|
-
end
|
|
139
|
-
|
|
140
118
|
# Flags an aggregate or domain name that collides with a Rust keyword or reserved
|
|
141
119
|
# Cargo key — both become bare module identifiers with no `r#` escape hatch.
|
|
142
120
|
#
|
|
@@ -54,25 +54,42 @@ module Hecks
|
|
|
54
54
|
correlates_by: -> { correlates_by&.to_s },
|
|
55
55
|
starts_on: :starts_on,
|
|
56
56
|
ends_on: :ends_on,
|
|
57
|
+
endings: :endings,
|
|
58
|
+
resumes: :resumes,
|
|
57
59
|
states: :states,
|
|
58
60
|
handlers: many(:handlers)
|
|
59
61
|
)
|
|
60
62
|
|
|
61
|
-
attr_reader :name, :correlates_by, :starts_on, :ends_on, :states, :handlers
|
|
63
|
+
attr_reader :name, :correlates_by, :starts_on, :ends_on, :endings, :resumes, :states, :handlers
|
|
62
64
|
|
|
63
65
|
# Every optional keyword and what it holds when the declaration omits it.
|
|
64
66
|
FIELD_DEFAULTS = {
|
|
65
|
-
correlates_by: nil, starts_on: nil, ends_on: nil,
|
|
67
|
+
correlates_by: nil, starts_on: nil, ends_on: nil, endings: [], resumes: [],
|
|
68
|
+
states: [], handlers: []
|
|
66
69
|
}.freeze
|
|
67
70
|
|
|
68
71
|
# @param correlates_by [Symbol, nil] the payload field that correlates a triggering
|
|
69
72
|
# event to an instance
|
|
70
73
|
# @param starts_on [String, nil] the event that starts a new instance
|
|
71
|
-
# @param ends_on [String, nil] the event that ends an instance
|
|
74
|
+
# @param ends_on [String, nil] the first event that ends an instance
|
|
75
|
+
# @param endings [Array<String>] every event that ends an instance, in declaration order;
|
|
76
|
+
# empty when the declaration names only `ends_on`
|
|
72
77
|
def initialize(name:, **given)
|
|
73
78
|
KeywordFields.assign(self, KeywordFields.fill(given, FIELD_DEFAULTS))
|
|
74
79
|
@name = name.to_s
|
|
75
80
|
end
|
|
81
|
+
|
|
82
|
+
# Every event that ends an instance. A process manager that declares one `ends_on` has
|
|
83
|
+
# that event alone; one that declares several ends on any of them.
|
|
84
|
+
#
|
|
85
|
+
# @return [Array<String>] the ending events, never empty when `ends_on` is set
|
|
86
|
+
def ending_events = endings.empty? ? [ends_on].compact : endings
|
|
87
|
+
|
|
88
|
+
# Replaces a bare aggregate name with the dotted path the bluebook resolved it to.
|
|
89
|
+
#
|
|
90
|
+
# @param key [String] the `"<Aggregate>.<identity>"` path
|
|
91
|
+
# @return [String] the path now held
|
|
92
|
+
def correlate_by!(key) = @correlates_by = key
|
|
76
93
|
end
|
|
77
94
|
end
|
|
78
95
|
end
|
|
@@ -9,7 +9,6 @@ module Hecks
|
|
|
9
9
|
# One field whose value changed, bridged by an exhaustive lookup table.
|
|
10
10
|
# Paths follow `TranslationMove`; `values` maps each old-era value to its new-era one.
|
|
11
11
|
# `:values` shadows Struct#values on purpose; no caller reads the built-in.
|
|
12
|
-
# rubocop:disable-next Lint/StructNewOverride
|
|
13
12
|
TranslationConvert = Struct.new(:from, :to, :values)
|
|
14
13
|
|
|
15
14
|
# A value object's or entity's type name changed with its members unchanged.
|
|
@@ -27,6 +26,9 @@ module Hecks
|
|
|
27
26
|
# derive has a value; a record where it has none keeps its id.
|
|
28
27
|
TranslationRekey = Struct.new(:to)
|
|
29
28
|
|
|
29
|
+
# ADR 0166: one aggregate's rows fan out into another, keyed by a field both share.
|
|
30
|
+
TranslationSplit = Struct.new(:into, :keyed_by, :fields)
|
|
31
|
+
|
|
30
32
|
# A newly added, required attribute with no source in old data.
|
|
31
33
|
# `default` is what an existing record reads until a command writes a real value;
|
|
32
34
|
# applied in-process by `Lineage#translate` on every adapter.
|
|
@@ -35,12 +37,12 @@ module Hecks
|
|
|
35
37
|
# One aggregate's part of a translation between eras.
|
|
36
38
|
# `drops` makes data loss a declared decision.
|
|
37
39
|
class TranslationAggregate
|
|
38
|
-
attr_reader :name, :was, :renames, :moves, :converts, :drops, :retypes, :derives, :rekeys, :backfills
|
|
40
|
+
attr_reader :name, :was, :renames, :moves, :converts, :drops, :retypes, :derives, :rekeys, :backfills, :splits
|
|
39
41
|
|
|
40
42
|
# Every optional field and what it holds when the declaration omits it.
|
|
41
43
|
FIELD_DEFAULTS = {
|
|
42
44
|
was: nil, renames: {}, moves: [], converts: [], drops: [], retypes: [],
|
|
43
|
-
derives: [], rekeys: [], backfills: []
|
|
45
|
+
derives: [], rekeys: [], backfills: [], splits: []
|
|
44
46
|
}.freeze
|
|
45
47
|
|
|
46
48
|
# @param name [String, Symbol] the aggregate's name in the destination era
|