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,120 @@
|
|
|
1
|
+
# The Run kind: an aggregate declared `kind: "Run"` is one request to the codebase tooling, carried
|
|
2
|
+
# out only inside a hecks checkout. It holds the lifecycle every such request shares, the three
|
|
3
|
+
# bookkeeping commands that move it along, the two queries that read how requests ended, and the
|
|
4
|
+
# policies that examine, accept, perform and record it.
|
|
5
|
+
#
|
|
6
|
+
# This file is aggregate-body text in the bluebook's own words. `{Name}` stands for the aggregate's
|
|
7
|
+
# name and `{Stem}` for that name without the kind (`GateRun` has the stem `Gate`). The aggregate's
|
|
8
|
+
# own body is evaluated at the `# body` line, so its attributes, value objects and request commands
|
|
9
|
+
# fall between the lines above and below it.
|
|
10
|
+
attribute :run, RunKey
|
|
11
|
+
attribute :operation, Operation, optional: true
|
|
12
|
+
|
|
13
|
+
value_object "RunKey" do
|
|
14
|
+
attribute :value, String, matches: :present
|
|
15
|
+
|
|
16
|
+
invariant("a run is named") { !value.to_s.empty? }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
value_object "Operation" do
|
|
20
|
+
attribute :value, String, matches: :present
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
value_object "Switch" do
|
|
24
|
+
attribute :value, Boolean
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
value_object "Report" do
|
|
28
|
+
attribute :value, String
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# body
|
|
32
|
+
|
|
33
|
+
attribute :checkout, Switch, optional: true
|
|
34
|
+
attribute :report, Report, optional: true
|
|
35
|
+
attribute :refusal, Report, optional: true
|
|
36
|
+
identified_by :run
|
|
37
|
+
|
|
38
|
+
lifecycle :status, default: "requested" do
|
|
39
|
+
mark :failure, "faulted"
|
|
40
|
+
transition "Accept" => "accepted", from: "requested"
|
|
41
|
+
transition "Complete" => "completed", from: "accepted"
|
|
42
|
+
transition "Fault" => "faulted", from: %w[requested accepted]
|
|
43
|
+
mark :terminal, "completed", "faulted"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# What the tree reported about itself, held against every request: nothing here runs
|
|
47
|
+
# outside a hecks checkout (hecks.gemspec beside lib/).
|
|
48
|
+
command "Accept" do
|
|
49
|
+
role "System"
|
|
50
|
+
goal "Let a request through only when the working tree is a hecks checkout"
|
|
51
|
+
|
|
52
|
+
reference_to {Name}
|
|
53
|
+
attribute :checkout, Switch, sets: true
|
|
54
|
+
|
|
55
|
+
given("needs a hecks checkout: hecks.gemspec stands beside lib/") { checkout.value }
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
emits {Stem}Accepted
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
command "Complete" do
|
|
62
|
+
role "System"
|
|
63
|
+
goal "Record that the request was carried out, and what it reported"
|
|
64
|
+
|
|
65
|
+
reference_to {Name}
|
|
66
|
+
attribute :report, Report, sets: true
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
emits {Stem}Completed
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
command "Fault" do
|
|
73
|
+
role "System"
|
|
74
|
+
goal "Record that the request was refused or could not be carried out, and why"
|
|
75
|
+
|
|
76
|
+
reference_to {Name}
|
|
77
|
+
attribute :refusal, Report, sets: true
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
emits {Stem}Faulted
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
query "{Stem}Outcome" do
|
|
84
|
+
description "How one request ended: its status, and what it reported or why it failed."
|
|
85
|
+
attribute :run, RunKey
|
|
86
|
+
where(run: :run)
|
|
87
|
+
order_by :run
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
query "{Stem}Faulted" do
|
|
91
|
+
description "Every request that was refused or could not be carried out."
|
|
92
|
+
where(status: "faulted")
|
|
93
|
+
order_by :run
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
policy "Accept{Stem}WhenExamined" do
|
|
97
|
+
on "{Name}.{Stem}Examined"
|
|
98
|
+
trigger {Name}::Accept, with: { checkout: :checkout }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
policy "Fault{Stem}WhenNotAccepted" do
|
|
102
|
+
on "{Name}.{Stem}Examined"
|
|
103
|
+
where { !checkout.value }
|
|
104
|
+
trigger {Name}::Fault, with: { refusal: "needs a hecks checkout: hecks.gemspec stands beside lib/" }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
policy "Perform{Stem}WhenAccepted" do
|
|
108
|
+
on "{Name}.{Stem}Accepted"
|
|
109
|
+
ask :perform, with: { run: :run }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
policy "Record{Stem}Outcome" do
|
|
113
|
+
on "{Name}.{Stem}Answered"
|
|
114
|
+
trigger {Name}::Complete, with: { report: :report }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
policy "Record{Stem}Fault" do
|
|
118
|
+
on "{Name}.{Stem}Refused"
|
|
119
|
+
trigger {Name}::Fault, with: { refusal: :refusal }
|
|
120
|
+
end
|
|
@@ -81,6 +81,11 @@
|
|
|
81
81
|
"verb": "Bluebook::Bluebook.Declare",
|
|
82
82
|
"role": "Language"
|
|
83
83
|
},
|
|
84
|
+
{
|
|
85
|
+
"scope": "bluebook:bluebook.group",
|
|
86
|
+
"verb": "Bluebook::Bluebook.Group",
|
|
87
|
+
"role": "Language"
|
|
88
|
+
},
|
|
84
89
|
{
|
|
85
90
|
"scope": "bluebook:bluebook.normalise",
|
|
86
91
|
"verb": "Bluebook::Bluebook.Normalise",
|
|
@@ -96,6 +101,11 @@
|
|
|
96
101
|
"verb": "Bluebook::Command.ActsOn",
|
|
97
102
|
"role": "Language"
|
|
98
103
|
},
|
|
104
|
+
{
|
|
105
|
+
"scope": "bluebook:command.address",
|
|
106
|
+
"verb": "Bluebook::Command.Address",
|
|
107
|
+
"role": "Language"
|
|
108
|
+
},
|
|
99
109
|
{
|
|
100
110
|
"scope": "bluebook:command.allow",
|
|
101
111
|
"verb": "Bluebook::Command.Allow",
|
|
@@ -31,6 +31,7 @@ Hecks.bluebook "Translation" do
|
|
|
31
31
|
attribute :retypes, list_of(TranslationRetype)
|
|
32
32
|
attribute :derives, list_of(TranslationDerive)
|
|
33
33
|
attribute :rekeys, list_of(TranslationRekey)
|
|
34
|
+
attribute :splits, list_of(TranslationSplit)
|
|
34
35
|
attribute :backfills, list_of(TranslationBackfill)
|
|
35
36
|
|
|
36
37
|
# Field names mirror the Struct records in lib/hecks/bluebook/translation.rb, not the
|
|
@@ -65,6 +66,12 @@ Hecks.bluebook "Translation" do
|
|
|
65
66
|
attribute :to, TranslationName
|
|
66
67
|
end
|
|
67
68
|
|
|
69
|
+
value_object "TranslationSplit" do
|
|
70
|
+
attribute :into, TranslationName
|
|
71
|
+
attribute :keyed_by, TranslationName
|
|
72
|
+
attribute :fields, list_of(TranslationName)
|
|
73
|
+
end
|
|
74
|
+
|
|
68
75
|
value_object "TranslationBackfill" do
|
|
69
76
|
attribute :name, TranslationName
|
|
70
77
|
attribute :default, TranslationLiteralText
|
|
@@ -168,6 +175,19 @@ Hecks.bluebook "Translation" do
|
|
|
168
175
|
emits "TranslationRekeyToAdded"
|
|
169
176
|
end
|
|
170
177
|
|
|
178
|
+
command "AddSplit" do
|
|
179
|
+
role "Deployment"
|
|
180
|
+
goal "Write rows into another aggregate from this one's rows, keyed by a field both share"
|
|
181
|
+
|
|
182
|
+
attribute :into, TranslationName
|
|
183
|
+
attribute :keyed_by, TranslationName
|
|
184
|
+
attribute :fields, list_of(TranslationName)
|
|
185
|
+
|
|
186
|
+
sets :splits, append: { into: :into, keyed_by: :keyed_by, fields: :fields }
|
|
187
|
+
|
|
188
|
+
emits "TranslationSplitAdded"
|
|
189
|
+
end
|
|
190
|
+
|
|
171
191
|
command "AddBackfill" do
|
|
172
192
|
role "Deployment"
|
|
173
193
|
goal "Name a newly required attribute and the value an existing record reads until written for real"
|
|
@@ -194,6 +214,7 @@ Hecks.bluebook "Translation" do
|
|
|
194
214
|
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
195
215
|
|
|
196
216
|
member word: "rename", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "renames", calls: "rename_impl"
|
|
217
|
+
member word: "split", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "splits", calls: "split_impl"
|
|
197
218
|
member word: "move", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "moves", calls: "move_impl"
|
|
198
219
|
member word: "convert", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "converts", calls: "convert_impl"
|
|
199
220
|
member word: "drop", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "drops"
|
|
@@ -224,6 +245,9 @@ Hecks.bluebook "Translation" do
|
|
|
224
245
|
|
|
225
246
|
member keyword: "rename", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "old_name"
|
|
226
247
|
member keyword: "rename", context: "TranslationAggregate", at: "", named: "to", kind: "symbol", required: "true", fills: "to"
|
|
248
|
+
member keyword: "split", context: "TranslationAggregate", at: "", named: "into", kind: "text", required: "true", fills: "into"
|
|
249
|
+
member keyword: "split", context: "TranslationAggregate", at: "", named: "keyed_by", kind: "text", required: "true", fills: "keyed_by"
|
|
250
|
+
member keyword: "split", context: "TranslationAggregate", at: "", named: "fields", kind: "text", required: "true", fills: "fields"
|
|
227
251
|
member keyword: "move", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
|
|
228
252
|
member keyword: "move", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
|
|
229
253
|
member keyword: "convert", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
# The module folders of a domain directory (ADR 0163). A folder named for a module holds that
|
|
3
|
+
# module's bluebook beside its name, `deliver/deliver.bluebook`; the bluebooks in them declare
|
|
4
|
+
# the one bluebook the directory's top-level file opens.
|
|
5
|
+
module ModuleFolders
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
# @param directory [String] a domain directory
|
|
9
|
+
# @return [Array<String>] the bluebook of each module folder directly under `directory`,
|
|
10
|
+
# sorted by path
|
|
11
|
+
def bluebooks(directory)
|
|
12
|
+
files(directory, ".bluebook")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def files(directory, extension)
|
|
16
|
+
Dir.glob(File.join(directory, "*", "*#{extension}")).select { |path| module_file?(path, extension) }.sort
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param directory [String] a domain directory
|
|
20
|
+
# @return [Array<String>] the directory's own bluebooks, then those of its module folders
|
|
21
|
+
def all(directory)
|
|
22
|
+
Dir.glob(File.join(directory, "*.bluebook")) + bluebooks(directory)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Whether a bluebook is named for the folder it sits in.
|
|
26
|
+
# @api private
|
|
27
|
+
def module_file?(path, extension)
|
|
28
|
+
File.basename(path, extension) == File.basename(File.dirname(path))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -23,7 +23,7 @@ module Hecks
|
|
|
23
23
|
# shredded or being shredded, is left alone and returns false.
|
|
24
24
|
#
|
|
25
25
|
# @return [Boolean] whether a shred was asked for; the record's status says how it ended
|
|
26
|
-
def shred!(dispatcher, domain:, subject_id:)
|
|
26
|
+
def shred!(dispatcher, domain:, subject_id:)
|
|
27
27
|
provider = dispatcher.registry.provider_of(Bluebook::Capabilities::SUBJECT_KEYS)
|
|
28
28
|
return false unless provider
|
|
29
29
|
|
|
@@ -12,7 +12,11 @@ module Hecks
|
|
|
12
12
|
# (set by `append` on a live write, or by `entries`/`entries_since` on
|
|
13
13
|
# a replayed one); nil for an adapter that assigns none. It rides
|
|
14
14
|
# along so `project` can advance a checkpoint without a second lookup.
|
|
15
|
-
|
|
15
|
+
#
|
|
16
|
+
# `mints_era` is the one-write allowance a command declared with `mints_era true` holds:
|
|
17
|
+
# only this entry, the command's own record, may be journaled through a boot whose shape no
|
|
18
|
+
# era holds yet. Nothing about it is persisted.
|
|
19
|
+
Entry = Struct.new(:operation, :id, :state, :mirrors, :sequence, :mints_era, keyword_init: true) do
|
|
16
20
|
# Tells a projecting adapter that this entry writes a record.
|
|
17
21
|
#
|
|
18
22
|
# @return [Boolean] true when `operation` is the String `"save"`
|
|
@@ -22,6 +26,9 @@ module Hecks
|
|
|
22
26
|
#
|
|
23
27
|
# @return [Boolean] true when `operation` is the String `"delete"`
|
|
24
28
|
def delete? = operation == "delete"
|
|
29
|
+
|
|
30
|
+
# @return [Boolean] true when the command that wrote this entry declared `mints_era true`
|
|
31
|
+
def mints_era? = mints_era == true
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
# Makes append-before-projection a port invariant: adapters keep their own durable
|
|
@@ -49,6 +56,14 @@ module Hecks
|
|
|
49
56
|
"#{adapter.class} does not implement append-only persistence: #{missing.join(", ")}"
|
|
50
57
|
end
|
|
51
58
|
|
|
59
|
+
# Whether the adapter's binding names this command as one whose own record an unminted
|
|
60
|
+
# boot may write (`mints_era` in the world); an adapter with no such binding says no.
|
|
61
|
+
#
|
|
62
|
+
# @param agg [String] the aggregate the command belongs to
|
|
63
|
+
# @param name [String] the command
|
|
64
|
+
# @return [Boolean]
|
|
65
|
+
def mints_era_declared?(agg, name) = adapter.respond_to?(:mints_era_declared?) && adapter.mints_era_declared?(agg, name)
|
|
66
|
+
|
|
52
67
|
# Reads one record's current projected state from the adapter.
|
|
53
68
|
#
|
|
54
69
|
# @param id [String, Object] the record's identity; adapters compare it as `id.to_s`
|
|
@@ -183,15 +198,16 @@ module Hecks
|
|
|
183
198
|
# Returns an Outcome, not a bare Instance, so callers can check `:saved` vs `:stale`;
|
|
184
199
|
# `expected_version:` only triggers CAS on an adapter declaring `:optimistic_concurrency`.
|
|
185
200
|
#
|
|
186
|
-
# @param instance [Runtime::Instance] the record to persist; its `state` is shallow
|
|
187
|
-
# copied into the entry
|
|
201
|
+
# @param instance [Runtime::Instance] the record to persist; its `state` is shallow copied
|
|
188
202
|
# @param expected_version [Integer, nil] the version the instance was read at, or nil
|
|
189
203
|
# for an unconditional write
|
|
204
|
+
# @param mints_era [Boolean] true when the writing command declares `mints_era true`
|
|
190
205
|
# @return [Persistence::Outcome] status `:saved` or `:stale`; `instance` is the
|
|
191
206
|
# adapter's projected result on `:saved`, else the instance passed in
|
|
192
207
|
# @raise [Runtime::WiringError] when the adapter's `append` or `project` refuses
|
|
193
|
-
def save(instance, expected_version: nil)
|
|
194
|
-
entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup
|
|
208
|
+
def save(instance, expected_version: nil, mints_era: false)
|
|
209
|
+
entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup,
|
|
210
|
+
mints_era: mints_era)
|
|
195
211
|
append(entry)
|
|
196
212
|
if expected_version && capabilities.include?(:optimistic_concurrency)
|
|
197
213
|
saved = @adapter.project(entry, expected_version: expected_version)
|
|
@@ -208,19 +224,21 @@ module Hecks
|
|
|
208
224
|
#
|
|
209
225
|
# @param instance [Runtime::Instance] the record to persist
|
|
210
226
|
# @param insert_only [Boolean] true to refuse replacing a record that already exists
|
|
227
|
+
# @param mints_era [Boolean] true when the writing command declares `mints_era true`
|
|
211
228
|
# @return [Persistence::Outcome] status `:inserted`, `:replaced`, or `:conflicted` when
|
|
212
229
|
# `insert_only` met an existing record and nothing was written; `instance` is always
|
|
213
230
|
# the instance passed in
|
|
214
231
|
# @raise [Runtime::WiringError] if the adapter does not both advertise `:atomic_put`
|
|
215
232
|
# and implement it
|
|
216
233
|
# @raise [ArgumentError] if the adapter answers a status outside `Outcome::STATUSES`
|
|
217
|
-
def atomic_put(instance, insert_only: false)
|
|
234
|
+
def atomic_put(instance, insert_only: false, mints_era: false)
|
|
218
235
|
unless capabilities.include?(:atomic_put) && @adapter.respond_to?(:atomic_put)
|
|
219
236
|
raise Runtime::WiringError,
|
|
220
237
|
"#{@adapter.class} advertises no atomic_put persistence capability"
|
|
221
238
|
end
|
|
222
239
|
|
|
223
|
-
entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup
|
|
240
|
+
entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup,
|
|
241
|
+
mints_era: mints_era)
|
|
224
242
|
status = @adapter.atomic_put(entry, insert_only: insert_only)
|
|
225
243
|
Outcome.new(status: status, instance: instance)
|
|
226
244
|
end
|
|
@@ -231,7 +249,7 @@ module Hecks
|
|
|
231
249
|
# @return [Boolean] true when a record was found and deleted, false when there was
|
|
232
250
|
# none and nothing was journaled
|
|
233
251
|
# @raise [Runtime::WiringError] when the adapter's `append` or `project` refuses
|
|
234
|
-
def delete(id)
|
|
252
|
+
def delete(id)
|
|
235
253
|
return false unless find(id)
|
|
236
254
|
|
|
237
255
|
entry = Entry.new(operation: "delete", id: id.to_s, state: nil)
|
|
@@ -80,7 +80,9 @@ module Hecks
|
|
|
80
80
|
# @return [Bluebook::Bind] the authoritative bind
|
|
81
81
|
# @raise [Runtime::WiringError] if the roleless count is not one, or a role is present
|
|
82
82
|
def authoritative_among(bindings, domain, aggregate)
|
|
83
|
-
|
|
83
|
+
# The same adapter declared again, by a hecksagon that another domain also attaches, is one
|
|
84
|
+
# binding, not an ambiguous second one.
|
|
85
|
+
authoritative = bindings.select { |bind| bind.role.nil? || bind.role.empty? }.uniq(&:adapter)
|
|
84
86
|
raise ambiguous_binding(domain, aggregate, authoritative) unless authoritative.size == 1
|
|
85
87
|
|
|
86
88
|
roled = bindings - authoritative
|
|
@@ -83,7 +83,7 @@ module Hecks
|
|
|
83
83
|
module Guarded; end
|
|
84
84
|
|
|
85
85
|
# A per-adapter-class cache, filled lazily under `WRAPPERS_LOCK`; deliberately mutable.
|
|
86
|
-
WRAPPERS = {}
|
|
86
|
+
WRAPPERS = {}
|
|
87
87
|
WRAPPERS_LOCK = Mutex.new
|
|
88
88
|
|
|
89
89
|
# Builds, or fetches from the cache, the module that guards one adapter class.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require_relative "../../runtime/errors"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Ports
|
|
5
|
+
module Persistence
|
|
6
|
+
# The commands whose own record an unminted boot may write, as a persistence binding names
|
|
7
|
+
# them: `persisted_by("PostgresEra") { mints_era "Maintenance.MintEra" }` in a world. This is
|
|
8
|
+
# where the allowance lives; the `mints_era true` a command can still carry is read as a
|
|
9
|
+
# fallback, and the two must agree.
|
|
10
|
+
#
|
|
11
|
+
# A name is `Aggregate.Command`. The world may give one name or a list.
|
|
12
|
+
module MintDoor
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# @param settings [Hash{Symbol, String => Object}] a persistence binding's settings
|
|
16
|
+
# @return [Array<String>] the `Aggregate.Command` names the binding declares, else `[]`
|
|
17
|
+
def names(settings)
|
|
18
|
+
Array(settings.transform_keys(&:to_sym)[:mints_era]).map(&:to_s)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @param settings [Hash] a persistence binding's settings
|
|
22
|
+
# @param aggregate_name [String] the aggregate the command belongs to
|
|
23
|
+
# @param command_name [String] the command
|
|
24
|
+
# @return [Boolean] true when the binding names `aggregate_name.command_name`
|
|
25
|
+
def declared?(settings, aggregate_name, command_name)
|
|
26
|
+
names(settings).include?("#{aggregate_name}.#{command_name}")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Checks the binding against the bluebook it serves, before anything is written.
|
|
30
|
+
#
|
|
31
|
+
# A binding that names no command leaves the bluebook word alone. One that does must name
|
|
32
|
+
# only commands the bluebook declares, and every command the bluebook flags with
|
|
33
|
+
# `mints_era true` must be among them, so the two never disagree about who may write.
|
|
34
|
+
#
|
|
35
|
+
# @param bluebook [Bluebook::Declaration] the bluebook the binding serves
|
|
36
|
+
# @param settings [Hash] the binding's settings
|
|
37
|
+
# @return [void]
|
|
38
|
+
# @raise [Runtime::WiringError] naming the command when the two disagree
|
|
39
|
+
def check!(bluebook, settings)
|
|
40
|
+
declared = names(settings)
|
|
41
|
+
return if declared.empty?
|
|
42
|
+
|
|
43
|
+
known = commands_of(bluebook)
|
|
44
|
+
unknown = declared - known.keys
|
|
45
|
+
raise_unknown!(bluebook, unknown, known) unless unknown.empty?
|
|
46
|
+
|
|
47
|
+
unnamed = known.select { |name, flagged| flagged && !declared.include?(name) }.keys
|
|
48
|
+
raise_unnamed!(bluebook, unnamed, declared) unless unnamed.empty?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [Hash{String => Boolean}] `Aggregate.Command` => whether it says `mints_era true`
|
|
52
|
+
def commands_of(bluebook)
|
|
53
|
+
bluebook.aggregates.flat_map do |aggregate|
|
|
54
|
+
aggregate.commands.map { |command| ["#{aggregate.hecks_name}.#{command.hecks_name}", command.mints_era?] }
|
|
55
|
+
end.to_h
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def raise_unknown!(bluebook, unknown, known)
|
|
59
|
+
raise Runtime::WiringError,
|
|
60
|
+
"the world's mints_era names #{unknown.join(", ")}, but #{bluebook.name} declares no such command " \
|
|
61
|
+
"(its commands: #{known.keys.join(", ")}). A name that matches nothing would let no write through " \
|
|
62
|
+
"an unminted boot, so the boot refuses."
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def raise_unnamed!(bluebook, unnamed, declared)
|
|
66
|
+
raise Runtime::WiringError,
|
|
67
|
+
"#{unnamed.join(", ")} declares `mints_era true` in #{bluebook.name}, but the world's mints_era " \
|
|
68
|
+
"(#{declared.join(", ")}) does not name it. Name it in the world, or remove the word from the " \
|
|
69
|
+
"command: the two must agree."
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -4,6 +4,7 @@ require_relative "lineage"
|
|
|
4
4
|
require_relative "../../../../naming"
|
|
5
5
|
require_relative "../../../../framework"
|
|
6
6
|
require_relative "../../../../framework_bluebooks"
|
|
7
|
+
require_relative "../../../../module_folders"
|
|
7
8
|
require_relative "../../../../runtime/registry"
|
|
8
9
|
|
|
9
10
|
module Hecks
|
|
@@ -67,10 +68,10 @@ module Hecks
|
|
|
67
68
|
|
|
68
69
|
# Reads the source text one bluebook was declared in, wherever that source lives.
|
|
69
70
|
#
|
|
70
|
-
# Matched by declared name, not position
|
|
71
|
-
#
|
|
72
|
-
# member or vendored bluebook is
|
|
73
|
-
# fallback so its own
|
|
71
|
+
# Matched by declared name, not position, over the files the loader reads in its order
|
|
72
|
+
# (ModuleFolders.all): a held era freezes this text, so a domain split into module folders
|
|
73
|
+
# is held whole. A framework member or vendored bluebook is left out of the single-file
|
|
74
|
+
# fallback so its own source is read, not a sibling's.
|
|
74
75
|
#
|
|
75
76
|
# @param bluebook [Bluebook::Declaration] the bluebook whose source is wanted
|
|
76
77
|
# @param directory [String] path of the domain's own bluebook directory
|
|
@@ -78,7 +79,7 @@ module Hecks
|
|
|
78
79
|
# @return [String, nil] UTF-8 text of every matching file joined with `"\n"`, or nil
|
|
79
80
|
def source_text_for(bluebook, directory, registry: nil)
|
|
80
81
|
domain_files = Dir[File.join(directory, "*.bluebook")]
|
|
81
|
-
own =
|
|
82
|
+
own = ModuleFolders.all(directory).select { |path| declares_bluebook?(path, bluebook.name) }
|
|
82
83
|
own = fallback_source_files(bluebook, directory, domain_files, registry) if own.empty?
|
|
83
84
|
return if own.empty?
|
|
84
85
|
|
|
@@ -68,10 +68,14 @@ module Hecks
|
|
|
68
68
|
paths.reject { |path| lineage.explains?(path) }
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
# Compares one path's held and current types, recursing into shared members.
|
|
71
|
+
# Compares one path's held and current types, recursing into shared members. A type is
|
|
72
|
+
# compared by its name: a stored shape holds every type as its string
|
|
73
|
+
# (`"Reference<Target>"`), a declared bluebook may hold an object that prints the same.
|
|
72
74
|
# A `list_of` entity is diffed only for member drift; no per-element translation exists, so
|
|
73
75
|
# only a top-level `drop` of the whole list satisfies it.
|
|
74
76
|
def diff_type(path, held_type, current_type, sides, seen = [])
|
|
77
|
+
held_type = held_type.to_s
|
|
78
|
+
current_type = current_type.to_s
|
|
75
79
|
return [path] if retype_drift?(held_type, current_type, sides.lineage)
|
|
76
80
|
return [] if seen.include?(current_type)
|
|
77
81
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require_relative "era_check"
|
|
2
|
+
require_relative "storage_shape"
|
|
3
|
+
|
|
4
|
+
module Hecks
|
|
5
|
+
module Runtime
|
|
6
|
+
# What a boot would resolve for each bluebook a registry loaded, asked of the same adapter the
|
|
7
|
+
# boot's era gate asks (`EraCheck`), against the database each bluebook's own world declares.
|
|
8
|
+
# Nothing is minted, provisioned or recorded: an era-holding adapter answers over a connection
|
|
9
|
+
# that can only read. A bluebook bound to an adapter that holds no eras answers `no_eras`.
|
|
10
|
+
module EraStatus
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
# @param registry [Runtime::Registry] the loaded registry, as a boot loads it
|
|
14
|
+
# @param directory [String] the domain's bluebook directory
|
|
15
|
+
# @return [Hash{String => Hash}] each bluebook's status row, by name: `status`, `held`,
|
|
16
|
+
# `current`, `ordinal`, `move`, `reason` and `source` (`database`, or `none` for `no_eras`)
|
|
17
|
+
# @raise [Runtime::WiringError] if a binding cannot be resolved, a database is unreachable, or
|
|
18
|
+
# a held text was altered
|
|
19
|
+
def rows(registry, directory)
|
|
20
|
+
registry.bluebooks.to_h { |name, bluebook| [name, row_for(registry, bluebook, directory)] }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# One bluebook's status row.
|
|
24
|
+
#
|
|
25
|
+
# @param registry [Runtime::Registry] the loaded registry
|
|
26
|
+
# @param bluebook [Bluebook::Declaration] the bluebook as it stands
|
|
27
|
+
# @param directory [String] the domain's bluebook directory
|
|
28
|
+
# @return [Hash] the row
|
|
29
|
+
def row_for(registry, bluebook, directory)
|
|
30
|
+
first = bluebook.aggregates.first
|
|
31
|
+
adapter = first && EraCheck.adapter_for(registry, bluebook.name, first)
|
|
32
|
+
return no_eras(bluebook, adapter || "nothing") unless adapter && EraCheck.lineage_capable?(registry, adapter)
|
|
33
|
+
|
|
34
|
+
settings = registry.binding_settings(bluebook.name, Ports::Persistence::VERB, adapter)
|
|
35
|
+
registry.adapter_class(adapter).era_status(registry: registry, bluebook: bluebook, settings: settings,
|
|
36
|
+
directory: directory).to_row
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param bluebook [Bluebook::Declaration] the bluebook
|
|
40
|
+
# @param adapter [String] the adapter it is bound to
|
|
41
|
+
# @return [Hash] the row of a bluebook whose store holds no eras
|
|
42
|
+
def no_eras(bluebook, adapter)
|
|
43
|
+
{ "status" => "no_eras", "held" => nil, "current" => StorageShape.mint_label(bluebook), "ordinal" => nil,
|
|
44
|
+
"move" => nil, "reason" => "#{bluebook.name} is bound to #{adapter}, which holds no eras", "source" => "none" }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require "digest"
|
|
2
|
+
require "json"
|
|
3
|
+
|
|
4
|
+
module Hecks
|
|
5
|
+
module Runtime
|
|
6
|
+
# A held era read from the storage shape its mint recorded, answering the bluebook questions an
|
|
7
|
+
# era's diff, additive rule and coverage check ask of the side they translate from: each
|
|
8
|
+
# aggregate's name, identity paths and attributes, and each value object's members.
|
|
9
|
+
#
|
|
10
|
+
# The shape is what an era is: its hash is the SHA-256 of the shape's canonical JSON, the same
|
|
11
|
+
# one `StorageShape.mint_hash` takes of a declared bluebook. Nothing here parses held text.
|
|
12
|
+
class ProjectedBluebook
|
|
13
|
+
# One attribute or value-object member, by name and type name. The name is a Symbol and the
|
|
14
|
+
# type name a String, as a declared bluebook answers them.
|
|
15
|
+
Attribute = Data.define(:name, :type, :list) do
|
|
16
|
+
# @return [Boolean] whether the attribute holds a list
|
|
17
|
+
def list? = list
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# A value object or entity an attribute's type names, with its members.
|
|
21
|
+
Container = Data.define(:name, :attributes) do
|
|
22
|
+
# @param name [String, Symbol] a member name
|
|
23
|
+
# @return [Attribute, nil] the member of that name
|
|
24
|
+
def attribute(name) = attributes.find { |member| member.name.to_s == name.to_s }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# One aggregate of the held shape.
|
|
28
|
+
class Aggregate
|
|
29
|
+
attr_reader :name, :identity_paths, :attributes
|
|
30
|
+
|
|
31
|
+
# @param shape [Hash{String => Object}] one entry of the projection's `aggregates`
|
|
32
|
+
def initialize(shape)
|
|
33
|
+
@name = shape["name"]
|
|
34
|
+
@identity_paths = Array(shape["identity"])
|
|
35
|
+
@containers = {}
|
|
36
|
+
@attributes = Array(shape["attributes"]).map { |attribute| read(attribute) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param name [String, Symbol] an attribute name
|
|
40
|
+
# @return [Attribute, nil] the attribute of that name
|
|
41
|
+
def attribute(name) = attributes.find { |attribute| attribute.name.to_s == name.to_s }
|
|
42
|
+
|
|
43
|
+
# @param type_name [String] a type name an attribute or member names
|
|
44
|
+
# @return [Container, nil] the value object or entity of that name
|
|
45
|
+
def value_object(type_name) = @containers[type_name]
|
|
46
|
+
|
|
47
|
+
# @return [Array] none: entities are answered as containers by `value_object`
|
|
48
|
+
def entities = []
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# Reads one attribute or member, keeping the container its type expands to.
|
|
53
|
+
def read(attribute)
|
|
54
|
+
type = attribute["type"]
|
|
55
|
+
type = contain(type) if type.is_a?(Hash)
|
|
56
|
+
Attribute.new(name: attribute["name"].to_sym, type: type, list: attribute["list"] == true)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Keeps the value object or entity a type expands to, and answers its name.
|
|
60
|
+
def contain(type)
|
|
61
|
+
name = type["type"]
|
|
62
|
+
@containers[name] ||= Container.new(name: name, attributes: Array(type["members"]).map { |member| read(member) })
|
|
63
|
+
name
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
attr_reader :projection, :name, :aggregates
|
|
68
|
+
|
|
69
|
+
# @param projection [Hash{String => Object}] a storage shape, as `StorageShape.project`
|
|
70
|
+
# answers it or as `hecks_eras.held_projection` stores it
|
|
71
|
+
def initialize(projection)
|
|
72
|
+
@projection = projection
|
|
73
|
+
@name = projection["name"]
|
|
74
|
+
@aggregates = Array(projection["aggregates"]).map { |shape| Aggregate.new(shape) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @param projection_or_bluebook [Hash, ProjectedBluebook, Object] a storage shape, a view, or
|
|
78
|
+
# a declared bluebook
|
|
79
|
+
# @return [ProjectedBluebook, Object] a storage shape wrapped as a view; anything else as
|
|
80
|
+
# given
|
|
81
|
+
def self.wrap(projection_or_bluebook)
|
|
82
|
+
projection_or_bluebook.is_a?(Hash) ? new(projection_or_bluebook) : projection_or_bluebook
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param name [String, Symbol] an aggregate name
|
|
86
|
+
# @return [Aggregate, nil] the aggregate of that name
|
|
87
|
+
def aggregate(name) = aggregates.find { |aggregate| aggregate.name == name.to_s }
|
|
88
|
+
|
|
89
|
+
# @return [nil] a held shape carries no rename marker; the declared bluebook does
|
|
90
|
+
def formerly_known_as = nil
|
|
91
|
+
|
|
92
|
+
# @return [String] the era's hash: the SHA-256 of the shape's canonical JSON
|
|
93
|
+
def mint_hash = Digest::SHA256.hexdigest(JSON.generate(Canonical.shape(projection)))
|
|
94
|
+
|
|
95
|
+
# The storage shape with its keys in the order `StorageShape.project` builds them, so a shape
|
|
96
|
+
# read back from `jsonb`, which reorders keys, hashes as it did when it was minted.
|
|
97
|
+
module Canonical
|
|
98
|
+
module_function
|
|
99
|
+
|
|
100
|
+
# @param shape [Hash] a storage shape
|
|
101
|
+
# @return [Hash] the shape with its keys in canonical order
|
|
102
|
+
def shape(shape)
|
|
103
|
+
{ "name" => shape["name"], "aggregates" => Array(shape["aggregates"]).map { |aggregate| aggregate(aggregate) } }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @return [Hash] one aggregate's shape in canonical key order
|
|
107
|
+
def aggregate(aggregate)
|
|
108
|
+
{ "name" => aggregate["name"], "identity" => aggregate["identity"],
|
|
109
|
+
"lifecycle_field" => aggregate["lifecycle_field"],
|
|
110
|
+
"attributes" => Array(aggregate["attributes"]).map { |attribute| attribute(attribute) } }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @return [Hash] one attribute's shape in canonical key order
|
|
114
|
+
def attribute(attribute)
|
|
115
|
+
{ "name" => attribute["name"], "list" => attribute["list"], "type" => type(attribute["type"]) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @return [String, Hash] a scalar type as given, or a container in canonical key order
|
|
119
|
+
def type(type)
|
|
120
|
+
return type unless type.is_a?(Hash)
|
|
121
|
+
|
|
122
|
+
{ "type" => type["type"], "members" => Array(type["members"]).map { |member| attribute(member) } }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|