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,64 @@
|
|
|
1
|
+
require_relative "sql_templates"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class PostgresEra
|
|
6
|
+
class Lineage
|
|
7
|
+
# The shortcut that builds an era from the matview of the era before it, rather than from
|
|
8
|
+
# the whole journal. A chain that cannot take it falls back to `ChainSql#chain_sql`.
|
|
9
|
+
module LayeredSql
|
|
10
|
+
include SqlTemplates
|
|
11
|
+
|
|
12
|
+
# Builds era N by layering its own last edge onto era N-1's existing
|
|
13
|
+
# matview, instead of re-deriving from raw history; returns nil
|
|
14
|
+
# (falling back to chain_sql) whenever that shortcut can't honestly
|
|
15
|
+
# apply. `edges.size != era - 1` guards names_by_era's own
|
|
16
|
+
# assumption that `edges` is the full chain reaching `era` — a
|
|
17
|
+
# shorter chain here would index names[:storage] out of bounds
|
|
18
|
+
# rather than safely falling back.
|
|
19
|
+
def layered_chain_sql(aggregate, era, edges)
|
|
20
|
+
return nil unless layerable?(era, edges)
|
|
21
|
+
|
|
22
|
+
held = eras
|
|
23
|
+
prior_view = existing_prior_view(aggregate, era, held)
|
|
24
|
+
return nil unless prior_view
|
|
25
|
+
|
|
26
|
+
layered_sql(aggregate, era, edges, held, prior_view)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def layerable?(era, edges) = era >= 3 && edges.size >= 2 && edges.size == era - 1
|
|
32
|
+
|
|
33
|
+
# The previous era's matview, when it is labelled and already built.
|
|
34
|
+
def existing_prior_view(aggregate, era, held)
|
|
35
|
+
prior = held.find { |candidate| candidate[:ordinal] == era - 1 }
|
|
36
|
+
return nil unless prior && prior[:label]
|
|
37
|
+
|
|
38
|
+
view = matview(aggregate.storage_name, era - 1, prior[:label])
|
|
39
|
+
view if view_exists?(view)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def layered_sql(aggregate, era, edges, held, prior_view)
|
|
43
|
+
names = names_by_era(aggregate, edges)
|
|
44
|
+
declared = edges.last[:translation].for_aggregate(names[:current][edges.size])
|
|
45
|
+
tokens = layered_tokens(prior_view, names, era, declared)
|
|
46
|
+
format(LAYERED_SQL, tokens.merge(cut: cut_clause(held, era)))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def layered_tokens(prior_view, names, era, declared)
|
|
50
|
+
{ prior_view: quote(prior_view), journal: quoted_journal, prior_era: era - 1,
|
|
51
|
+
aggregate: text_literal(names[:storage][era - 2]),
|
|
52
|
+
id_column: id_column_for(declared, "operation = 'save'"), expression: rules_expression(declared) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Cuts the previous era's rows at the watermark recorded when this era was minted.
|
|
56
|
+
def cut_clause(held, era)
|
|
57
|
+
cut = held.find { |candidate| candidate[:ordinal] == era }&.dig(:watermark)
|
|
58
|
+
" AND ordinal <= #{cut}" if cut
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "digest"
|
|
3
|
+
|
|
4
|
+
module Hecks
|
|
5
|
+
module Adapters
|
|
6
|
+
class PostgresEra
|
|
7
|
+
class Lineage
|
|
8
|
+
# The writes a disposable ledger's boot makes in place of a mint: it re-holds the latest era
|
|
9
|
+
# at the booting shape, gives an aggregate a head that reads only its latest era, and moves
|
|
10
|
+
# an aggregate's rows into a dated archive table so it starts empty. Nothing is dropped:
|
|
11
|
+
# archived rows stay in their table, and each archive is listed in `hecks_ledger_archives`.
|
|
12
|
+
module LedgerReset
|
|
13
|
+
# The list of every archive a disposable ledger's boot made.
|
|
14
|
+
ARCHIVES_SQL = <<~SQL.freeze
|
|
15
|
+
CREATE TABLE IF NOT EXISTS hecks_ledger_archives (
|
|
16
|
+
domain text NOT NULL,
|
|
17
|
+
aggregate text NOT NULL,
|
|
18
|
+
archive text NOT NULL PRIMARY KEY,
|
|
19
|
+
row_count bigint NOT NULL,
|
|
20
|
+
archived_at timestamptz NOT NULL DEFAULT now()
|
|
21
|
+
)
|
|
22
|
+
SQL
|
|
23
|
+
|
|
24
|
+
# The update that re-holds an era at a new shape.
|
|
25
|
+
REHOLD_SQL = "UPDATE hecks_eras SET held_text = $3, held_digest = $4, held_projection = $5::text::jsonb, " \
|
|
26
|
+
"hash = $6, label = $7, canon_form = $8 WHERE domain = $1 AND ordinal = $2".freeze
|
|
27
|
+
|
|
28
|
+
# Moves every journal row of one aggregate, from every era, into a new table named for it
|
|
29
|
+
# and the time, then empties the aggregate's head snapshots, all in one transaction.
|
|
30
|
+
# The journal is locked against writers for the whole move, so no row can commit between
|
|
31
|
+
# the copy and the delete, and the delete must remove exactly the rows the copy holds or
|
|
32
|
+
# the transaction rolls back. A name already taken gets `_2`, `_3`, and so on; an archive
|
|
33
|
+
# is never overwritten.
|
|
34
|
+
#
|
|
35
|
+
# @param storage_name [String] the aggregate's snake-cased storage name
|
|
36
|
+
# @param stamp [String] the time the archive is named for, as `YYYYMMDDHHMMSS`
|
|
37
|
+
# @return [Array(String, Integer)] the archive table's name and how many rows it holds
|
|
38
|
+
# @raise [PG::Error] if Postgres refuses a statement; nothing is moved then
|
|
39
|
+
# @raise [Runtime::WiringError] if the delete removed other rows than the copy holds
|
|
40
|
+
def archive_aggregate!(storage_name, stamp)
|
|
41
|
+
archive = nil
|
|
42
|
+
nested_transaction("hecks_ledger_archive") do
|
|
43
|
+
lock_journal!
|
|
44
|
+
archive = unused_archive_name(storage_name, stamp)
|
|
45
|
+
move_rows!(storage_name, archive)
|
|
46
|
+
end
|
|
47
|
+
[archive, archived_count(archive)]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Points an aggregate's head view at its snapshot in `era` alone, with no ancestor tail,
|
|
51
|
+
# creating the snapshot when it is missing. Used for an aggregate whose rows are all in
|
|
52
|
+
# that era: one just added, or one just archived.
|
|
53
|
+
#
|
|
54
|
+
# @param storage_name [String] the aggregate's snake-cased storage name
|
|
55
|
+
# @param era [Integer] the ordinal of the latest held era
|
|
56
|
+
# @return [void]
|
|
57
|
+
# @raise [PG::Error] if Postgres refuses a statement
|
|
58
|
+
def fresh_head!(storage_name, era)
|
|
59
|
+
ensure_head_snapshot!(storage_name, era)
|
|
60
|
+
tokens = { head_view: quote(head_view(storage_name)), snapshot: quote(head_snapshot(storage_name, era)) }
|
|
61
|
+
nested_transaction("hecks_fresh_head") do
|
|
62
|
+
@db.exec("DROP VIEW IF EXISTS #{quote(head_view(storage_name))}")
|
|
63
|
+
@db.exec(format(SqlTemplates::FIRST_HEAD_VIEW_SQL, tokens))
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Replaces the latest era's held text, digest, projection and name with the booting
|
|
68
|
+
# shape's, recording the old and new digests in `hecks_attestations`.
|
|
69
|
+
#
|
|
70
|
+
# @param ordinal [Integer] the latest held era
|
|
71
|
+
# @param text [String] the booting bluebook's source text
|
|
72
|
+
# @param projection [Hash] the booting bluebook's storage shape
|
|
73
|
+
# @param hash [String] the booting shape's mint hash
|
|
74
|
+
# @return [void]
|
|
75
|
+
# @raise [PG::Error] if Postgres refuses a statement
|
|
76
|
+
def rehold!(ordinal, text, projection, hash)
|
|
77
|
+
fresh = Digest::SHA256.hexdigest(text)
|
|
78
|
+
@db.exec(EraIntegrity::CREATE_ATTESTATIONS_SQL)
|
|
79
|
+
record_attestation!(ordinal, raw_era(ordinal)&.fetch(:held_digest), fresh)
|
|
80
|
+
@db.exec_params(REHOLD_SQL, [@domain, ordinal, text, fresh, JSON.generate(projection), hash,
|
|
81
|
+
hash[0, Runtime::StorageShape::LABEL_LENGTH],
|
|
82
|
+
Runtime::StorageShape::FORM_VERSION])
|
|
83
|
+
archive_text!(ordinal, text)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
# Blocks every concurrent insert, update and delete on the journal until the transaction
|
|
89
|
+
# ends; reads go on. A writer that waits here lands its row in the journal after the move.
|
|
90
|
+
def lock_journal! = @db.exec("LOCK TABLE #{quoted_journal} IN SHARE ROW EXCLUSIVE MODE")
|
|
91
|
+
|
|
92
|
+
def move_rows!(storage_name, archive)
|
|
93
|
+
@db.exec("CREATE TABLE #{quote(archive)} AS SELECT * FROM #{quoted_journal} " \
|
|
94
|
+
"WHERE aggregate = #{text_literal(storage_name)}")
|
|
95
|
+
record_archive!(storage_name, archive)
|
|
96
|
+
verify_moved!(archive, delete_journal_rows!(storage_name))
|
|
97
|
+
empty_head_snapshots!(storage_name)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# A delete of a row the archive does not hold would lose it; refuse and roll back.
|
|
101
|
+
def verify_moved!(archive, deleted)
|
|
102
|
+
return if deleted == archived_count(archive)
|
|
103
|
+
|
|
104
|
+
raise Runtime::WiringError, "the ledger archive #{archive} holds #{archived_count(archive)} rows but " \
|
|
105
|
+
"#{deleted} were deleted from the journal; nothing was moved"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def archived_count(archive) = @db.exec("SELECT count(*) FROM #{quote(archive)}")[0]["count"].to_i
|
|
109
|
+
|
|
110
|
+
# The archive's name, suffixed `_2`, `_3` and on while a table or listed archive has it.
|
|
111
|
+
def unused_archive_name(storage_name, stamp)
|
|
112
|
+
@db.exec(ARCHIVES_SQL)
|
|
113
|
+
base = "#{storage_name}_archived_#{stamp}"
|
|
114
|
+
(1..).lazy.map { |n| qualified_name(n == 1 ? base : "#{base}_#{n}") }.find { |name| archive_name_free?(name) }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def archive_name_free?(name)
|
|
118
|
+
return false if table_exists?(quote(name))
|
|
119
|
+
|
|
120
|
+
@db.exec_params("SELECT 1 FROM hecks_ledger_archives WHERE archive = $1", [name]).ntuples.zero?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def record_archive!(storage_name, archive)
|
|
124
|
+
@db.exec(ARCHIVES_SQL)
|
|
125
|
+
@db.exec_params("INSERT INTO hecks_ledger_archives (domain, aggregate, archive, row_count) " \
|
|
126
|
+
"SELECT $1, $2, $3, count(*) FROM #{quote(archive)}", [@domain, storage_name, archive])
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# The journal forces row-level security with no DELETE policy, so even its owner deletes
|
|
130
|
+
# nothing; a policy that admits this one aggregate's rows stands for the one statement.
|
|
131
|
+
def delete_journal_rows!(storage_name)
|
|
132
|
+
aggregate = text_literal(storage_name)
|
|
133
|
+
@db.exec("CREATE POLICY hecks_ledger_archive ON #{quoted_journal} FOR DELETE TO PUBLIC " \
|
|
134
|
+
"USING (aggregate = #{aggregate})")
|
|
135
|
+
deleted = @db.exec("DELETE FROM #{quoted_journal} WHERE aggregate = #{aggregate}").cmd_tuples
|
|
136
|
+
@db.exec("DROP POLICY hecks_ledger_archive ON #{quoted_journal}")
|
|
137
|
+
deleted
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def empty_head_snapshots!(storage_name)
|
|
141
|
+
eras.each do |era|
|
|
142
|
+
snapshot = head_snapshot(storage_name, era[:ordinal])
|
|
143
|
+
@db.exec("TRUNCATE #{quote(snapshot)}") if table_exists?(snapshot)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require_relative "../field_cache_provisioner"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class PostgresEra
|
|
6
|
+
class Lineage
|
|
7
|
+
# The read side of an era that the mint path provisions: each aggregate's head view and the
|
|
8
|
+
# field caches its queries narrow by. The mint that compiles an era and the first-era hold
|
|
9
|
+
# call these; nothing a boot reads does.
|
|
10
|
+
module MintProvisioning
|
|
11
|
+
# Creates and backfills one aggregate's field caches for an era, on this lineage's
|
|
12
|
+
# connection, so the caches commit with the era that owns them.
|
|
13
|
+
#
|
|
14
|
+
# @param aggregate [Bluebook::Aggregate] the aggregate whose where-fields are cached
|
|
15
|
+
# @param era [Integer] the ordinal of the era the caches belong to
|
|
16
|
+
# @return [Hash{String => String}] each cached field mapped to its cache table
|
|
17
|
+
# @raise [PG::Error] if Postgres refuses the DDL, a source read or an upsert
|
|
18
|
+
def provision_read_side!(aggregate, era)
|
|
19
|
+
FieldCacheProvisioner.new(self, aggregate, era).provision!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Holds the read side of the first era: each aggregate's head view over the snapshot the
|
|
23
|
+
# first era holds, then its field caches, then the app role's privileges on them, as a
|
|
24
|
+
# mint grants them for a later era.
|
|
25
|
+
#
|
|
26
|
+
# @param aggregates [Array<Bluebook::Aggregate>] the domain's aggregates
|
|
27
|
+
# @param role [String, nil] the app role to grant; none when blank
|
|
28
|
+
# @return [void]
|
|
29
|
+
# @raise [PG::Error] if Postgres refuses a statement
|
|
30
|
+
def provision_first_era!(aggregates, role: nil)
|
|
31
|
+
aggregates.each do |aggregate|
|
|
32
|
+
ensure_first_head!(aggregate.storage_name)
|
|
33
|
+
provision_read_side!(aggregate, 1)
|
|
34
|
+
end
|
|
35
|
+
grant_role!(role, aggregates: aggregates, era: 1)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Holds era 1 and provisions its read side in one transaction under the domain's era lock,
|
|
39
|
+
# so a crash leaves either all of it or none. A run that finds era 1 already held from the
|
|
40
|
+
# same text with some head view missing (a half-done run of an older version) completes
|
|
41
|
+
# it; any other held era is refused.
|
|
42
|
+
#
|
|
43
|
+
# @param text [String] the bluebook source the first era freezes
|
|
44
|
+
# @param projection [Hash, nil] the storage-shape projection of the text
|
|
45
|
+
# @param aggregates [Array<Bluebook::Aggregate>] the domain's aggregates
|
|
46
|
+
# @param role [String, nil] the app role to grant; nil or empty grants nothing
|
|
47
|
+
# @return [void]
|
|
48
|
+
# @raise [Runtime::WiringError] if another era is held, the lock is not granted in 10s,
|
|
49
|
+
# or Postgres refuses a statement; the transaction rolls back first
|
|
50
|
+
def hold_first_era!(text, projection:, aggregates:, role: nil)
|
|
51
|
+
lock_era_table!
|
|
52
|
+
refuse_second_hold!(text, aggregates)
|
|
53
|
+
hold_first!(text, projection: projection)
|
|
54
|
+
provision_first_era!(aggregates, role: role)
|
|
55
|
+
@db.exec("COMMIT")
|
|
56
|
+
rescue StandardError
|
|
57
|
+
rollback_quietly
|
|
58
|
+
raise
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def lock_era_table!
|
|
64
|
+
@db.exec("BEGIN")
|
|
65
|
+
@db.exec("SET LOCAL lock_timeout = '10s'")
|
|
66
|
+
@db.exec("SELECT pg_advisory_xact_lock(hashtext('hecks_eras:' || #{text_literal(@domain)}))")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Refuses unless no era is held, or only era 1, from `text`, is held and unfinished.
|
|
70
|
+
def refuse_second_hold!(text, aggregates)
|
|
71
|
+
held = eras
|
|
72
|
+
return if held.empty?
|
|
73
|
+
return if held.size == 1 && held.first[:held_text] == text && unfinished?(aggregates)
|
|
74
|
+
|
|
75
|
+
raise Runtime::WiringError, "#{@domain} already holds an era"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def unfinished?(aggregates)
|
|
79
|
+
aggregates.any? { |aggregate| !table_exists?(head_view(aggregate.storage_name)) }
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -10,8 +10,9 @@ module Hecks
|
|
|
10
10
|
module MintTransaction
|
|
11
11
|
# The era a mint writes: its name, frozen text, the aggregates to recompile and the
|
|
12
12
|
# edge chain that derives their heads.
|
|
13
|
-
Mint = Data.define(:ordinal, :shape_hash, :label, :held_text, :aggregates, :edges, :role, :projection
|
|
14
|
-
|
|
13
|
+
Mint = Data.define(:ordinal, :shape_hash, :label, :held_text, :aggregates, :edges, :role, :projection,
|
|
14
|
+
:edge) do
|
|
15
|
+
def initialize(role: nil, projection: nil, edge: nil, **rest) = super
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
# Makes a new era real in one locked transaction, or reports a concurrent minter won.
|
|
@@ -53,7 +54,7 @@ module Hecks
|
|
|
53
54
|
# @return [void]
|
|
54
55
|
# @raise [PG::Error] if Postgres refuses a grant
|
|
55
56
|
def grant_role!(role, aggregates: [], era: nil)
|
|
56
|
-
return
|
|
57
|
+
return if role.to_s.empty? || !provisioner?
|
|
57
58
|
|
|
58
59
|
quoted_role = quote(role)
|
|
59
60
|
@db.exec("GRANT INSERT, SELECT ON #{quoted_journal} TO #{quoted_role}")
|
|
@@ -112,11 +113,11 @@ module Hecks
|
|
|
112
113
|
def insert_era!(mint)
|
|
113
114
|
@db.exec_params(
|
|
114
115
|
"INSERT INTO hecks_eras (domain, ordinal, hash, label, held_text, watermark, held_digest, " \
|
|
115
|
-
"held_projection, canon_form) " \
|
|
116
|
-
"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
|
116
|
+
"held_projection, canon_form, edge) " \
|
|
117
|
+
"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
|
117
118
|
[@domain, mint.ordinal, mint.shape_hash, mint.label, mint.held_text, last_ordinal,
|
|
118
119
|
Digest::SHA256.hexdigest(mint.held_text), mint.projection && JSON.generate(mint.projection),
|
|
119
|
-
Runtime::StorageShape::FORM_VERSION]
|
|
120
|
+
Runtime::StorageShape::FORM_VERSION, mint.edge && JSON.generate(mint.edge)]
|
|
120
121
|
)
|
|
121
122
|
end
|
|
122
123
|
|
|
@@ -136,7 +137,10 @@ module Hecks
|
|
|
136
137
|
# grant_role! must follow compile_head!, which creates the per-era snapshot
|
|
137
138
|
# tables that it grants on.
|
|
138
139
|
def compile_and_grant!(mint)
|
|
139
|
-
mint.aggregates.each
|
|
140
|
+
mint.aggregates.each do |aggregate|
|
|
141
|
+
compile_head!(aggregate, mint.ordinal, mint.label, mint.edges)
|
|
142
|
+
provision_read_side!(aggregate, mint.ordinal)
|
|
143
|
+
end
|
|
140
144
|
grant_role!(mint.role, aggregates: mint.aggregates, era: mint.ordinal) if mint.role
|
|
141
145
|
end
|
|
142
146
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative "base_sql"
|
|
2
2
|
require_relative "domain_rename"
|
|
3
|
+
require_relative "../shared_tables"
|
|
3
4
|
|
|
4
5
|
module Hecks
|
|
5
6
|
module Adapters
|
|
@@ -12,16 +13,17 @@ module Hecks
|
|
|
12
13
|
include DomainRename
|
|
13
14
|
|
|
14
15
|
# Builds or tops up this domain's lineage schema when the connected role owns the
|
|
15
|
-
# journal (or none exists yet); any other role
|
|
16
|
+
# journal (or none exists yet); any other role skips it. Also
|
|
17
|
+
# creates the event, saga and outbox tables the database shares.
|
|
16
18
|
#
|
|
17
|
-
#
|
|
19
|
+
# Only the mint path and the owner-only tools call it; a boot never does. ALTER TABLE and
|
|
20
|
+
# REVOKE are owner-only, so a non-owner app role must skip them.
|
|
18
21
|
#
|
|
19
22
|
# @return [void]
|
|
20
|
-
# @raise [Runtime::WiringError] if the `formerly_known_as` rename
|
|
21
|
-
# its locks within 10s or Postgres refuses one of its statements
|
|
23
|
+
# @raise [Runtime::WiringError] if the domain's `formerly_known_as` rename is still pending
|
|
22
24
|
# @raise [PG::Error] if Postgres refuses a provisioning statement
|
|
23
25
|
def ensure_base!
|
|
24
|
-
|
|
26
|
+
refuse_pending_rename!
|
|
25
27
|
return unless provisioner?
|
|
26
28
|
|
|
27
29
|
create_lineage_tables!
|
|
@@ -30,6 +32,7 @@ module Hecks
|
|
|
30
32
|
revoke_journal_mutation!
|
|
31
33
|
force_row_security!
|
|
32
34
|
install_transforms!
|
|
35
|
+
SharedTables.new(@db).provision!
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
# Refuses to boot on a connection whose role Postgres exempts from row-level security
|
|
@@ -117,6 +120,9 @@ module Hecks
|
|
|
117
120
|
# Canonical-form version that minted the name (Runtime::StorageShape::FORM_VERSION);
|
|
118
121
|
# NULL reads as 1.
|
|
119
122
|
@db.exec("ALTER TABLE hecks_eras ADD COLUMN IF NOT EXISTS canon_form int")
|
|
123
|
+
# The edge an era was minted under when no edge file wrote it, as `Translation::ImplicitEdge::RECORD`;
|
|
124
|
+
# NULL for every era a written edge reached.
|
|
125
|
+
@db.exec("ALTER TABLE hecks_eras ADD COLUMN IF NOT EXISTS edge jsonb")
|
|
120
126
|
@db.exec(ERA_TEXTS_SQL)
|
|
121
127
|
end
|
|
122
128
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Adapters
|
|
3
|
+
class PostgresEra
|
|
4
|
+
class Lineage
|
|
5
|
+
# ADR 0166: a `split` writes rows into another aggregate from one aggregate's rows. The target's
|
|
6
|
+
# head is not stored: its tail is the source's held-era state, fanned out one row per target key,
|
|
7
|
+
# and read through the same chain every head reads.
|
|
8
|
+
module SplitSql
|
|
9
|
+
# The source's rows as they are in the era the split edge starts from, latest per id, with the
|
|
10
|
+
# era kept so later edges' guards still hold.
|
|
11
|
+
SPLIT_SOURCE_SQL = <<~SQL.freeze
|
|
12
|
+
WITH tail AS MATERIALIZED (%<tail>s),
|
|
13
|
+
%<chain>s
|
|
14
|
+
SELECT ordinal, era, aggregate_id, operation, state FROM edge_%<last>s
|
|
15
|
+
SQL
|
|
16
|
+
|
|
17
|
+
# The split edge that creates `names[:current][n]`, with the source aggregate and the split, or nil.
|
|
18
|
+
def split_into(names, edges)
|
|
19
|
+
edges.each_with_index do |edge, index|
|
|
20
|
+
target = names[:current][index + 1]
|
|
21
|
+
edge[:translation].aggregates.each do |source|
|
|
22
|
+
split = source.splits.find { |candidate| candidate.into == target }
|
|
23
|
+
return { index: index, source: source, split: split } if split
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The target's tail from its source's held-era rows: the source is chained through the edges
|
|
30
|
+
# before the split edge, so the split reads the shape it declares its fields in.
|
|
31
|
+
def split_tail_sql(names, edges)
|
|
32
|
+
found = split_into(names, edges)
|
|
33
|
+
return nil unless found
|
|
34
|
+
|
|
35
|
+
source_sql = split_source_sql(found[:source], edges, found[:index])
|
|
36
|
+
split_fanout_sql(source_sql, found[:split], names[:storage][found[:index] + 1])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A split target's records as its split fans them out of the source, latest per id, or nil when
|
|
40
|
+
# the aggregate is not a split target: the "before" side of the audit of a split edge.
|
|
41
|
+
def split_latest(aggregate, edges)
|
|
42
|
+
tail = split_tail_sql(names_by_era(aggregate, edges), edges)
|
|
43
|
+
tail && latest_of("SELECT ordinal, era, aggregate_id, operation, state FROM (#{tail}) split_rows")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def split_source_sql(source, edges, index)
|
|
49
|
+
through = edges.first(index + 1)
|
|
50
|
+
names = names_by_era(Struct.new(:name).new(source.name), through)
|
|
51
|
+
tail = latest_per_id(ancestor_tail_sql(names, index + 2))
|
|
52
|
+
index.zero? ? tail : split_chain_sql(tail, through.first(index), names)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def split_chain_sql(tail, edges, names)
|
|
56
|
+
chain = edges.each_with_index.map { |edge, i| edge_step_sql(edge, i, names) }
|
|
57
|
+
format(SPLIT_SOURCE_SQL, tail: tail, chain: chain.join(",\n"), last: edges.size)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# One row per source row that carries the key: the key becomes the target's id, and the named
|
|
61
|
+
# fields are copied under their own names. Deletes are kept, so a deleted source deletes its
|
|
62
|
+
# target row too.
|
|
63
|
+
def split_fanout_sql(source_sql, split, target_storage)
|
|
64
|
+
key = text_literal(split.keyed_by.to_s)
|
|
65
|
+
# A keyed_by field is often a value object, whose identity is its `value` member.
|
|
66
|
+
key_value = "COALESCE(state -> #{key} ->> 'value', state ->> #{key})"
|
|
67
|
+
fields = split.fields.map { |field| "#{text_literal(field.to_s)}, state -> #{text_literal(field.to_s)}" }
|
|
68
|
+
"SELECT ordinal, era, #{text_literal(target_storage)} AS aggregate, #{key_value} AS aggregate_id, " \
|
|
69
|
+
"operation, jsonb_build_object(#{fields.join(", ")}) AS state " \
|
|
70
|
+
"FROM (#{source_sql}) split_source WHERE state ? #{key}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -77,6 +77,15 @@ module Hecks
|
|
|
77
77
|
SELECT ordinal, aggregate_id, operation, state FROM edge_%<last>s
|
|
78
78
|
SQL
|
|
79
79
|
|
|
80
|
+
# The chain in one step: each held era's rows take the one composed translation from
|
|
81
|
+
# that era to the current shape.
|
|
82
|
+
DIRECT_SQL = <<~SQL.freeze
|
|
83
|
+
WITH tail AS MATERIALIZED (%<tail>s),
|
|
84
|
+
direct AS MATERIALIZED (SELECT ordinal, era, aggregate_id, operation,
|
|
85
|
+
%<state>s AS state FROM tail)
|
|
86
|
+
SELECT ordinal, aggregate_id, operation, state FROM direct
|
|
87
|
+
SQL
|
|
88
|
+
|
|
80
89
|
# Reduces to newest entry per aggregate id, dropping any id whose newest entry is a
|
|
81
90
|
# delete.
|
|
82
91
|
LATEST_SQL = <<~SQL.freeze
|
|
@@ -10,6 +10,8 @@ require_relative "lineage/resumable_backfill"
|
|
|
10
10
|
require_relative "lineage/head_compiler"
|
|
11
11
|
require_relative "lineage/field_cache"
|
|
12
12
|
require_relative "lineage/transform_installer"
|
|
13
|
+
require_relative "lineage/mint_provisioning"
|
|
14
|
+
require_relative "lineage/ledger_reset"
|
|
13
15
|
require_relative "../../../naming"
|
|
14
16
|
|
|
15
17
|
module Hecks
|
|
@@ -27,6 +29,8 @@ module Hecks
|
|
|
27
29
|
include HeadCompiler
|
|
28
30
|
include FieldCache
|
|
29
31
|
include TransformInstaller
|
|
32
|
+
include MintProvisioning
|
|
33
|
+
include LedgerReset
|
|
30
34
|
|
|
31
35
|
# Longer identifiers are silently truncated by Postgres, so `qualified_name` hashes them.
|
|
32
36
|
POSTGRES_IDENTIFIER_LIMIT = 63
|
|
@@ -37,11 +41,15 @@ module Hecks
|
|
|
37
41
|
# @param domain [String, Symbol] the domain's declared name; every relation name and
|
|
38
42
|
# advisory-lock key derives from it
|
|
39
43
|
# @param formerly_known_as [String, Symbol, nil] the domain's prior name, which makes
|
|
40
|
-
# `ensure_base!`
|
|
41
|
-
|
|
44
|
+
# `ensure_base!` and a read refuse while the history sits under it; `rename_domain!` moves
|
|
45
|
+
# the history; nil when there is no prior name
|
|
46
|
+
# @param reading [Boolean] true for a read: the held eras are verified in memory and never
|
|
47
|
+
# archived or backfilled, so the connection needs only SELECT
|
|
48
|
+
def initialize(db, domain, formerly_known_as: nil, reading: false)
|
|
42
49
|
@db = db
|
|
43
50
|
@domain = domain.to_s
|
|
44
51
|
@formerly_known_as = formerly_known_as&.to_s
|
|
52
|
+
@reading = reading
|
|
45
53
|
end
|
|
46
54
|
|
|
47
55
|
# Names the domain's one journal table, the partitioned parent of every era's rows.
|
|
@@ -4,10 +4,11 @@ module Hecks
|
|
|
4
4
|
module LineageManager
|
|
5
5
|
# Everything one era check carries from connecting to minting: the booting registry and
|
|
6
6
|
# bluebook, its source text, the open lineage, the role to grant, the bluebook directory,
|
|
7
|
-
# whether this copy may mint,
|
|
7
|
+
# whether this copy may mint, the mint request the Maintenance mint command made (nil on
|
|
8
|
+
# a boot), and the latest held era once the held eras were read.
|
|
8
9
|
Context = Data.define(:registry, :bluebook, :current_text, :lineage, :role, :directory, :latest,
|
|
9
|
-
:mint_permitted) do
|
|
10
|
-
def initialize(latest: nil, mint_permitted: false, **rest) = super
|
|
10
|
+
:mint_permitted, :mint_request) do
|
|
11
|
+
def initialize(latest: nil, mint_permitted: false, mint_request: nil, **rest) = super
|
|
11
12
|
|
|
12
13
|
# @return [String] the name of the domain being checked
|
|
13
14
|
def domain_name = bluebook.name
|
|
@@ -15,9 +16,15 @@ module Hecks
|
|
|
15
16
|
# @return [Array<Bluebook::Aggregate>] the aggregates of the bluebook being checked
|
|
16
17
|
def aggregates = bluebook.aggregates
|
|
17
18
|
|
|
19
|
+
# @return [Array<Object>] the translation edges the registry loaded
|
|
20
|
+
def translations = registry.translations
|
|
21
|
+
|
|
18
22
|
# @return [Array<Hash>] the eras the open lineage holds, oldest first
|
|
19
23
|
def held_eras = lineage.eras
|
|
20
24
|
|
|
25
|
+
# @return [Integer] the ledger watermark now: the journal's highest ordinal
|
|
26
|
+
def watermark = lineage.last_ordinal
|
|
27
|
+
|
|
21
28
|
# @return [Integer] the ordinal of the era a mint would create
|
|
22
29
|
def ordinal = latest[:ordinal] + 1
|
|
23
30
|
|
|
@@ -41,6 +48,19 @@ module Hecks
|
|
|
41
48
|
# @param ordinal [Integer] the superseding era
|
|
42
49
|
# @return [Integer] `ordinal`
|
|
43
50
|
def record_superseded(ordinal) = registry.superseded_eras[domain_name] = ordinal
|
|
51
|
+
|
|
52
|
+
# Records that this boot's shape is held by no era, with the latest held era it reads.
|
|
53
|
+
#
|
|
54
|
+
# @param ordinal [Integer] the latest held era
|
|
55
|
+
# @return [Integer] `ordinal`
|
|
56
|
+
def record_unminted(ordinal) = registry.unminted_eras[domain_name] = ordinal
|
|
57
|
+
|
|
58
|
+
# Records that this boot's shape is one recorded move or edge ahead of the latest
|
|
59
|
+
# held era.
|
|
60
|
+
#
|
|
61
|
+
# @param ordinal [Integer] the latest held era the move leaves
|
|
62
|
+
# @return [Integer] `ordinal`
|
|
63
|
+
def record_behind(ordinal) = registry.behind_eras[domain_name] = ordinal
|
|
44
64
|
end
|
|
45
65
|
end
|
|
46
66
|
end
|
|
@@ -111,9 +111,11 @@ module Hecks
|
|
|
111
111
|
|
|
112
112
|
# The aggregate's head as the chain's last step receives it.
|
|
113
113
|
def translated_before(lineage, aggregate, ordinal, chain)
|
|
114
|
+
split = lineage.split_latest(aggregate, chain)
|
|
115
|
+
return split if split
|
|
114
116
|
return lineage.ancestor_latest(aggregate, ordinal, chain) unless chain.size > 1
|
|
115
117
|
|
|
116
|
-
lineage.
|
|
118
|
+
lineage.received_latest(aggregate, ordinal, chain)
|
|
117
119
|
end
|
|
118
120
|
end
|
|
119
121
|
end
|