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,119 @@
|
|
|
1
|
+
require_relative "../lineage"
|
|
2
|
+
require_relative "../../../../ports/persistence/plugins/era/storage_shape"
|
|
3
|
+
require_relative "ledger_change"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class PostgresEra
|
|
8
|
+
module LineageManager
|
|
9
|
+
# The era check of a world that declares `disposable_ledger true` in its PostgresEra
|
|
10
|
+
# `persisted_by` block: a tooling ledger whose rows are worth keeping, not worth an era.
|
|
11
|
+
#
|
|
12
|
+
# Its boot never refuses as unminted or superseded and needs no edge, mint or rehearsal. It
|
|
13
|
+
# holds the first era itself, and on a shape change it re-holds the latest era at the
|
|
14
|
+
# booting shape: an added aggregate gets a head, a widened one keeps its rows as they are,
|
|
15
|
+
# and a replaced one has its rows moved to a dated archive table and starts empty. It names
|
|
16
|
+
# each archive on stderr. A world without the setting never reaches this module.
|
|
17
|
+
module DisposableLedger
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
# Whether a world's persistence settings declare the ledger disposable, spelled as a
|
|
21
|
+
# boolean or as the word. Unset is false, so every other world keeps its era guard.
|
|
22
|
+
#
|
|
23
|
+
# @param settings [Hash{Symbol, String => Object}] the persistence settings of the boot
|
|
24
|
+
# @return [Boolean]
|
|
25
|
+
def declared?(settings) = [true, "true"].include?(PostgresEra.setting(settings, :disposable_ledger, default: false))
|
|
26
|
+
|
|
27
|
+
# Brings the ledger to the booting shape and records the era the boot reads.
|
|
28
|
+
#
|
|
29
|
+
# @param registry [Runtime::Registry] the booting registry; `resolved_eras` is set
|
|
30
|
+
# @param bluebook [Bluebook::Declaration] the bluebook booting now
|
|
31
|
+
# @param current_text [String] its source text, held as the era's text
|
|
32
|
+
# @param settings [Hash{Symbol, String => Object}] the persistence settings of the boot
|
|
33
|
+
# @return [nil] a disposable ledger's boot mints no era
|
|
34
|
+
# @raise [Runtime::WiringError] if the connection is refused or its role is unfenced
|
|
35
|
+
#
|
|
36
|
+
# The world's `stored_as` names are applied first: the boot gates run before the wiring
|
|
37
|
+
# check that applies them, and a re-hold provisions heads under the storage names.
|
|
38
|
+
def check!(registry:, bluebook:, current_text:, settings:)
|
|
39
|
+
registry.apply_world_names!
|
|
40
|
+
db = PostgresEra.connect_for(bluebook.name, settings, provision: true)
|
|
41
|
+
lineage = open_lineage(db, bluebook, settings)
|
|
42
|
+
registry.resolved_eras[bluebook.name] = locked(db, bluebook.name) { reconcile!(lineage, bluebook, current_text) }
|
|
43
|
+
grant!(lineage, bluebook, settings, registry.resolved_eras[bluebook.name])
|
|
44
|
+
nil
|
|
45
|
+
ensure
|
|
46
|
+
db&.close
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The ordinal the ledger holds once it is at the booting shape.
|
|
50
|
+
#
|
|
51
|
+
# @return [Integer]
|
|
52
|
+
def reconcile!(lineage, bluebook, text)
|
|
53
|
+
latest = lineage.eras.last
|
|
54
|
+
return hold_first!(lineage, bluebook, text) unless latest
|
|
55
|
+
|
|
56
|
+
change = LedgerChange.between(held_projection(latest), bluebook)
|
|
57
|
+
apply!(lineage, bluebook, text, change, latest[:ordinal]) if change.changed?
|
|
58
|
+
latest[:ordinal]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Archives every replaced aggregate, gives each added or replaced one a head over the
|
|
62
|
+
# latest era alone, provisions the read side of every aggregate, and re-holds the era.
|
|
63
|
+
def apply!(lineage, bluebook, text, change, ordinal)
|
|
64
|
+
stamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
65
|
+
change.replaced.each { |name| archive!(lineage, bluebook, change.storage_name(bluebook, name), stamp) }
|
|
66
|
+
fresh_heads!(lineage, bluebook, change, ordinal)
|
|
67
|
+
bluebook.aggregates.each { |aggregate| lineage.provision_read_side!(aggregate, ordinal) }
|
|
68
|
+
lineage.rehold!(ordinal, text, Runtime::StorageShape.project(bluebook), Runtime::StorageShape.mint_hash(bluebook))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Gives every added or replaced aggregate the booting bluebook declares a head over the
|
|
72
|
+
# latest era alone: none of its rows are in an earlier era.
|
|
73
|
+
def fresh_heads!(lineage, bluebook, change, ordinal)
|
|
74
|
+
(change.added + change.replaced).filter_map { |name| bluebook.aggregate(name) }
|
|
75
|
+
.each { |aggregate| lineage.fresh_head!(aggregate.storage_name, ordinal) }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def archive!(lineage, bluebook, storage_name, stamp)
|
|
79
|
+
archive, count = lineage.archive_aggregate!(storage_name, stamp)
|
|
80
|
+
warn "[hecks] #{bluebook.name}: the shape of #{storage_name} changed in a way its rows do not fit; " \
|
|
81
|
+
"archived #{count} journal row#{"s" unless count == 1} to #{archive} and started it empty " \
|
|
82
|
+
"(disposable_ledger)"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def hold_first!(lineage, bluebook, text)
|
|
86
|
+
lineage.hold_first!(text, projection: Runtime::StorageShape.project(bluebook))
|
|
87
|
+
lineage.provision_first_era!(bluebook.aggregates)
|
|
88
|
+
1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# The storage shape the latest era holds: the projection its hold recorded, else the
|
|
92
|
+
# shape its held text declares.
|
|
93
|
+
def held_projection(era) = era[:projection] || Runtime::StorageShape.project(LineageManager.shadow(era[:held_text]))
|
|
94
|
+
|
|
95
|
+
def open_lineage(db, bluebook, settings)
|
|
96
|
+
lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as)
|
|
97
|
+
lineage.check_fence_applies!(allow_superuser: PostgresEra.setting(settings, :allow_superuser, default: false))
|
|
98
|
+
lineage.ensure_base!
|
|
99
|
+
lineage
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Holds the domain's era lock, the one a mint takes, for the whole reconcile, so two boots
|
|
103
|
+
# of a changed shape archive once.
|
|
104
|
+
def locked(db, domain)
|
|
105
|
+
db.exec_params("SELECT pg_advisory_lock(hashtext('hecks_eras:' || $1))", [domain])
|
|
106
|
+
yield
|
|
107
|
+
ensure
|
|
108
|
+
db.exec_params("SELECT pg_advisory_unlock(hashtext('hecks_eras:' || $1))", [domain])
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def grant!(lineage, bluebook, settings, ordinal)
|
|
112
|
+
role = PostgresEra.setting(settings, :role)
|
|
113
|
+
lineage.grant_role!(role.to_s, aggregates: bluebook.aggregates, era: ordinal) unless role.to_s.empty?
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
require_relative "../../../../ports/persistence/plugins/era/storage_shape"
|
|
2
|
+
require_relative "mint_decision"
|
|
3
|
+
require_relative "../lineage"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class PostgresEra
|
|
8
|
+
module LineageManager
|
|
9
|
+
# The one answer to which era a bluebook's shape resolves to, given the eras its database
|
|
10
|
+
# holds: the boot records it, the boot status reports it, and the rehearsal and the mint
|
|
11
|
+
# read the held era and the match from it. It writes nothing. A status is one of:
|
|
12
|
+
#
|
|
13
|
+
# - `unheld`: the database holds no era for the bluebook.
|
|
14
|
+
# - `current`: the latest held era holds the current shape.
|
|
15
|
+
# - `superseded`: an older held era holds the current shape; a later one superseded it.
|
|
16
|
+
# - `behind`: no era holds the current shape, and a mint from the latest one would go ahead
|
|
17
|
+
# on its translation edge or recorded implicit move.
|
|
18
|
+
# - `unminted`: no era holds the current shape, and no mint from the latest one would go
|
|
19
|
+
# ahead.
|
|
20
|
+
module EraResolution
|
|
21
|
+
# What a resolution concludes. `resolved` is the era the boot reads (nil when `unheld`),
|
|
22
|
+
# `latest` the latest held era, `verdict` the mint decision from the latest era (nil
|
|
23
|
+
# unless the shape is `behind` or `unminted`), and `held_count` how many eras are held.
|
|
24
|
+
Answer = Data.define(:status, :resolved, :latest, :current_label, :verdict, :held_count,
|
|
25
|
+
:breaking) do
|
|
26
|
+
# @return [Boolean] whether the shape is unminted because the move is breaking and no
|
|
27
|
+
# translation edge covers it, so a boot reads nothing under it and refuses
|
|
28
|
+
def breaking? = breaking == true
|
|
29
|
+
|
|
30
|
+
# @return [Boolean] whether a held era holds the current shape
|
|
31
|
+
def matched? = %w[current superseded].include?(status)
|
|
32
|
+
|
|
33
|
+
# The label of the era the boot reads. An era no edge has left yet has no stored name,
|
|
34
|
+
# so its label is worked out in memory, as its mint would name it; naming is a write,
|
|
35
|
+
# so a resolution never stores it.
|
|
36
|
+
#
|
|
37
|
+
# @return [String, nil] the label; nil when no era is held
|
|
38
|
+
# @raise [Runtime::WiringError] when an unnamed era stores no shape (`refuse_unshaped!`)
|
|
39
|
+
def held_label
|
|
40
|
+
stored = resolved&.fetch(:label, nil)
|
|
41
|
+
return stored if stored || resolved.nil?
|
|
42
|
+
|
|
43
|
+
LineageManager.held_hash(resolved)[0, Runtime::StorageShape::LABEL_LENGTH]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @return [Integer, nil] the ordinal of the era the boot reads
|
|
47
|
+
def ordinal = resolved&.fetch(:ordinal, nil)
|
|
48
|
+
|
|
49
|
+
# @return [String, nil] why the status is what it is; nil for `current`
|
|
50
|
+
def reason = Reasons.of(self)
|
|
51
|
+
|
|
52
|
+
# @return [Boolean] whether a mint from the latest era would go ahead on a recorded
|
|
53
|
+
# implicit move rather than a written translation edge
|
|
54
|
+
def implicit? = verdict&.source == "implicit"
|
|
55
|
+
|
|
56
|
+
# @return [String] the mint decision from the latest era and why, as `verdict: reason`
|
|
57
|
+
def decision = "#{verdict.verdict}: #{verdict.reason}"
|
|
58
|
+
|
|
59
|
+
# @return [Hash, nil] the implicit move a `behind` shape would mint on, or nil
|
|
60
|
+
def move
|
|
61
|
+
return unless status == "behind" && implicit?
|
|
62
|
+
|
|
63
|
+
{ "from" => held_label, "to" => current_label }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String, nil] a sentence when the read era's stored hash is not the hash
|
|
67
|
+
# of its stored projection (a boot still reads it); nil when they agree or the era
|
|
68
|
+
# stores only one of them
|
|
69
|
+
def warning
|
|
70
|
+
recomputed = projection_hash
|
|
71
|
+
return if recomputed.nil? || recomputed == resolved[:hash]
|
|
72
|
+
|
|
73
|
+
"era #{ordinal} stores hash #{resolved[:hash][0, 6]} but its stored projection hashes to #{recomputed[0, 6]}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @return [String, nil] the hash of the read era's stored projection; nil when it stores
|
|
77
|
+
# no hash or no projection
|
|
78
|
+
def projection_hash
|
|
79
|
+
return unless resolved && resolved[:hash] && resolved[:projection]
|
|
80
|
+
|
|
81
|
+
Runtime::ProjectedBluebook.new(resolved[:projection]).mint_hash
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @return [Hash] the answer as a status row, string-keyed for a JSON document; `warning`
|
|
85
|
+
# appears only when `warning` has something to say
|
|
86
|
+
def to_row
|
|
87
|
+
row = { "status" => status, "held" => held_label, "current" => current_label, "ordinal" => ordinal,
|
|
88
|
+
"move" => move, "reason" => reason, "source" => "database" }
|
|
89
|
+
(note = warning) ? row.merge("warning" => note) : row
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
module_function
|
|
94
|
+
|
|
95
|
+
# Resolves the current shape of a bluebook against the eras its database holds.
|
|
96
|
+
#
|
|
97
|
+
# @param eras [Array<Hash>] the held eras, oldest first, as `Lineage#eras` answers them
|
|
98
|
+
# @param bluebook [Bluebook::Declaration] the bluebook as it stands
|
|
99
|
+
# @param translations [Array<Object>] the translation edges the registry loaded
|
|
100
|
+
# @param directory [String, nil] the domain's bluebook directory, where moves are recorded
|
|
101
|
+
# @yieldreturn [Integer] the ledger watermark, read only when no held era matches
|
|
102
|
+
# @return [Answer]
|
|
103
|
+
def resolve(eras:, bluebook:, translations:, directory:)
|
|
104
|
+
facts = { latest: eras.last, current_label: MintDecision.label_of(bluebook), held_count: eras.size }
|
|
105
|
+
return answer("unheld", nil, facts) if eras.empty?
|
|
106
|
+
|
|
107
|
+
matched = matching_era(eras, bluebook)
|
|
108
|
+
return answer(matched.equal?(eras.last) ? "current" : "superseded", matched, facts) if matched
|
|
109
|
+
|
|
110
|
+
unmatched(facts, bluebook, translations, directory, yield)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Resolves a bluebook against the eras its own database holds, over a connection that
|
|
114
|
+
# can only read: nothing is provisioned, and the session refuses any write.
|
|
115
|
+
#
|
|
116
|
+
# @param bluebook [Bluebook::Declaration] the bluebook as it stands
|
|
117
|
+
# @param settings [Hash] the persistence settings its world declares; needs `database`
|
|
118
|
+
# @param translations [Array<Object>] the translation edges the registry loaded
|
|
119
|
+
# @param directory [String, nil] the domain's bluebook directory
|
|
120
|
+
# @return [Answer]
|
|
121
|
+
# @raise [Runtime::WiringError] if the connection is refused or a held text fails its
|
|
122
|
+
# integrity check
|
|
123
|
+
def read(bluebook:, settings:, translations:, directory: nil)
|
|
124
|
+
db = PostgresEra.connect_for(bluebook.name, settings, provision: false)
|
|
125
|
+
db.exec("SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY")
|
|
126
|
+
lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as, reading: true)
|
|
127
|
+
resolve(eras: lineage.eras, bluebook: bluebook, translations: translations, directory: directory) do
|
|
128
|
+
lineage.last_ordinal
|
|
129
|
+
end
|
|
130
|
+
ensure
|
|
131
|
+
db&.close
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# The held era whose shape is the bluebook's: the latest when it holds it, else the
|
|
135
|
+
# oldest that does; nil when none holds it.
|
|
136
|
+
#
|
|
137
|
+
# @param eras [Array<Hash>] the held eras, oldest first
|
|
138
|
+
# @param bluebook [Bluebook::Declaration] the bluebook as it stands
|
|
139
|
+
# @return [Hash, nil] the matching era
|
|
140
|
+
def matching_era(eras, bluebook)
|
|
141
|
+
current = Runtime::StorageShape.project(bluebook)
|
|
142
|
+
[eras.last, *eras].find { |era| held_shape_of(era, bluebook) == current }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# An era's storage shape, with a prior name normalized to the bluebook's. Held text is a
|
|
146
|
+
# frozen record and keeps the prior name; only the in-memory shape is renamed, and only on
|
|
147
|
+
# an exact match with the declared prior name.
|
|
148
|
+
#
|
|
149
|
+
# @param era [Hash] a held era
|
|
150
|
+
# @param bluebook [Bluebook::Declaration] the bluebook as it stands
|
|
151
|
+
# @return [Hash] the storage shape the era holds
|
|
152
|
+
def held_shape_of(era, bluebook)
|
|
153
|
+
shape = LineageManager.held_shape(era)
|
|
154
|
+
prior = bluebook.formerly_known_as
|
|
155
|
+
prior && shape["name"] == prior ? shape.merge("name" => bluebook.name) : shape
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# @return [Answer] a `behind` or `unminted` answer, by the latest era's mint decision
|
|
159
|
+
def unmatched(facts, bluebook, translations, directory, watermark)
|
|
160
|
+
verdict = MintDecision.decide_latest(facts[:latest], bluebook: bluebook, translations: translations,
|
|
161
|
+
directory: directory, watermark: watermark)
|
|
162
|
+
status = verdict.verdict == "would_mint" ? "behind" : "unminted"
|
|
163
|
+
breaking = MintDecision.breaking?(facts[:latest], bluebook, verdict, translations)
|
|
164
|
+
answer(status, facts[:latest], facts, verdict, breaking: breaking)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @return [Answer]
|
|
168
|
+
def answer(status, resolved, facts, verdict = nil, breaking: false)
|
|
169
|
+
Answer.new(status: status, resolved: resolved, verdict: verdict, breaking: breaking, **facts)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# The sentence a status row gives for its status.
|
|
173
|
+
module Reasons
|
|
174
|
+
REMEDY = "write an edge (`era.scaffold_translation`) and mint it with the release mint".freeze
|
|
175
|
+
|
|
176
|
+
module_function
|
|
177
|
+
|
|
178
|
+
# @param answer [Answer] the resolution
|
|
179
|
+
# @return [String, nil] the reason; nil for `current`
|
|
180
|
+
def of(answer)
|
|
181
|
+
case answer.status
|
|
182
|
+
when "unheld" then "no era is held; the mint entry point holds the first"
|
|
183
|
+
when "superseded" then superseded(answer)
|
|
184
|
+
when "behind" then behind(answer)
|
|
185
|
+
when "unminted" then unminted(answer)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# @return [String]
|
|
190
|
+
def superseded(answer)
|
|
191
|
+
"era #{answer.ordinal} holds the current shape #{answer.current_label}; era " \
|
|
192
|
+
"#{answer.latest[:ordinal]} (#{answer.latest[:label]}) superseded it"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# @return [String]
|
|
196
|
+
def behind(answer)
|
|
197
|
+
"no era holds #{answer.current_label}; a mint from era #{answer.ordinal} (#{answer.held_label}) " \
|
|
198
|
+
"would go ahead on its #{answer.implicit? ? "recorded implicit move" : "translation edge"}"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# @return [String] the refusal a boot over a breaking move gives
|
|
202
|
+
def breaking(answer)
|
|
203
|
+
"no translation edge covers it: #{answer.current_label} is not an additive move from " \
|
|
204
|
+
"era #{answer.ordinal} (#{answer.held_label}); #{REMEDY}"
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @return [String]
|
|
208
|
+
def unminted(answer)
|
|
209
|
+
return breaking(answer) if answer.breaking?
|
|
210
|
+
|
|
211
|
+
"no era holds #{answer.current_label}; a mint from era #{answer.ordinal} (#{answer.held_label}) " \
|
|
212
|
+
"is #{answer.decision}"
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
@@ -1,114 +1,111 @@
|
|
|
1
1
|
require_relative "../lineage"
|
|
2
2
|
require_relative "../../../../ports/persistence/plugins/era/storage_shape"
|
|
3
3
|
require_relative "context"
|
|
4
|
+
require_relative "mint_request"
|
|
5
|
+
require_relative "mint_decision"
|
|
6
|
+
require_relative "era_resolution"
|
|
7
|
+
require_relative "disposable_ledger"
|
|
4
8
|
require_relative "../../../../indifferent_key"
|
|
5
9
|
|
|
6
10
|
module Hecks
|
|
7
11
|
module Adapters
|
|
8
12
|
class PostgresEra
|
|
9
13
|
module LineageManager
|
|
10
|
-
# Boot-time era resolution
|
|
11
|
-
#
|
|
14
|
+
# Boot-time era resolution. A boot reads: it reports the era its shape resolves to, and
|
|
15
|
+
# writes nothing. The mint entry point (a settings `mint_request`) is the only path that
|
|
16
|
+
# provisions the lineage or mints an era.
|
|
12
17
|
module EraResolver
|
|
13
18
|
# Whether this copy may mint when its world says nothing about it. False, so a copy that
|
|
14
|
-
# was not told refuses, and only the copy that owns a database moves it.
|
|
19
|
+
# was not told refuses, and only the copy that owns a database moves it. A mint also needs
|
|
20
|
+
# the mint entry point's request (`mint_request` in the settings): a boot never mints.
|
|
15
21
|
MINT_BY_DEFAULT = false
|
|
16
22
|
|
|
17
23
|
# Resolves which era this boot is and records it on the registry.
|
|
18
24
|
#
|
|
25
|
+
# A boot with no mint request opens its lineage for reading and never provisions, holds,
|
|
26
|
+
# mints or grants. A boot with a request provisions the lineage first, then mints if the
|
|
27
|
+
# shape drifted.
|
|
28
|
+
#
|
|
19
29
|
# @return [Integer, nil] the ordinal minted, or nil when this boot minted nothing
|
|
20
30
|
# @raise [Runtime::WiringError] if the connection is refused, a held text fails its
|
|
21
|
-
# integrity check, or the shape is unheld and `mint!` refuses
|
|
31
|
+
# integrity check, no era is held, or the shape is unheld and `mint!` refuses
|
|
22
32
|
def check!(registry:, bluebook:, current_text:, settings:, directory: nil)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
lineage
|
|
29
|
-
# key? first, never `||`: a stored `false` must not read as an absent key.
|
|
30
|
-
role = IndifferentKey.read(settings, :role)
|
|
33
|
+
# A world that declares its ledger disposable has no era guard: see `DisposableLedger`.
|
|
34
|
+
return DisposableLedger.check!(registry:, bluebook:, current_text:, settings:) if DisposableLedger.declared?(settings)
|
|
35
|
+
|
|
36
|
+
request = MintRequest.from(settings)
|
|
37
|
+
db = PostgresEra.connect_for(bluebook.name, settings, provision: !request.nil?)
|
|
38
|
+
lineage = open_lineage(db, bluebook, settings, request)
|
|
31
39
|
resolve_era(Context.new(registry: registry, bluebook: bluebook, current_text: current_text,
|
|
32
|
-
lineage: lineage, role:
|
|
33
|
-
mint_permitted: mint_permitted?(settings)
|
|
40
|
+
lineage: lineage, role: IndifferentKey.read(settings, :role),
|
|
41
|
+
directory: directory, mint_permitted: mint_permitted?(settings),
|
|
42
|
+
mint_request: request))
|
|
34
43
|
ensure
|
|
35
44
|
db&.close
|
|
36
45
|
end
|
|
37
46
|
|
|
38
47
|
private
|
|
39
48
|
|
|
49
|
+
# Opens the lineage: for reading on a boot, and provisioned first on a mint request. Either
|
|
50
|
+
# refuses, by name, while the domain's history still sits under its former name.
|
|
51
|
+
def open_lineage(db, bluebook, settings, request)
|
|
52
|
+
lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as,
|
|
53
|
+
reading: request.nil?)
|
|
54
|
+
# First, before anything else: the earliest point the connection's role is known,
|
|
55
|
+
# so a superuser connection refuses here by default.
|
|
56
|
+
lineage.check_fence_applies!(allow_superuser: PostgresEra.setting(settings, :allow_superuser, default: false))
|
|
57
|
+
request ? lineage.ensure_base! : lineage.refuse_pending_rename!
|
|
58
|
+
lineage
|
|
59
|
+
end
|
|
60
|
+
|
|
40
61
|
# Whether the world allows minting, spelled as a boolean or as the word.
|
|
41
62
|
def mint_permitted?(settings)
|
|
42
63
|
[true, "true"].include?(PostgresEra.setting(settings, :mint_eras, default: MINT_BY_DEFAULT))
|
|
43
64
|
end
|
|
44
65
|
|
|
66
|
+
# Resolves the boot's shape through `EraResolution`, the answer every era tool reads, and
|
|
67
|
+
# records it on the registry; a mint request on a shape no era holds mints instead.
|
|
45
68
|
def resolve_era(context)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
# Some era is held: the latest, a superseded one, or none matches and a new one is minted.
|
|
53
|
-
def resolve_held(context, held)
|
|
54
|
-
shapes = held_shapes(context.bluebook, held)
|
|
55
|
-
latest, latest_shape = shapes.last
|
|
56
|
-
current_shape = context.current_shape
|
|
57
|
-
return resolve_latest(context, latest) if latest_shape == current_shape
|
|
58
|
-
|
|
59
|
-
matched, = shapes.find { |_, shape| shape == current_shape }
|
|
60
|
-
return resolve_superseded(context, matched, latest) if matched
|
|
61
|
-
|
|
62
|
-
context.record_resolved(mint!(context.with(latest: latest)))
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def hold_first_era(context)
|
|
66
|
-
context.lineage.hold_first!(context.current_text, projection: context.current_shape)
|
|
67
|
-
ensure_first_heads!(context)
|
|
68
|
-
grant_role!(context, 1)
|
|
69
|
-
nil
|
|
70
|
-
end
|
|
69
|
+
answer = EraResolution.resolve(eras: context.held_eras, bluebook: context.bluebook,
|
|
70
|
+
translations: context.translations, directory: context.directory) do
|
|
71
|
+
context.watermark
|
|
72
|
+
end
|
|
73
|
+
return refuse_unheld!(context) if answer.status == "unheld"
|
|
74
|
+
return context.record_resolved(mint!(context.with(latest: answer.latest))) if minting?(answer, context)
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
def resolve_latest(context, latest)
|
|
74
|
-
ensure_first_heads!(context) if latest[:ordinal] == 1
|
|
75
|
-
grant_role!(context, latest[:ordinal])
|
|
76
|
-
context.record_resolved(latest[:ordinal])
|
|
77
|
-
nil
|
|
78
|
-
end
|
|
76
|
+
return refuse_breaking!(context, answer) if answer.breaking?
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
# here, since the fence is already past this ordinal.
|
|
82
|
-
def resolve_superseded(context, matched, latest)
|
|
83
|
-
grant_role!(context, matched[:ordinal])
|
|
84
|
-
context.record_resolved(matched[:ordinal])
|
|
85
|
-
# The adapter refuses appends on this, even where the RLS fence cannot bind.
|
|
86
|
-
context.record_superseded(latest[:ordinal])
|
|
87
|
-
nil
|
|
78
|
+
record(context, answer)
|
|
88
79
|
end
|
|
89
80
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
# A breaking move no edge covers: the boot reads nothing and writes nothing. This stands
|
|
82
|
+
# in until the commit-time gate (ADR 0168) keeps such a move off main.
|
|
83
|
+
def refuse_breaking!(context, answer)
|
|
84
|
+
raise Runtime::WiringError, "cannot boot #{context.domain_name}: #{answer.reason}"
|
|
93
85
|
end
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
# Whether this check mints: a mint request, on a shape no held era holds.
|
|
88
|
+
def minting?(answer, context) = context.mint_request && !answer.matched?
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
# No era is held: the first era is held by the mint entry point, never by a boot.
|
|
91
|
+
def refuse_unheld!(context)
|
|
92
|
+
raise Runtime::WiringError,
|
|
93
|
+
"cannot boot #{context.domain_name}: no era held; run the mint entry point " \
|
|
94
|
+
"(`hecks era.hold_first! <domain directory> --confirm`) to hold the first era"
|
|
100
95
|
end
|
|
101
96
|
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
# the
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
97
|
+
# Records what the resolution answered and writes nothing. A superseded era (an old
|
|
98
|
+
# checkout) reads and never writes: the adapter refuses appends on it, even where the RLS
|
|
99
|
+
# fence cannot bind. A shape no era holds reads the latest held era, and is behind when a
|
|
100
|
+
# mint from it would go ahead; the mint entry point runs that mint.
|
|
101
|
+
def record(context, answer)
|
|
102
|
+
context.record_resolved(answer.ordinal)
|
|
103
|
+
latest = answer.latest[:ordinal]
|
|
104
|
+
status = answer.status
|
|
105
|
+
context.record_superseded(latest) if status == "superseded"
|
|
106
|
+
context.record_unminted(latest) if %w[unminted behind].include?(status)
|
|
107
|
+
context.record_behind(latest) if status == "behind"
|
|
108
|
+
nil
|
|
112
109
|
end
|
|
113
110
|
end
|
|
114
111
|
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require_relative "../../../../ports/persistence/plugins/era/storage_shape"
|
|
2
|
+
require_relative "../../../../ports/persistence/plugins/era/projected_bluebook"
|
|
3
|
+
require_relative "../../../../runtime/errors"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class PostgresEra
|
|
8
|
+
module LineageManager
|
|
9
|
+
# What a held era is: the storage shape its mint recorded, and the hash of that shape.
|
|
10
|
+
#
|
|
11
|
+
# Held text is kept for audit and decides nothing. An era minted without a stored shape is
|
|
12
|
+
# read from its held text only when that text is the whole domain, which it is when it
|
|
13
|
+
# hashes to the era's stored hash; otherwise the era is refused by name. LineageManager
|
|
14
|
+
# extends it, so each method is called on LineageManager.
|
|
15
|
+
module HeldEra
|
|
16
|
+
# @param era [Hash] an era as `Lineage#eras` answers it: `projection` when its mint
|
|
17
|
+
# recorded one, `hash` once it is named, and `held_text`
|
|
18
|
+
# @return [Hash] the storage shape the era holds
|
|
19
|
+
# @raise [Runtime::WiringError] naming the era, when it stores no shape and its held text
|
|
20
|
+
# does not hash to its stored hash
|
|
21
|
+
def held_shape(era) = era[:projection] || verified_text_shape(era) || refuse_unshaped!(era)
|
|
22
|
+
|
|
23
|
+
# The held era as a bluebook view over its storage shape, for a diff, the additive rule or
|
|
24
|
+
# the coverage check.
|
|
25
|
+
#
|
|
26
|
+
# @param era [Hash] an era as `Lineage#eras` answers it
|
|
27
|
+
# @return [Runtime::ProjectedBluebook]
|
|
28
|
+
# @raise [Runtime::WiringError] as `held_shape`
|
|
29
|
+
def held_bluebook(era) = Runtime::ProjectedBluebook.new(held_shape(era))
|
|
30
|
+
|
|
31
|
+
# The era's hash: the one it stores once named, else the hash of the shape it holds.
|
|
32
|
+
#
|
|
33
|
+
# @param era [Hash] an era as `Lineage#eras` answers it
|
|
34
|
+
# @return [String] 64 lowercase hex characters
|
|
35
|
+
def held_hash(era) = era[:hash] || held_bluebook(era).mint_hash
|
|
36
|
+
|
|
37
|
+
# The shape an era's held text declares, when the text hashes to the era's stored hash and
|
|
38
|
+
# so is the whole domain the era was minted from; nil otherwise.
|
|
39
|
+
#
|
|
40
|
+
# @param era [Hash] an era with no stored shape
|
|
41
|
+
# @return [Hash, nil]
|
|
42
|
+
def verified_text_shape(era)
|
|
43
|
+
return unless era[:hash] && era[:held_text]
|
|
44
|
+
|
|
45
|
+
declared = shadow(era[:held_text])
|
|
46
|
+
Runtime::StorageShape.project(declared) if declared && Runtime::StorageShape.mint_hash(declared) == era[:hash]
|
|
47
|
+
rescue StandardError, SyntaxError
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @raise [Runtime::WiringError] always, naming the era and why its shape is unknown
|
|
52
|
+
def refuse_unshaped!(era)
|
|
53
|
+
raise Runtime::WiringError,
|
|
54
|
+
"era #{era[:ordinal]} (#{era[:label] || "unnamed"}) stores no storage shape, and its held " \
|
|
55
|
+
"text #{unverified_reason(era)}, so it is not the whole domain the era was minted from"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @return [String] why an era's held text cannot stand in for its missing shape
|
|
59
|
+
def unverified_reason(era)
|
|
60
|
+
return "has no stored hash to check it against" unless era[:hash]
|
|
61
|
+
|
|
62
|
+
"does not hash to its stored hash"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require_relative "../../../../ports/persistence/plugins/era/storage_shape"
|
|
2
|
+
require_relative "../../../../naming"
|
|
3
|
+
require_relative "../../../../ports/persistence/plugins/era/translation/additive_shape"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Adapters
|
|
7
|
+
class PostgresEra
|
|
8
|
+
module LineageManager
|
|
9
|
+
# The change between the storage shape a disposable ledger holds and the shape it boots
|
|
10
|
+
# with, aggregate by aggregate. `added` names aggregates the held shape did not have,
|
|
11
|
+
# `widened` those that only gained optional attributes, and `replaced` those whose stored
|
|
12
|
+
# rows do not fit the booting shape: removed, or with an attribute renamed, dropped,
|
|
13
|
+
# retyped, switched between list and scalar, or a changed identity or lifecycle field. It
|
|
14
|
+
# reads and writes nothing.
|
|
15
|
+
LedgerChange = Data.define(:added, :widened, :replaced) do
|
|
16
|
+
# @param held_projection [Hash] the held era's storage shape, as `StorageShape.project`
|
|
17
|
+
# answers it
|
|
18
|
+
# @param bluebook [Bluebook::Declaration] the bluebook booting now
|
|
19
|
+
# @return [LedgerChange]
|
|
20
|
+
def self.between(held_projection, bluebook)
|
|
21
|
+
held = by_name(held_projection)
|
|
22
|
+
current = by_name(Runtime::StorageShape.project(bluebook))
|
|
23
|
+
widened, broken = changed_in_both(held, current).partition do |name|
|
|
24
|
+
widened?(held[name], current[name], bluebook.aggregate(name))
|
|
25
|
+
end
|
|
26
|
+
new(added: missing(held, current), widened: widened, replaced: broken + missing(current, held))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [Hash{String => Hash}] each projected aggregate by its name
|
|
30
|
+
def self.by_name(projection) = projection.fetch("aggregates", []).to_h { |aggregate| [aggregate["name"], aggregate] }
|
|
31
|
+
|
|
32
|
+
# @return [Array<String>] the aggregates `to` has and `from` does not
|
|
33
|
+
def self.missing(from, to) = to.keys - from.keys
|
|
34
|
+
|
|
35
|
+
# @return [Array<String>] the aggregates both shapes have, whose shapes differ
|
|
36
|
+
def self.changed_in_both(held, current) = (held.keys & current.keys).reject { |name| held[name] == current[name] }
|
|
37
|
+
|
|
38
|
+
# Whether an aggregate kept its identity, lifecycle field and every attribute as it was
|
|
39
|
+
# held, list or scalar included, and gained only attributes it declares optional
|
|
40
|
+
# (`Translation::AdditiveShape`). An attribute that became required is not seen: the
|
|
41
|
+
# held projection does not record `optional`.
|
|
42
|
+
#
|
|
43
|
+
# @return [Boolean]
|
|
44
|
+
def self.widened?(held, current, aggregate)
|
|
45
|
+
Translation::AdditiveShape.widened?(held, current, optional: Translation::AdditiveShape.optional_in(aggregate))
|
|
46
|
+
end
|
|
47
|
+
private_class_method :by_name, :changed_in_both, :widened?, :missing
|
|
48
|
+
|
|
49
|
+
# @return [Boolean] whether the held shape and the booting shape differ at all
|
|
50
|
+
def changed? = !(added.empty? && widened.empty? && replaced.empty?)
|
|
51
|
+
|
|
52
|
+
# The storage name of a replaced aggregate: the booting bluebook's own, else the name the
|
|
53
|
+
# held shape gave it, snake-cased the way an aggregate names its storage.
|
|
54
|
+
#
|
|
55
|
+
# @param bluebook [Bluebook::Declaration] the bluebook booting now
|
|
56
|
+
# @param name [String] a name from `replaced`
|
|
57
|
+
# @return [String]
|
|
58
|
+
def storage_name(bluebook, name) = bluebook.aggregate(name)&.storage_name || Naming.snake(name)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|