hecks 2.9.0 → 3.0.1
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 +51 -6
- data/lib/hecks/adapters/driven/heki/journal.rb +1 -1
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +1 -1
- data/lib/hecks/adapters/driven/memory.rb +16 -3
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +6 -2
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +13 -4
- data/lib/hecks/adapters/driven/prism.rb +41 -8
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +73 -16
- data/lib/hecks/behaviors/expectations.rb +1 -1
- data/lib/hecks/behaviors.rb +1 -1
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +2 -0
- data/lib/hecks/bluebook/attribute.rb +1 -1
- data/lib/hecks/bluebook/behaviour/aggregate.rb +30 -1
- data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -0
- data/lib/hecks/bluebook/chapter.rb +6 -2
- data/lib/hecks/bluebook/domain_port.rb +36 -5
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +10 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +8 -0
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -1
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +31 -3
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +122 -3
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +1 -1
- data/lib/hecks/bluebook/dsl/query_builder.rb +27 -1
- data/lib/hecks/bluebook/dsl/rule_reference.rb +1 -1
- data/lib/hecks/bluebook/dsl/world_builder.rb +29 -2
- data/lib/hecks/bluebook/expression/canonical_form.rb +1 -1
- data/lib/hecks/bluebook/expression/resolver.rb +3 -2
- data/lib/hecks/bluebook/hexagon.rb +13 -5
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +1 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +4 -1
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator.rb +9 -4
- data/lib/hecks/bluebook/model_check.rb +23 -0
- data/lib/hecks/bluebook/pattern_subset.rb +38 -0
- data/lib/hecks/bluebook/query.rb +20 -5
- data/lib/hecks/bluebook/smoke_test.rb +1 -1
- data/lib/hecks/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +2 -2
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +1 -1
- data/lib/hecks/cli/mcp.rb +3 -3
- data/lib/hecks/cli/model_check.rb +15 -8
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +224 -32
- data/lib/hecks/cli/project_diagrams.rb +4 -3
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +3 -3
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +5 -3
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -5
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +201 -52
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +591 -23
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -4
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +1 -1
- data/lib/hecks/{facade → doors}/handle.rb +2 -2
- data/lib/hecks/{facade → doors}/json_door.rb +4 -4
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +7 -7
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/{facade/surface → doors/ruby_door}/aggregate_door.rb +8 -3
- data/lib/hecks/{facade/surface → doors/ruby_door}/chapter.rb +3 -3
- data/lib/hecks/{facade/surface.rb → doors/ruby_door.rb} +36 -5
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +1 -1
- data/lib/hecks/embryonaut_bluebook.rb +1 -1
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +24 -37
- data/lib/hecks/forms/app.rb +6 -6
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/field_shape.rb +2 -1
- data/lib/hecks/forms/port_argument.rb +1 -1
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +11 -0
- data/lib/hecks/language/bluebook/query.bluebook +7 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +4 -4
- data/lib/hecks/language/hecksagon/domain_port.bluebook +10 -0
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +20 -0
- data/lib/hecks/mcp_stdio_guard.rb +2 -2
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +8 -5
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +4 -1
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +15 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +32 -15
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +15 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +43 -24
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/state_codec.rb +24 -5
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +1 -1
- data/lib/hecks/projections/deploy/fargate.rb +5 -5
- data/lib/hecks/projections/deploy/lambda.rb +43 -32
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/template.rb +1 -1
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/shared.rb +1 -1
- data/lib/hecks/projections/diagrams.rb +3 -3
- data/lib/hecks/projections/model/deviations.rb +1 -1
- data/lib/hecks/projections/parser_table.rb +4 -4
- data/lib/hecks/projections/reference.rb +2 -3
- data/lib/hecks/projections/rust_vocabulary.rb +1 -1
- data/lib/hecks/projector/cli_projector.rb +106 -37
- data/lib/hecks/projector.rb +1 -1
- data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- data/lib/hecks/release/runner/ci_publisher.rb +2 -2
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +14 -7
- data/lib/hecks/release/runner/npm_publisher.rb +6 -36
- data/lib/hecks/release/runner/preflight.rb +26 -2
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +30 -15
- data/lib/hecks/release/runner.rb +57 -6
- data/lib/hecks/router/namespace_installer.rb +3 -3
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +4 -0
- data/lib/hecks/runtime/dependency_planning.rb +20 -2
- data/lib/hecks/runtime/dispatcher.rb +53 -3
- data/lib/hecks/runtime/interpreting.rb +3 -0
- data/lib/hecks/runtime/loader.rb +65 -12
- data/lib/hecks/runtime/outbox.rb +1 -1
- data/lib/hecks/runtime/policy_interpreter.rb +5 -2
- data/lib/hecks/runtime/port_operation_interpreter.rb +2 -10
- data/lib/hecks/runtime/query_interpreter.rb +77 -0
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/refusal_wording.rb +23 -1
- data/lib/hecks/runtime/registry/verification.rb +163 -4
- data/lib/hecks/runtime/registry.rb +57 -3
- data/lib/hecks/runtime/remote_dispatcher.rb +31 -2
- data/lib/hecks/runtime/value/coercion.rb +23 -135
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +4 -1
- data/lib/hecks/runtime.rb +20 -6
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +16 -16
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +2 -2
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +1 -1
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks.rb +32 -15
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +477 -12
- data/lib/hecks/facade/cli_door.rb +0 -96
- data/lib/hecks/facade/cli_runner.rb +0 -127
- data/lib/hecks/mcp_door_scope.rb +0 -95
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../tools"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Tools
|
|
7
|
+
# Removes a command's `attribute :field, Type` line when it only repeats what an `append:`
|
|
8
|
+
# target element already declares (see `CommandBuilder#resolve_append_fields!`). The
|
|
9
|
+
# edit/reboot/diff-or-revert machinery lives in `Hecks::Codemod`.
|
|
10
|
+
#
|
|
11
|
+
# hecks drop_implicit_append_fields [--dry-run]
|
|
12
|
+
module DropImplicitAppendFields
|
|
13
|
+
# One attribute a command repeats.
|
|
14
|
+
Candidate = Struct.new(:command_name, :field, :type, keyword_init: true)
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# Runs the codemod over every example domain and prints what it found.
|
|
19
|
+
#
|
|
20
|
+
# @param argv [Array<String>] `--dry-run` to restore every file after the rewrite is checked
|
|
21
|
+
# @param root [String] the checkout (unused: the examples come from `Codemod`)
|
|
22
|
+
# @return [Integer] 0
|
|
23
|
+
def main(argv, root: Tools::ROOT)
|
|
24
|
+
_ = root
|
|
25
|
+
require "hecks"
|
|
26
|
+
require "hecks/codemod"
|
|
27
|
+
dry_run = argv.include?("--dry-run")
|
|
28
|
+
|
|
29
|
+
runner = Hecks::Codemod::Runner.new(find_candidates: method(:find_candidates),
|
|
30
|
+
apply_candidate: method(:apply_candidate),
|
|
31
|
+
label: ->(c) { "#{c.command_name}##{c.field} (#{c.type})" })
|
|
32
|
+
results = runner.run(dry_run: dry_run)
|
|
33
|
+
runner.report(results, dry_run: dry_run)
|
|
34
|
+
0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param candidate [Candidate] the attribute a command declares
|
|
38
|
+
# @param owner_attr [Object, nil] the same attribute on the element the command appends to
|
|
39
|
+
# @return [Boolean] whether the two declare the same thing
|
|
40
|
+
def identical_attribute?(candidate, owner_attr)
|
|
41
|
+
return false unless owner_attr
|
|
42
|
+
|
|
43
|
+
%i[type pattern optional? admits].all? { |m| candidate.public_send(m) == owner_attr.public_send(m) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Replays `CommandBuilder#resolve_append_fields!`'s lookup against the booted IR.
|
|
47
|
+
#
|
|
48
|
+
# @param registry [Object] the booted bluebooks
|
|
49
|
+
# @return [Array<Candidate>] the attributes that can be dropped
|
|
50
|
+
def find_candidates(registry)
|
|
51
|
+
found = []
|
|
52
|
+
Hecks::Codemod.each_command(registry) do |construct, command|
|
|
53
|
+
command.mutations.select { |m| m.op == :append }.each do |mutation|
|
|
54
|
+
element = Hecks::Codemod.element_construct_for(construct, mutation.target)
|
|
55
|
+
next unless element
|
|
56
|
+
|
|
57
|
+
mutation.source.each do |field, value|
|
|
58
|
+
next unless value.is_a?(Symbol) && value.to_s == field.to_s
|
|
59
|
+
|
|
60
|
+
local = command.attributes.find { |attr| attr.name.to_s == field.to_s }
|
|
61
|
+
next unless local
|
|
62
|
+
|
|
63
|
+
owner_attr = Hecks::Codemod.owner_attribute(element, field)
|
|
64
|
+
next unless identical_attribute?(local, owner_attr)
|
|
65
|
+
|
|
66
|
+
found << Candidate.new(command_name: command.hecks_name, field: field.to_s, type: local.type)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
found
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @param text [String] a bluebook's source
|
|
74
|
+
# @param candidate [Candidate] the attribute to drop
|
|
75
|
+
# @return [Array(String, Boolean)] `[new_text, true]` on a single clean match, `[text, false]`
|
|
76
|
+
# when ambiguous or absent
|
|
77
|
+
def apply_candidate(text, candidate)
|
|
78
|
+
window_start = text.index(/^\s*command\s+"#{Regexp.escape(candidate.command_name)}"/)
|
|
79
|
+
return [text, false] unless window_start
|
|
80
|
+
|
|
81
|
+
window_end = text.index(/^\s*emits\s/, window_start)
|
|
82
|
+
return [text, false] unless window_end
|
|
83
|
+
|
|
84
|
+
before = text[0...window_start]
|
|
85
|
+
window = text[window_start...window_end]
|
|
86
|
+
after = text[window_end..]
|
|
87
|
+
|
|
88
|
+
pattern = /^[ \t]*attribute\s+:#{Regexp.escape(candidate.field)}\s*,[^\n]*\n/
|
|
89
|
+
return [text, false] unless window.scan(pattern).size == 1
|
|
90
|
+
|
|
91
|
+
[before + window.sub(pattern, "") + after, true]
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hecks"
|
|
4
|
+
require_relative "../tools"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module Tools
|
|
8
|
+
# Backfills `hecks_eras.held_projection` for rows that predate it, by calling the same path
|
|
9
|
+
# `EraStore#eras` already takes on boot, explicitly. Idempotent.
|
|
10
|
+
#
|
|
11
|
+
# hecks backfill_projections <domain path>
|
|
12
|
+
module EraProjectionBackfill
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# Backfills the rows that carry no projection and prints how many it fixed.
|
|
16
|
+
#
|
|
17
|
+
# @param argv [Array<String>] the domain directory
|
|
18
|
+
# @param root [String] unused: the domain is read from the path given
|
|
19
|
+
# @return [Integer] 0, or 1 when a row fails its own integrity check
|
|
20
|
+
# @raise [SystemExit] when the domain cannot be loaded or its adapter holds no eras
|
|
21
|
+
def main(argv, **)
|
|
22
|
+
domain_path = argv.first
|
|
23
|
+
abort "usage: hecks backfill_projections <domain path>" unless domain_path
|
|
24
|
+
|
|
25
|
+
loading = Hecks::Ports::Loading.bootstrap
|
|
26
|
+
directory = loading.bluebook_directory(domain_path)
|
|
27
|
+
registry = Hecks::Runtime::Registry.new(root: File.dirname(directory))
|
|
28
|
+
Hecks.with_registry(registry) do
|
|
29
|
+
loading.load_library
|
|
30
|
+
loading.load_project(loading.shared_root(nil, directory))
|
|
31
|
+
loading.load_each(directory, %w[*.port *.adapter *.bluebook *.hecksagon *.world])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
bluebook = registry.bluebooks.values.first or abort "no bluebook in #{directory}"
|
|
35
|
+
backfill(bluebook, lineage_settings(registry, bluebook))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Hash] the persistence binding's settings
|
|
39
|
+
# @raise [SystemExit] when the bound adapter holds no eras
|
|
40
|
+
def lineage_settings(registry, bluebook)
|
|
41
|
+
first = bluebook.aggregates.first or abort "#{bluebook.name} declares no aggregates"
|
|
42
|
+
adapter_name = Hecks::Ports::Persistence::BindingPolicy.resolve(registry, bluebook.name, first).adapter
|
|
43
|
+
capable =
|
|
44
|
+
begin
|
|
45
|
+
adapter_class = registry.adapter_class(adapter_name)
|
|
46
|
+
adapter_class.respond_to?(:lineage_capable?) && adapter_class.lineage_capable?
|
|
47
|
+
rescue StandardError
|
|
48
|
+
false
|
|
49
|
+
end
|
|
50
|
+
# Only a lineage-capable adapter holds eras — every other adapter has no held_projection
|
|
51
|
+
# column to migrate.
|
|
52
|
+
abort "#{bluebook.name} is bound to #{adapter_name}, which holds no eras — nothing to migrate." unless capable
|
|
53
|
+
|
|
54
|
+
registry.binding_settings(bluebook.name, Hecks::Ports::Persistence::VERB, adapter_name)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @return [Integer] the exit status
|
|
58
|
+
def backfill(bluebook, settings)
|
|
59
|
+
db = Hecks::Adapters::PostgresEra.connect_for(bluebook.name, settings)
|
|
60
|
+
lineage = Hecks::Adapters::PostgresEra::Lineage.new(db, bluebook.name)
|
|
61
|
+
lineage.ensure_base!
|
|
62
|
+
|
|
63
|
+
missing = lambda {
|
|
64
|
+
db.exec_params(
|
|
65
|
+
"SELECT count(*)::int AS n FROM hecks_eras WHERE domain = $1 AND held_projection IS NULL",
|
|
66
|
+
[bluebook.name]
|
|
67
|
+
)[0]["n"].to_i
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
before = missing.call
|
|
71
|
+
if before.zero?
|
|
72
|
+
puts "#{bluebook.name}: every held era already carries a projection — nothing to do."
|
|
73
|
+
return 0
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
begin
|
|
77
|
+
# Raises on the first row whose own digest check fails — a tampered row, not a merely
|
|
78
|
+
# legacy one, which backfilling must not paper over.
|
|
79
|
+
lineage.eras
|
|
80
|
+
rescue Hecks::Runtime::WiringError => e
|
|
81
|
+
puts "#{bluebook.name}: stopped at a row that isn't merely legacy — it fails its own integrity check:"
|
|
82
|
+
puts " #{e.message}"
|
|
83
|
+
puts " resolve that first (see hecks reattest), then run this again for the remaining rows."
|
|
84
|
+
return 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
backfilled = before - missing.call
|
|
88
|
+
puts "#{bluebook.name}: backfilled #{backfilled} era#{'s' unless backfilled == 1} — " \
|
|
89
|
+
"every row now carries a projection."
|
|
90
|
+
0
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hecks"
|
|
4
|
+
require "json"
|
|
5
|
+
require_relative "../tools"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Tools
|
|
9
|
+
# Re-attests an era's held text after a digest-integrity refusal, once a human has read it.
|
|
10
|
+
# Refuses without `--accept`; each attestation (old digest, new digest, when) is logged. The
|
|
11
|
+
# digest is tamper-evidence against drift, not against an adversary.
|
|
12
|
+
#
|
|
13
|
+
# hecks reattest <domain> <era ordinal> [--accept]
|
|
14
|
+
module EraReattest
|
|
15
|
+
USAGE = "usage: hecks reattest <domain> <era ordinal> [--accept]"
|
|
16
|
+
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
# Shows the held text against its recorded digest and, with `--accept`, re-freezes it.
|
|
20
|
+
#
|
|
21
|
+
# @param argv [Array<String>] the domain directory, the era's ordinal and `--accept`
|
|
22
|
+
# @param root [String] unused: the domain is read from the path given
|
|
23
|
+
# @return [Integer] 0 when nothing needed attesting or it was attested, 1 when refused
|
|
24
|
+
# @raise [SystemExit] when the domain cannot be loaded or holds no such era
|
|
25
|
+
def main(argv, **)
|
|
26
|
+
argv = argv.dup
|
|
27
|
+
accept = argv.delete("--accept")
|
|
28
|
+
domain_path = argv.shift
|
|
29
|
+
ordinal = argv.shift&.to_i
|
|
30
|
+
abort USAGE unless domain_path && ordinal&.positive?
|
|
31
|
+
|
|
32
|
+
registry, bluebook = load_domain(domain_path)
|
|
33
|
+
lineage = open_lineage(registry, bluebook)
|
|
34
|
+
era = lineage.raw_era(ordinal) or abort "#{bluebook.name} holds no era #{ordinal}"
|
|
35
|
+
verify(bluebook, lineage, era, ordinal, accept)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# No translations are loaded: an unresolved edge must not block attesting a text.
|
|
39
|
+
#
|
|
40
|
+
# @param domain_path [String] the domain directory
|
|
41
|
+
# @return [Array] the registry and its bluebook
|
|
42
|
+
def load_domain(domain_path)
|
|
43
|
+
loading = Hecks::Ports::Loading.bootstrap
|
|
44
|
+
directory = loading.bluebook_directory(domain_path)
|
|
45
|
+
registry = Hecks::Runtime::Registry.new(root: File.dirname(directory))
|
|
46
|
+
Hecks.with_registry(registry) do
|
|
47
|
+
loading.load_library
|
|
48
|
+
loading.load_project(loading.shared_root(nil, directory))
|
|
49
|
+
loading.load_each(directory, %w[*.port *.adapter *.bluebook *.hecksagon *.world])
|
|
50
|
+
end
|
|
51
|
+
bluebook = registry.bluebooks.values.first or abort "no bluebook in #{directory}"
|
|
52
|
+
[registry, bluebook]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [Object] the domain's ensured lineage
|
|
56
|
+
# @raise [SystemExit] when the bound adapter holds no eras
|
|
57
|
+
def open_lineage(registry, bluebook)
|
|
58
|
+
first = bluebook.aggregates.first or abort "#{bluebook.name} declares no aggregates"
|
|
59
|
+
adapter_name = Hecks::Ports::Persistence::BindingPolicy.resolve(registry, bluebook.name, first).adapter
|
|
60
|
+
capable =
|
|
61
|
+
begin
|
|
62
|
+
adapter_class = registry.adapter_class(adapter_name)
|
|
63
|
+
adapter_class.respond_to?(:lineage_capable?) && adapter_class.lineage_capable?
|
|
64
|
+
rescue StandardError
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
# Only a lineage-capable adapter holds era texts.
|
|
68
|
+
unless capable
|
|
69
|
+
abort "#{bluebook.name} is bound to #{adapter_name}, which holds no eras — " \
|
|
70
|
+
"there is no frozen text to re-attest."
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
settings = registry.world(bluebook.name)&.for_binding(Hecks::Ports::Persistence::VERB, adapter_name) || {}
|
|
74
|
+
db = Hecks::Adapters::PostgresEra.connect_for(bluebook.name, settings)
|
|
75
|
+
lineage = Hecks::Adapters::PostgresEra::Lineage.new(db, bluebook.name)
|
|
76
|
+
lineage.ensure_base!
|
|
77
|
+
lineage
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @return [Integer] the exit status
|
|
81
|
+
def verify(bluebook, lineage, era, ordinal, accept)
|
|
82
|
+
text = era[:held_text]
|
|
83
|
+
stored = era[:held_digest]
|
|
84
|
+
computed = Digest::SHA256.hexdigest(text)
|
|
85
|
+
if stored == computed
|
|
86
|
+
puts "#{bluebook.name} era #{ordinal}: the held text matches its digest — nothing to re-attest."
|
|
87
|
+
return 0
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
puts "#{bluebook.name} era #{ordinal}: the held text does NOT match its recorded digest."
|
|
91
|
+
puts " recorded: #{stored || '(none)'}"
|
|
92
|
+
puts " computed: #{computed}"
|
|
93
|
+
return 1 unless shape_unchanged?(bluebook, era, ordinal, text)
|
|
94
|
+
|
|
95
|
+
show(text)
|
|
96
|
+
return refuse_without_accept unless accept
|
|
97
|
+
|
|
98
|
+
fresh = lineage.reattest!(ordinal)
|
|
99
|
+
puts
|
|
100
|
+
puts "ATTESTED: era #{ordinal} re-frozen as #{fresh[0, 12]}… — the old and new digests are recorded."
|
|
101
|
+
0
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# A shape change refuses hard; no `--accept` passes it.
|
|
105
|
+
#
|
|
106
|
+
# @return [Boolean] false after printing the refusal
|
|
107
|
+
def shape_unchanged?(bluebook, era, ordinal, text)
|
|
108
|
+
stored_projection = era[:held_projection] && JSON.parse(era[:held_projection])
|
|
109
|
+
verdict = Hecks::Translation::Reattest.shape_guard!(
|
|
110
|
+
domain: bluebook.name, ordinal: ordinal, text: text,
|
|
111
|
+
stored_hash: era[:hash], stored_projection: stored_projection
|
|
112
|
+
)
|
|
113
|
+
case verdict
|
|
114
|
+
when :cosmetic
|
|
115
|
+
puts " shape: unchanged — the edit is cosmetic (the text still projects to era #{ordinal}'s " \
|
|
116
|
+
"minted name)"
|
|
117
|
+
when :unnamed
|
|
118
|
+
puts " shape: era #{ordinal} was never named, so no shape comparison is possible — read carefully"
|
|
119
|
+
end
|
|
120
|
+
true
|
|
121
|
+
rescue Hecks::Runtime::WiringError => e
|
|
122
|
+
puts
|
|
123
|
+
puts "REFUSED: #{e.message}"
|
|
124
|
+
false
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @return [void]
|
|
128
|
+
def show(text)
|
|
129
|
+
puts
|
|
130
|
+
puts "The held text AS IT NOW STANDS — the original is gone; this is what you would be attesting to:"
|
|
131
|
+
puts "─" * 72
|
|
132
|
+
puts text
|
|
133
|
+
puts "─" * 72
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @return [Integer] 1
|
|
137
|
+
def refuse_without_accept
|
|
138
|
+
puts
|
|
139
|
+
puts "REFUSED: nothing changed. If you have read the text above and accept it as this era's"
|
|
140
|
+
puts "frozen source, run again with --accept. The attestation (old digest, new digest, when)"
|
|
141
|
+
puts "goes on the record either way you decide."
|
|
142
|
+
1
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../tools"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Tools
|
|
7
|
+
# Walks a bluebook language change (syntax row, builder, golden) through its lifecycle:
|
|
8
|
+
# `status`, `propose`, `admit`, `deprecate`, `retire` and `rename` a word, and the
|
|
9
|
+
# `argument-*` forms of the same for a keyword's arguments (see `USAGE`).
|
|
10
|
+
#
|
|
11
|
+
# hecks evolve propose <word> --context Aggregate a row enters, proposed
|
|
12
|
+
# hecks evolve admit <word> --context Aggregate proposed -> admitted
|
|
13
|
+
# hecks evolve rename <word> --context X --to new
|
|
14
|
+
#
|
|
15
|
+
# Mutating commands regenerate the golden and run the gates; a failing gate restores every file.
|
|
16
|
+
module EvolveRun
|
|
17
|
+
# The specs a change must keep green.
|
|
18
|
+
GATES = %w[
|
|
19
|
+
spec/syntax_conformance_spec.rb
|
|
20
|
+
spec/syntax_lifecycle_spec.rb
|
|
21
|
+
spec/ir_golden_spec.rb
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
# Words that move a word to a status.
|
|
25
|
+
WORD_STATUS = { "admit" => "admitted", "deprecate" => "deprecated", "retire" => "retired" }.freeze
|
|
26
|
+
|
|
27
|
+
# Words that move a keyword's argument to a status.
|
|
28
|
+
ARGUMENT_STATUS = { "argument-admit" => "admitted", "argument-deprecate" => "deprecated",
|
|
29
|
+
"argument-retire" => "retired" }.freeze
|
|
30
|
+
|
|
31
|
+
USAGE = "usage: hecks evolve status|propose|admit|deprecate|retire <word> --context <Context> " \
|
|
32
|
+
"[--body none|keywords|source|rows] [--inner X] [--opens X] [--fills x]\n " \
|
|
33
|
+
"or: hecks evolve argument-propose|argument-admit|argument-deprecate|argument-retire " \
|
|
34
|
+
"<keyword> --context <Context> [--kind K] [--at N] [--named NAME] [--required true|false] " \
|
|
35
|
+
"[--fills F]"
|
|
36
|
+
|
|
37
|
+
module_function
|
|
38
|
+
|
|
39
|
+
# Runs one lifecycle command.
|
|
40
|
+
#
|
|
41
|
+
# @param argv [Array<String>] the command, its word or keyword, then its flags
|
|
42
|
+
# @param root [String] the checkout whose syntax tables and golden are edited
|
|
43
|
+
# @return [Integer] 0, or 1 when a gate refuses and the files are restored
|
|
44
|
+
# @raise [SystemExit] with the reason when an argument is missing
|
|
45
|
+
def main(argv, root: Tools::ROOT)
|
|
46
|
+
require "hecks/grammar/evolve"
|
|
47
|
+
args = argv.dup
|
|
48
|
+
command = args.shift
|
|
49
|
+
evolve = Hecks::Grammar::Evolve
|
|
50
|
+
ok =
|
|
51
|
+
case command
|
|
52
|
+
when "status" then status(evolve)
|
|
53
|
+
when "propose" then propose(args, evolve, root)
|
|
54
|
+
when *WORD_STATUS.keys then set_status(command, args, evolve, root)
|
|
55
|
+
when "rename" then rename(args, evolve, root)
|
|
56
|
+
when "argument-propose" then propose_argument(args, evolve, root)
|
|
57
|
+
when *ARGUMENT_STATUS.keys then set_argument_status(command, args, evolve, root)
|
|
58
|
+
else abort USAGE
|
|
59
|
+
end
|
|
60
|
+
ok == false ? 1 : 0
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Rewrites spec/golden/ir/Bluebook.json by running its spec with `GOLDEN=rewrite`.
|
|
64
|
+
#
|
|
65
|
+
# @param root [String] the checkout
|
|
66
|
+
# @return [Boolean, nil] whether the spec ran green
|
|
67
|
+
def regenerate!(root)
|
|
68
|
+
system({ "GOLDEN" => "rewrite" },
|
|
69
|
+
"bundle", "exec", "rspec", "spec/ir_golden_spec.rb",
|
|
70
|
+
chdir: root, out: File::NULL, err: File::NULL)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Runs the syntax conformance, syntax lifecycle and golden IR specs.
|
|
74
|
+
#
|
|
75
|
+
# @param root [String] the checkout
|
|
76
|
+
# @return [Boolean, nil] whether they passed
|
|
77
|
+
def gates_pass?(root)
|
|
78
|
+
system("bundle", "exec", "rspec", *GATES, chdir: root)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Runs one grammar edit inside the snapshot/regenerate/gate sequence, restoring every
|
|
82
|
+
# snapshot if the block raises or a gate fails.
|
|
83
|
+
#
|
|
84
|
+
# @param word [String] what the edit is about, for the report
|
|
85
|
+
# @param context [String] the aggregate the word belongs to
|
|
86
|
+
# @param evolve [Module] `Hecks::Grammar::Evolve`
|
|
87
|
+
# @param root [String] the checkout
|
|
88
|
+
# @return [Boolean] true if the block ran and the gates held
|
|
89
|
+
def guarded(word, context, evolve, root, &)
|
|
90
|
+
paths = evolve.syntax_paths + [File.join(root, "spec/golden/ir/Bluebook.json")]
|
|
91
|
+
snapshots = paths.to_h { |path| [path, File.read(path)] }
|
|
92
|
+
evolve.restore_on_raise(paths, &)
|
|
93
|
+
regenerate!(root)
|
|
94
|
+
if gates_pass?(root)
|
|
95
|
+
puts "\n#{context}.#{word} — the gates hold. Regenerated projections and the golden are in the tree."
|
|
96
|
+
true
|
|
97
|
+
else
|
|
98
|
+
snapshots.each { |path, content| File.write(path, content) }
|
|
99
|
+
puts "\nRESTORED — the gates refused, and the failures above are the checklist. " \
|
|
100
|
+
"Nothing was changed."
|
|
101
|
+
false
|
|
102
|
+
end
|
|
103
|
+
rescue StandardError => e
|
|
104
|
+
# `restore_on_raise` has already restored the files; this only reports.
|
|
105
|
+
puts "\nRESTORED — #{e.message} Nothing was changed."
|
|
106
|
+
false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @return [true]
|
|
110
|
+
def status(evolve) # rubocop:disable Naming/PredicateMethod
|
|
111
|
+
rows = evolve.keyword_rows
|
|
112
|
+
moving = rows.reject { |row| row[:status] == "admitted" }
|
|
113
|
+
renamed = rows.reject { |row| row[:was].to_s.empty? }
|
|
114
|
+
puts "#{rows.size} keyword rows; #{moving.size} not simply admitted; #{renamed.size} renamed"
|
|
115
|
+
moving.each { |row| puts " #{row[:status].ljust(10)} #{row[:context]}.#{row[:word]}" }
|
|
116
|
+
renamed.each { |row| puts " renamed #{row[:context]}.#{row[:word]} (was #{row[:was]})" }
|
|
117
|
+
true
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @return [Boolean] whether the gates held
|
|
121
|
+
def propose(args, evolve, root)
|
|
122
|
+
word = args.shift or abort "propose what word?"
|
|
123
|
+
context = evolve.option(args, "context") or abort "--context is required — a word is a word somewhere"
|
|
124
|
+
ok = guarded(word, context, evolve, root) do
|
|
125
|
+
evolve.propose(word: word, context: context,
|
|
126
|
+
body: evolve.option(args, "body", "none"), inner: evolve.option(args, "inner", ""),
|
|
127
|
+
opens: evolve.option(args, "opens", ""), fills: evolve.option(args, "fills", ""))
|
|
128
|
+
end
|
|
129
|
+
if ok
|
|
130
|
+
puts "Proposed. It reaches no projection until admitted. Before `hecks evolve admit`:"
|
|
131
|
+
puts " 1. teach the #{context} builder the word (and its spec/dsl_spec example)"
|
|
132
|
+
end
|
|
133
|
+
ok
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @return [Boolean] whether the gates held
|
|
137
|
+
def set_status(command, args, evolve, root)
|
|
138
|
+
word = args.shift or abort "#{command} what word?"
|
|
139
|
+
context = evolve.option(args, "context") or abort "--context is required"
|
|
140
|
+
guarded(word, context, evolve, root) do
|
|
141
|
+
evolve.set_status(word: word, context: context, to: WORD_STATUS.fetch(command))
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# @return [Boolean] whether the gates held
|
|
146
|
+
def rename(args, evolve, root)
|
|
147
|
+
word = args.shift or abort "rename what word?"
|
|
148
|
+
context = evolve.option(args, "context") or abort "--context is required"
|
|
149
|
+
to = evolve.option(args, "to") or abort "--to is required — a rename goes somewhere"
|
|
150
|
+
ok = guarded(word, context, evolve, root) { evolve.rename(word: word, context: context, to: to) }
|
|
151
|
+
if ok
|
|
152
|
+
puts "Renamed. The old spelling keeps parsing — that is the point. Before this holds:"
|
|
153
|
+
puts " 1. alias the new word to the old in the #{context} builder (alias_method :#{to}, :#{word})"
|
|
154
|
+
puts " 2. add the identical-IR example to spec/dsl_spec.rb"
|
|
155
|
+
end
|
|
156
|
+
ok
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# @return [Boolean] whether the gates held
|
|
160
|
+
def propose_argument(args, evolve, root)
|
|
161
|
+
keyword = args.shift or abort "argument-propose which keyword's argument?"
|
|
162
|
+
context = evolve.option(args, "context") or abort "--context is required"
|
|
163
|
+
kind = evolve.option(args, "kind") or abort "--kind is required — text|symbol|number|flag|literal|constant|pairs|list"
|
|
164
|
+
ok = guarded("#{keyword} argument", context, evolve, root) do
|
|
165
|
+
evolve.propose_argument(keyword: keyword, context: context, kind: kind,
|
|
166
|
+
required: evolve.option(args, "required", "false"),
|
|
167
|
+
at: evolve.option(args, "at", ""), named: evolve.option(args, "named", ""),
|
|
168
|
+
fills: evolve.option(args, "fills", ""),
|
|
169
|
+
pairs_shape: evolve.option(args, "pairs-shape"))
|
|
170
|
+
end
|
|
171
|
+
if ok
|
|
172
|
+
puts "Proposed. It reaches no projection until admitted. Before `hecks evolve argument-admit`:"
|
|
173
|
+
puts " 1. teach the #{context} builder's #{keyword} method the argument"
|
|
174
|
+
end
|
|
175
|
+
ok
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# @return [Boolean] whether the gates held
|
|
179
|
+
def set_argument_status(command, args, evolve, root)
|
|
180
|
+
keyword = args.shift or abort "#{command} which keyword's argument?"
|
|
181
|
+
context = evolve.option(args, "context") or abort "--context is required"
|
|
182
|
+
guarded("#{keyword} argument", context, evolve, root) do
|
|
183
|
+
evolve.set_argument_status(keyword: keyword, context: context, to: ARGUMENT_STATUS.fetch(command),
|
|
184
|
+
at: evolve.option(args, "at", ""), named: evolve.option(args, "named", ""))
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|