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,42 @@
|
|
|
1
|
+
# Where the Hecks domain keeps its journal: every command's events, one entry per aggregate.
|
|
2
|
+
#
|
|
3
|
+
# **PostgresEra** is the default, for real runs: a client's `hecks` and a maintainer's on main
|
|
4
|
+
# or in the merge queue. The journal then survives the process, and `hecks stores` and
|
|
5
|
+
# `hecks history` read it back. `default_adapter` binds every aggregate of the chapter (and of
|
|
6
|
+
# the attached Governance chapter, see governance.world) in one line, which is what lets the
|
|
7
|
+
# environments/memory.world overlay swap the whole domain to Memory.
|
|
8
|
+
#
|
|
9
|
+
# **Memory** is for anything that must not touch a database: specs and pull-request runs.
|
|
10
|
+
# Select it with `HECKS_ENVIRONMENT=memory` (Hecks.boot reads the variable) or
|
|
11
|
+
# `Hecks.boot(path, environment: "memory")`. Queries and refused or dry-run requests record
|
|
12
|
+
# nothing worth keeping, so they behave the same on either.
|
|
13
|
+
#
|
|
14
|
+
# The database is `HECKS_DATABASE` when set, so a client points the domain at their own
|
|
15
|
+
# Postgres (a `postgres://` URL, or a bare database name); otherwise a local database named for
|
|
16
|
+
# the domain. It connects as the ordinary role `hecks`, never a superuser: the era write-fence
|
|
17
|
+
# (row-level security) is bypassed by one, so boot refuses it. Create the role once with
|
|
18
|
+
# `hecks quality_control create_ledger_role hecks` and the database with `createdb -O hecks hecks`.
|
|
19
|
+
#
|
|
20
|
+
# PostgresEra versions the storage shape. Once a database holds an era, a later change to this
|
|
21
|
+
# domain's shape needs a translation edge, kept in `translations/` beside the bluebook; an
|
|
22
|
+
# edge is written only when such a change is made.
|
|
23
|
+
#
|
|
24
|
+
# **launcher** switches on the opt-in parts of the generated `hecks` launcher (see
|
|
25
|
+
# `Doors::LauncherOptions`): `run_keys` mints a `run` key for a creating command given none,
|
|
26
|
+
# `failure_states` are the lifecycle states `--wait` reports as exit 1 (every failure state the
|
|
27
|
+
# chapter's lifecycles declare), `names` gives a command the launcher name clients type,
|
|
28
|
+
# `executable` is where `hecks project_cli` writes this chapter's launcher (the gem's
|
|
29
|
+
# `exe/hecks`), and `legacy` names the verbs that launcher hands to `Hecks::CLI` in the
|
|
30
|
+
# positional forms ADR 0066 shipped.
|
|
31
|
+
Hecks.world "Hecks" do
|
|
32
|
+
realm "Hecks"
|
|
33
|
+
default_adapter "PostgresEra"
|
|
34
|
+
default_database ENV.fetch("HECKS_DATABASE", "postgres://hecks@localhost/hecks")
|
|
35
|
+
launcher "Launcher", run_keys: true,
|
|
36
|
+
failure_states: %w[flagged failed drifted unreachable refused faulted halted stopped
|
|
37
|
+
abandoned red needs_fix],
|
|
38
|
+
names: { "mcp" => "serve_mcp", "console" => "open_console" },
|
|
39
|
+
executable: "exe/hecks",
|
|
40
|
+
legacy: %w[run docs narrate ir stores model_check smoke_test
|
|
41
|
+
project_diagrams project_cli mcp]
|
|
42
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "projection_files"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
# The capability enums the hand-written Rust kernel is matched against, and the check that every
|
|
7
|
+
# capability the Ruby grammar admits has its hand-written file.
|
|
8
|
+
#
|
|
9
|
+
# The `pub mod` roster and the enum of `rust/src/kernel/attribute_shapes/mod.rs` and
|
|
10
|
+
# `rust/src/kernel/expression_operators/mod.rs` are generated; the `<name>.rs` files beside them
|
|
11
|
+
# are hand-written, so a grammar change can leave a `pub mod` naming a file nobody has written.
|
|
12
|
+
# Ground truth is `Coercion::SHAPES` and `Grammar.admitted_operators`, never a copied list.
|
|
13
|
+
# Query comparators are one flat hand-maintained file with no per-variant files to check.
|
|
14
|
+
module KernelCapabilities
|
|
15
|
+
# One capability a hand-written kernel file should exist for.
|
|
16
|
+
#
|
|
17
|
+
# @!attribute [r] name
|
|
18
|
+
# @return [String] the capability's name
|
|
19
|
+
# @!attribute [r] path
|
|
20
|
+
# @return [String] where its file conventionally stands
|
|
21
|
+
# @!attribute [r] present
|
|
22
|
+
# @return [Boolean] whether the file exists
|
|
23
|
+
# @!attribute [r] source
|
|
24
|
+
# @return [String] where the capability is declared
|
|
25
|
+
Row = Struct.new(:name, :path, :present, :source)
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# Renders both capability modules without writing them.
|
|
30
|
+
#
|
|
31
|
+
# @param root [String] the checkout
|
|
32
|
+
# @return [ProjectionFiles::Result] each `mod.rs`, and nothing stale
|
|
33
|
+
def build(root: ProjectionFiles::ROOT)
|
|
34
|
+
require "hecks"
|
|
35
|
+
require "hecks/grammar"
|
|
36
|
+
require "hecks/runtime/value/coercion"
|
|
37
|
+
kernel = File.join(root, "rust/src/kernel")
|
|
38
|
+
content = {
|
|
39
|
+
File.join(kernel, "attribute_shapes/mod.rs") => shapes_module,
|
|
40
|
+
File.join(kernel, "expression_operators/mod.rs") => operators_module
|
|
41
|
+
}
|
|
42
|
+
ProjectionFiles::Result.new(content, [])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Writes the capability modules.
|
|
46
|
+
#
|
|
47
|
+
# @param root [String] the checkout
|
|
48
|
+
# @return [Array<String>] one `wrote <path>` line for each file
|
|
49
|
+
def write(root: ProjectionFiles::ROOT)
|
|
50
|
+
build(root: root).content.map { |path, text| ProjectionFiles.write_atomically(path, text) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Checks every capability the live grammar admits against the kernel's files.
|
|
54
|
+
#
|
|
55
|
+
# @param root [String] the checkout
|
|
56
|
+
# @return [Array<Row>] one row for each attribute shape and expression-operator category
|
|
57
|
+
def coverage(root: ProjectionFiles::ROOT)
|
|
58
|
+
require "hecks"
|
|
59
|
+
require "hecks/grammar"
|
|
60
|
+
require "hecks/runtime/value/coercion"
|
|
61
|
+
check(root, "attribute_shapes", Hecks::Runtime::Value::Coercion::SHAPES, "Coercion::SHAPES") +
|
|
62
|
+
check(root, "expression_operators", operator_categories,
|
|
63
|
+
"Grammar.admitted_operators's own category field")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The coverage check as text: one line for each capability, then a verdict.
|
|
67
|
+
#
|
|
68
|
+
# @param root [String] the checkout
|
|
69
|
+
# @return [Array(String, String, Boolean)] the lines of the check, the closing verdict (the
|
|
70
|
+
# complaint, when a file is missing), and whether every file is present
|
|
71
|
+
def coverage_report(root: ProjectionFiles::ROOT)
|
|
72
|
+
rows = coverage(root: root)
|
|
73
|
+
prefix = "#{root}/"
|
|
74
|
+
lines = rows.map do |row|
|
|
75
|
+
"#{row.present ? 'OK ' : 'MISS'} #{row.path.delete_prefix(prefix)} (#{row.source}: #{row.name.inspect})"
|
|
76
|
+
end
|
|
77
|
+
missing = rows.reject(&:present)
|
|
78
|
+
return [lines.join("\n"), coverage_verdict(rows.size), true] if missing.empty?
|
|
79
|
+
|
|
80
|
+
gaps = missing.map { |row| " #{row.path.delete_prefix(prefix)}" }
|
|
81
|
+
head = "#{missing.size} capability file(s) missing — the grammar admits these but no " \
|
|
82
|
+
"hand-written Rust interpretation exists for them yet:"
|
|
83
|
+
[lines.join("\n"), [head, *gaps].join("\n"), false]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @param count [Integer] how many capabilities there are
|
|
87
|
+
# @return [String] the clean verdict
|
|
88
|
+
def coverage_verdict(count)
|
|
89
|
+
"#{count}/#{count} kernel capability files present — every attribute shape and " \
|
|
90
|
+
"expression-operator category the live Ruby grammar admits has a rust/src/kernel/ file " \
|
|
91
|
+
"at its conventional path."
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @param name [String, Symbol] a snake_case capability name
|
|
95
|
+
# @return [String] the PascalCase Rust variant
|
|
96
|
+
def pascal(name)
|
|
97
|
+
name.to_s.split("_").map { |part| part[0].upcase + part[1..] }.join
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# `category` in first-appearance order over the admission ledger, never alphabetized, so a
|
|
101
|
+
# re-run does not reshuffle variants.
|
|
102
|
+
#
|
|
103
|
+
# @return [Array<String>] the expression-operator categories
|
|
104
|
+
def operator_categories
|
|
105
|
+
Hecks::Grammar.admitted_operators.map { |op| op[:category] }.uniq
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @param root [String] the checkout
|
|
109
|
+
# @param category_dir [String] the directory below `rust/src/kernel/`
|
|
110
|
+
# @param names [Array<String>] the capabilities to look for
|
|
111
|
+
# @param source [String] where they are declared
|
|
112
|
+
# @return [Array<Row>] a row for each
|
|
113
|
+
def check(root, category_dir, names, source)
|
|
114
|
+
names.map do |name|
|
|
115
|
+
path = File.join(root, "rust/src/kernel", category_dir, "#{name}.rs")
|
|
116
|
+
Row.new(name, path, File.file?(path), source)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @return [String] the whole `attribute_shapes/mod.rs`
|
|
121
|
+
def shapes_module
|
|
122
|
+
header = <<~HEADER.strip
|
|
123
|
+
// Ground truth: Hecks::Runtime::Value::Coercion::SHAPES
|
|
124
|
+
// (lib/hecks/runtime/value/coercion.rb) — the four branches
|
|
125
|
+
// `for_attribute` itself takes, read directly rather than
|
|
126
|
+
// re-derived here.
|
|
127
|
+
HEADER
|
|
128
|
+
render(header: header, enum_name: "AttributeShape", names: Hecks::Runtime::Value::Coercion::SHAPES,
|
|
129
|
+
doc_line: "Coercion::SHAPES")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# @return [String] the whole `expression_operators/mod.rs`
|
|
133
|
+
def operators_module
|
|
134
|
+
header = <<~HEADER.strip
|
|
135
|
+
// Ground truth: Hecks::Grammar.admitted_operators (lib/hecks/
|
|
136
|
+
// grammar.rb), the SAME live-booted call hecks project_expression_tables
|
|
137
|
+
// uses — grouped by the `category` field Evaluator::PROJECTION already
|
|
138
|
+
// partitions comparison operators by (evaluator.rb).
|
|
139
|
+
HEADER
|
|
140
|
+
render(header: header, enum_name: "OperatorCategory", names: operator_categories,
|
|
141
|
+
doc_line: "Grammar.admitted_operators's own `category` field")
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Renders one capability module: `pub mod` lines, the enum, and its `ALL`.
|
|
145
|
+
#
|
|
146
|
+
# @param header [String] the ground-truth comment
|
|
147
|
+
# @param enum_name [String] `AttributeShape` or `OperatorCategory`
|
|
148
|
+
# @param names [Array<String>] the capabilities, in declaration order
|
|
149
|
+
# @param doc_line [String] where the capabilities are declared
|
|
150
|
+
# @return [String] the Rust source
|
|
151
|
+
def render(header:, enum_name:, names:, doc_line:)
|
|
152
|
+
shapes = enum_name == "AttributeShape"
|
|
153
|
+
variants = names.map { |name| " #{pascal(name)}," }.join("\n")
|
|
154
|
+
mods = names.map { |name| "pub mod #{name};" }.join("\n")
|
|
155
|
+
arms = names.map { |name| " #{enum_name}::#{pascal(name)} => #{name.to_s.inspect}," }.join("\n")
|
|
156
|
+
all = names.map { |name| "#{enum_name}::#{pascal(name)}" }.join(", ")
|
|
157
|
+
|
|
158
|
+
<<~RUST
|
|
159
|
+
// GENERATED by hecks project_kernel_capabilities from #{doc_line}.
|
|
160
|
+
// Do not hand-edit — re-run hecks project_kernel_capabilities instead.
|
|
161
|
+
//
|
|
162
|
+
#{header}
|
|
163
|
+
|
|
164
|
+
#{mods}
|
|
165
|
+
|
|
166
|
+
/// One variant per real #{shapes ? 'attribute shape' : 'expression-operator category'} the Ruby
|
|
167
|
+
/// grammar admits, in the order #{doc_line} declares them. Every match
|
|
168
|
+
/// over this enum in the kernel (rust/src/kernel/expr.rs) is written
|
|
169
|
+
/// WITHOUT a wildcard `_ =>` arm — see expr.rs's own header for why:
|
|
170
|
+
/// a wildcard here would let a newly-admitted capability compile
|
|
171
|
+
/// silently into a router that never calls the new file this same
|
|
172
|
+
/// regeneration adds a `pub mod` line for above.
|
|
173
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
174
|
+
pub enum #{enum_name} {
|
|
175
|
+
#{variants}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
impl #{enum_name} {
|
|
179
|
+
/// The `rust/src/kernel/#{shapes ? 'attribute_shapes' : 'expression_operators'}/<name>.rs` file this
|
|
180
|
+
/// variant names — `hecks measure_kernel_coverage`'s own existence
|
|
181
|
+
/// check reads this, so the file-name spelling here is the ONE
|
|
182
|
+
/// place that ever needs to change if a name is renamed.
|
|
183
|
+
pub fn module_name(&self) -> &'static str {
|
|
184
|
+
match self {
|
|
185
|
+
#{arms}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
pub const ALL: &'static [#{enum_name}] = &[#{all}];
|
|
190
|
+
}
|
|
191
|
+
RUST
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -33,6 +33,7 @@ Hecks.bluebook "Bluebook", version: "1" do
|
|
|
33
33
|
attribute :version, Version
|
|
34
34
|
# A rename is a declared fact. Absent is not empty.
|
|
35
35
|
attribute :formerly_known_as, FormerlyKnownAs
|
|
36
|
+
attribute :namespace, ChapterNamespace
|
|
36
37
|
attribute :normalisations, list_of(NormalisationRule)
|
|
37
38
|
# Core contexts a sub-language chapter contributes Syntax rows for (ADR 0026).
|
|
38
39
|
# Absent is not empty: most chapters attach to nothing.
|
|
@@ -92,6 +93,12 @@ Hecks.bluebook "Bluebook", version: "1" do
|
|
|
92
93
|
invariant("a formerly_known_as says something") { !value.to_s.empty? }
|
|
93
94
|
end
|
|
94
95
|
|
|
96
|
+
# The Ruby module a chapter's constants install under instead of its own name.
|
|
97
|
+
value_object "ChapterNamespace" do
|
|
98
|
+
attribute :value, String
|
|
99
|
+
invariant("a namespace is a constant path") { value.to_s.match?(/\A[A-Z][A-Za-z0-9_]*(::[A-Z][A-Za-z0-9_]*)*\z/) }
|
|
100
|
+
end
|
|
101
|
+
|
|
95
102
|
value_object "AttachesToContext" do
|
|
96
103
|
attribute :value, String
|
|
97
104
|
invariant("an attachment names a context") { !value.to_s.empty? }
|
|
@@ -106,12 +113,14 @@ Hecks.bluebook "Bluebook", version: "1" do
|
|
|
106
113
|
attribute :classification, Classification, optional: true
|
|
107
114
|
attribute :version, Version, optional: true
|
|
108
115
|
attribute :formerly_known_as, FormerlyKnownAs, optional: true
|
|
116
|
+
attribute :namespace, ChapterNamespace, optional: true
|
|
109
117
|
|
|
110
118
|
sets :name
|
|
111
119
|
sets :vision
|
|
112
120
|
sets :classification
|
|
113
121
|
sets :version
|
|
114
122
|
sets :formerly_known_as
|
|
123
|
+
sets :namespace
|
|
115
124
|
|
|
116
125
|
emits ChapterDeclared
|
|
117
126
|
end
|
|
@@ -185,6 +194,7 @@ Hecks.bluebook "Bluebook", version: "1" do
|
|
|
185
194
|
member word: "bluebook", context: "File", body: "keywords", inner: "Bluebook", opens: "Bluebook", fills: ""
|
|
186
195
|
member word: "vision", context: "Bluebook", body: "none", inner: "", opens: "", fills: "vision"
|
|
187
196
|
member word: "formerly_known_as", context: "Bluebook", body: "none", inner: "", opens: "", fills: "formerly_known_as"
|
|
197
|
+
member word: "namespace", context: "Bluebook", body: "none", inner: "", opens: "", fills: "namespace"
|
|
188
198
|
member word: "attaches_to", context: "Bluebook", body: "none", inner: "", opens: "", fills: "attaches_to", calls: "attaches_to_impl"
|
|
189
199
|
member word: "provides", context: "Bluebook", body: "none", inner: "", opens: "", fills: "provides", calls: "provides_impl"
|
|
190
200
|
member word: "core", context: "Bluebook", body: "none", inner: "", opens: "", fills: "classification"
|
|
@@ -218,6 +228,7 @@ Hecks.bluebook "Bluebook", version: "1" do
|
|
|
218
228
|
member keyword: "bluebook", context: "File", at: "", named: "version", kind: "text", required: "false", fills: "version"
|
|
219
229
|
member keyword: "vision", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "vision", coerce: "false"
|
|
220
230
|
member keyword: "formerly_known_as", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "formerly_known_as"
|
|
231
|
+
member keyword: "namespace", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "namespace"
|
|
221
232
|
member keyword: "attaches_to", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "attaches_to", variadic: "true"
|
|
222
233
|
member keyword: "provides", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "provides"
|
|
223
234
|
member keyword: "provides", context: "Bluebook", at: "", named: "assignments", kind: "text", required: "false", fills: "provides"
|
|
@@ -15,6 +15,9 @@ Hecks.bluebook "Bluebook" do
|
|
|
15
15
|
attribute :order_field, QueryText
|
|
16
16
|
attribute :order_way, QueryText
|
|
17
17
|
attribute :limit, QueryText
|
|
18
|
+
# The value object that shapes an answer given from outside the domain, spelled as written:
|
|
19
|
+
# `Name` or `list_of(Name)`. Empty when the answer is the aggregate's own row.
|
|
20
|
+
attribute :returns, QueryText
|
|
18
21
|
attribute :wheres, list_of(Filter)
|
|
19
22
|
attribute :attributes, list_of(AskArgument)
|
|
20
23
|
# Every other option a query carries, as an open map: rows of option name, key within it, and
|
|
@@ -88,6 +91,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
88
91
|
attribute :order_field, QueryText, optional: true
|
|
89
92
|
attribute :order_way, QueryText, optional: true
|
|
90
93
|
attribute :limit, QueryText, optional: true
|
|
94
|
+
attribute :returns, QueryText, optional: true
|
|
91
95
|
|
|
92
96
|
attribute :position, Position, optional: true
|
|
93
97
|
sets :aggregate
|
|
@@ -97,6 +101,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
97
101
|
sets :order_field
|
|
98
102
|
sets :order_way
|
|
99
103
|
sets :limit
|
|
104
|
+
sets :returns
|
|
100
105
|
sets :position
|
|
101
106
|
emits AskDeclared
|
|
102
107
|
end
|
|
@@ -173,6 +178,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
173
178
|
member word: "order_by", context: "Query", body: "none", inner: "", opens: "", fills: "order_field", calls: "order_by_impl"
|
|
174
179
|
member word: "authorize", context: "Query", body: "none", inner: "", opens: "", fills: "options", calls: "authorize_impl"
|
|
175
180
|
member word: "inspect_query", context: "Query", body: "none", inner: "", opens: "", fills: "options"
|
|
181
|
+
member word: "returns", context: "Query", body: "none", inner: "", opens: "", fills: "returns"
|
|
176
182
|
|
|
177
183
|
end
|
|
178
184
|
|
|
@@ -210,6 +216,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
210
216
|
member keyword: "authorize", context: "Query", at: "1", named: "", kind: "symbol", required: "true", fills: "policy"
|
|
211
217
|
member keyword: "authorize", context: "Query", at: "", named: "tenant", kind: "symbol", required: "false", fills: "tenant"
|
|
212
218
|
member keyword: "inspect_query", context: "Query", at: "1", named: "", kind: "symbol", required: "false", fills: "mode"
|
|
219
|
+
member keyword: "returns", context: "Query", at: "1", named: "", kind: "constant", required: "true", fills: "type"
|
|
213
220
|
|
|
214
221
|
end
|
|
215
222
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Hecks.bluebook "Bluebook" do
|
|
2
2
|
aggregate "Vocabulary" do
|
|
3
3
|
# Closed sets the language admits, projected into matching Ruby and Rust
|
|
4
|
-
# tables (
|
|
4
|
+
# tables (hecks project_vocabulary, hecks project_rust_vocabulary) so both runtimes agree.
|
|
5
5
|
description "The closed sets the language admits — the whole of what any runtime may accept, declared once."
|
|
6
6
|
|
|
7
7
|
# Named only by itself; a vocabulary hangs under nothing else.
|
|
@@ -585,7 +585,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
585
585
|
# (case-insensitively) to guess an HTML input type or textarea kind, when
|
|
586
586
|
# nothing more specific already answered (Hecks::Forms::FieldShape's
|
|
587
587
|
# EMAIL_HINT/URL_HINT/TEL_HINT/TEXTAREA_HINT). `pattern` is the regex
|
|
588
|
-
# source, no delimiters or flags.
|
|
588
|
+
# source, no delimiters or flags. hecks project_field_hints writes the Rust
|
|
589
589
|
# host's copy from these rows, so neither side is typed by hand.
|
|
590
590
|
#
|
|
591
591
|
# `resolves_to` names which Field attribute a match sets: html_type for
|
|
@@ -604,7 +604,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
604
604
|
|
|
605
605
|
# Rust keywords (strict + reserved) a generated identifier must not
|
|
606
606
|
# collide with. RustProjection::Projector::RUST_KEYWORDS reads this;
|
|
607
|
-
#
|
|
607
|
+
# hecks project_reserved_names projects it into
|
|
608
608
|
# rust/codegen/src/reserved_names.rs, so Ruby and Rust escape or refuse
|
|
609
609
|
# the same words from one declaration instead of two hand-typed copies.
|
|
610
610
|
value_object "RustReservedWord" do
|
|
@@ -621,7 +621,7 @@ Hecks.bluebook "Bluebook" do
|
|
|
621
621
|
# outside `[features]` (`[package]`, `[lib]`, `[[bin]]`) plus `default`,
|
|
622
622
|
# which Cargo reserves for the auto-enabled feature set. Read by
|
|
623
623
|
# RustProjection::Projector::CARGO_RESERVED_DOMAIN_NAMES and projected by
|
|
624
|
-
#
|
|
624
|
+
# hecks project_reserved_names, same as RustReservedWord above.
|
|
625
625
|
value_object "CargoReservedName" do
|
|
626
626
|
attribute :name, String,
|
|
627
627
|
one_of: ["name", "version", "edition", "path", "authors", "license", "description", "default",
|
|
@@ -7,6 +7,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
7
7
|
attribute :verb, PortVerb, optional: true
|
|
8
8
|
attribute :signal, PortSignal, optional: true
|
|
9
9
|
attribute :answers, list_of(PortAnswer)
|
|
10
|
+
attribute :answered_queries, list_of(QueryBinding)
|
|
10
11
|
|
|
11
12
|
value_object "PortName" do
|
|
12
13
|
attribute :value, String
|
|
@@ -29,6 +30,13 @@ Hecks.bluebook "Hecksagon" do
|
|
|
29
30
|
invariant("an answer names a real method") { !value.to_s.empty? }
|
|
30
31
|
end
|
|
31
32
|
|
|
33
|
+
# A query this port's adapter answers. The shape of the answer is the query's own `returns`,
|
|
34
|
+
# declared in the bluebook; the hecksagon only says who answers.
|
|
35
|
+
value_object "QueryBinding" do
|
|
36
|
+
attribute :name, String
|
|
37
|
+
invariant("a bound query is named") { !name.to_s.empty? }
|
|
38
|
+
end
|
|
39
|
+
|
|
32
40
|
# Keyword rows for DomainPort; SyntaxBoot discovers every aggregate-local seed table.
|
|
33
41
|
value_object "KeywordSeed" do
|
|
34
42
|
attribute :word, String
|
|
@@ -48,6 +56,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
48
56
|
member word: "verb", context: "DomainPort", body: "none", inner: "", opens: "", fills: "verb"
|
|
49
57
|
member word: "signal", context: "DomainPort", body: "none", inner: "", opens: "", fills: "signal"
|
|
50
58
|
member word: "answers", context: "DomainPort", body: "none", inner: "", opens: "", fills: "answers"
|
|
59
|
+
member word: "answers_query", context: "DomainPort", body: "none", inner: "", opens: "", fills: "answered_queries", calls: "answers_query_impl"
|
|
51
60
|
|
|
52
61
|
end
|
|
53
62
|
|
|
@@ -74,6 +83,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
74
83
|
member keyword: "verb", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "verb"
|
|
75
84
|
member keyword: "signal", context: "DomainPort", at: "1", named: "", kind: "symbol", required: "true", fills: "signal"
|
|
76
85
|
member keyword: "answers", context: "DomainPort", at: "1", named: "", kind: "symbol", required: "true", fills: "answers"
|
|
86
|
+
member keyword: "answers_query", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
77
87
|
|
|
78
88
|
# The receiving aggregate is named on the opening word (`to:`), not by `reference_to` inside.
|
|
79
89
|
member keyword: "operation", context: "DomainPort", at: "", named: "to", kind: "constant", required: "false", fills: "to"
|
|
@@ -7,6 +7,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
7
7
|
attribute :subscriptions, list_of(Subscription)
|
|
8
8
|
attribute :framework_members, list_of(FrameworkMember)
|
|
9
9
|
attribute :vendored_bluebooks, list_of(VendoredBluebook)
|
|
10
|
+
attribute :attached_chapters, list_of(AttachedChapter)
|
|
10
11
|
|
|
11
12
|
value_object "HecksagonName" do
|
|
12
13
|
attribute :value, String
|
|
@@ -30,6 +31,12 @@ Hecks.bluebook "Hecksagon" do
|
|
|
30
31
|
invariant("a vendored bluebook is named") { !value.to_s.empty? }
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
# A chapter the gem carries (the language, Expression, Tenancy, Deploy) this hecksagon attaches.
|
|
35
|
+
value_object "AttachedChapter" do
|
|
36
|
+
attribute :value, String
|
|
37
|
+
invariant("an attached chapter is named") { !value.to_s.empty? }
|
|
38
|
+
end
|
|
39
|
+
|
|
33
40
|
command "Declare" do
|
|
34
41
|
role "Deployment"
|
|
35
42
|
goal "Open a hecksagon for a domain"
|
|
@@ -74,6 +81,17 @@ Hecks.bluebook "Hecksagon" do
|
|
|
74
81
|
emits "VendoredBluebookAttached"
|
|
75
82
|
end
|
|
76
83
|
|
|
84
|
+
command "Attaches" do
|
|
85
|
+
role "Deployment"
|
|
86
|
+
goal "Attach a chapter the gem carries to this hecksagon, by name"
|
|
87
|
+
|
|
88
|
+
attribute :chapter, AttachedChapter
|
|
89
|
+
|
|
90
|
+
sets :attached_chapters, append: { value: :chapter }
|
|
91
|
+
|
|
92
|
+
emits "ChapterAttached"
|
|
93
|
+
end
|
|
94
|
+
|
|
77
95
|
# Keyword rows for File and Hecksagon; SyntaxBoot discovers every aggregate-local seed table.
|
|
78
96
|
value_object "KeywordSeed" do
|
|
79
97
|
attribute :word, String
|
|
@@ -91,6 +109,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
91
109
|
member word: "subscribe", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "subscriptions"
|
|
92
110
|
member word: "uses_framework", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "framework_members"
|
|
93
111
|
member word: "uses_embryonaut_bluebook", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "vendored_bluebooks"
|
|
112
|
+
member word: "attaches", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attached_chapters"
|
|
94
113
|
member word: "port", context: "Hecksagon", body: "keywords", inner: "DomainPort", opens: "DomainPort", fills: "", calls: "port_impl"
|
|
95
114
|
# A cross-domain reaction wired here rather than in the bluebook; reuses the Policy context.
|
|
96
115
|
# No `calls:` — HecksagonBuilder#translates is an ordinary method, found before `word_gate`.
|
|
@@ -121,6 +140,7 @@ Hecks.bluebook "Hecksagon" do
|
|
|
121
140
|
member keyword: "subscribe", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "subscriptions"
|
|
122
141
|
member keyword: "uses_framework", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "framework_members"
|
|
123
142
|
member keyword: "uses_embryonaut_bluebook", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "vendored_bluebooks"
|
|
143
|
+
member keyword: "attaches", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attached_chapters"
|
|
124
144
|
member keyword: "port", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
125
145
|
member keyword: "translates", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
126
146
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
require "socket"
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
|
-
# Startup gate for the stdio MCP servers
|
|
5
|
-
# unknown `HECKS_MCP_*` variables. It is not authentication (ADR 0062).
|
|
4
|
+
# Startup gate for the stdio MCP servers `hecks mcp` runs: refuses network sockets, extra
|
|
5
|
+
# flags and unknown `HECKS_MCP_*` variables. It is not authentication (ADR 0062).
|
|
6
6
|
module McpStdioGuard
|
|
7
7
|
ACCEPTED_ARGS = %w[--stdio].freeze
|
|
8
8
|
ENV_PREFIX = "HECKS_MCP_".freeze
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
require "open3"
|
|
6
|
+
require "tmpdir"
|
|
7
|
+
|
|
8
|
+
module Hecks
|
|
9
|
+
module PersistenceLegacyFixture
|
|
10
|
+
# Regenerates the persistence legacy fixtures by writing the seed records through the real
|
|
11
|
+
# adapters: Heki, SQLite, D1, Postgres and PostgresEra. It needs a reachable Postgres (which
|
|
12
|
+
# scratch databases are made in) and the `sqlite3` program (which dumps the SQLite database).
|
|
13
|
+
#
|
|
14
|
+
# The fixtures are the baseline later adapters are compared with, so a caller confirms before
|
|
15
|
+
# this is run, and it is not re-run once adapters write through the state codec: it would
|
|
16
|
+
# overwrite the baseline.
|
|
17
|
+
class Regenerate
|
|
18
|
+
# The scratch database each Postgres-backed store is written to.
|
|
19
|
+
SCRATCH = {
|
|
20
|
+
postgres: "hecks_persistence_legacy_postgres",
|
|
21
|
+
postgres_era: "hecks_persistence_legacy_postgres_era"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
# Raised when a fixture cannot be written.
|
|
25
|
+
class Failure < StandardError; end
|
|
26
|
+
|
|
27
|
+
# Rewrites every fixture set.
|
|
28
|
+
#
|
|
29
|
+
# @param dir [String] where the fixtures stand
|
|
30
|
+
# @return [String] `wrote <dir>`
|
|
31
|
+
# @raise [Failure] when the `sqlite3` dump fails
|
|
32
|
+
def self.call(dir: PersistenceLegacyFixture::DIR)
|
|
33
|
+
new(dir).call
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param dir [String] where the fixtures stand
|
|
37
|
+
def initialize(dir)
|
|
38
|
+
@dir = dir
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [String] `wrote <dir>`
|
|
42
|
+
def call
|
|
43
|
+
require "hecks/ports/persistence/plugins/era"
|
|
44
|
+
require "pg"
|
|
45
|
+
instances = PersistenceLegacyFixture.instances
|
|
46
|
+
write_heki(instances)
|
|
47
|
+
write_sqlite(instances)
|
|
48
|
+
write_d1(instances)
|
|
49
|
+
with_scratch_databases do
|
|
50
|
+
write_postgres(instances)
|
|
51
|
+
write_postgres_era(instances)
|
|
52
|
+
end
|
|
53
|
+
"wrote #{@dir}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def reset_dir(name)
|
|
59
|
+
dir = File.join(@dir, name)
|
|
60
|
+
FileUtils.rm_rf(dir)
|
|
61
|
+
FileUtils.mkdir_p(dir)
|
|
62
|
+
dir
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def write_json(relative, value)
|
|
66
|
+
File.write(File.join(@dir, relative), "#{JSON.pretty_generate(value)}\n")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def with_scratch_databases
|
|
70
|
+
admin = PG.connect(dbname: "postgres")
|
|
71
|
+
admin.exec("SET client_min_messages = warning")
|
|
72
|
+
SCRATCH.each_value do |name|
|
|
73
|
+
admin.exec("DROP DATABASE IF EXISTS #{name} WITH (FORCE)")
|
|
74
|
+
admin.exec("CREATE DATABASE #{name}")
|
|
75
|
+
end
|
|
76
|
+
yield
|
|
77
|
+
ensure
|
|
78
|
+
SCRATCH.each_value { |name| admin&.exec("DROP DATABASE IF EXISTS #{name} WITH (FORCE)") }
|
|
79
|
+
admin&.close
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def write_heki(instances)
|
|
83
|
+
out = reset_dir("heki")
|
|
84
|
+
Dir.mktmpdir("hecks-legacy-heki-") do |tmp|
|
|
85
|
+
instances.each do |instance|
|
|
86
|
+
Hecks::Adapters::Heki.new(aggregate: instance.aggregate, settings: { dir: "." }, root: tmp).save(instance)
|
|
87
|
+
%w[heki heki.journal].each do |ext|
|
|
88
|
+
FileUtils.cp(File.join(tmp, "#{instance.aggregate.storage_name}.#{ext}"), out)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def write_sqlite(instances)
|
|
95
|
+
out = reset_dir("sqlite")
|
|
96
|
+
Dir.mktmpdir("hecks-legacy-sqlite-") do |tmp|
|
|
97
|
+
instances.each do |instance|
|
|
98
|
+
Hecks::Adapters::Sqlite.new(aggregate: instance.aggregate, settings: { database: "banking.sqlite3" },
|
|
99
|
+
root: tmp).save(instance)
|
|
100
|
+
end
|
|
101
|
+
dump, status = Open3.capture2("sqlite3", File.join(tmp, "banking.sqlite3"), ".dump")
|
|
102
|
+
raise Failure, "sqlite3 .dump failed" unless status.success?
|
|
103
|
+
|
|
104
|
+
File.write(File.join(out, "banking.sql"), dump)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def write_d1(instances)
|
|
109
|
+
reset_dir("d1")
|
|
110
|
+
connection = PersistenceLegacyFixture.fake_d1_connection
|
|
111
|
+
tables = instances.flat_map do |instance|
|
|
112
|
+
PersistenceLegacyFixture.with_d1_connection(connection) do
|
|
113
|
+
Hecks::Adapters::D1.new(aggregate: instance.aggregate,
|
|
114
|
+
settings: { account_id: "acc", database_id: "db", api_token: "tok" }).save(instance)
|
|
115
|
+
end
|
|
116
|
+
[instance.aggregate.storage_name, "#{instance.aggregate.storage_name}_entries"]
|
|
117
|
+
end
|
|
118
|
+
write_json("d1/rows.json",
|
|
119
|
+
tables.to_h { |table| [table, connection.execute(%(SELECT * FROM "#{table}" ORDER BY rowid))] })
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def write_postgres(instances)
|
|
123
|
+
reset_dir("postgres")
|
|
124
|
+
rows = instances.to_h do |instance|
|
|
125
|
+
adapter = Hecks::Adapters::Postgres.new(aggregate: instance.aggregate, settings: { database: SCRATCH[:postgres] })
|
|
126
|
+
adapter.save(instance)
|
|
127
|
+
db = adapter.instance_variable_get(:@db)
|
|
128
|
+
table = PG::Connection.quote_ident(instance.aggregate.storage_name)
|
|
129
|
+
entries = PG::Connection.quote_ident("#{instance.aggregate.storage_name}_entries")
|
|
130
|
+
[instance.aggregate.storage_name, {
|
|
131
|
+
"head" => db.exec("SELECT * FROM #{table} ORDER BY id").to_a,
|
|
132
|
+
"entries" => db.exec("SELECT aggregate_id, operation, state, mirrors FROM #{entries} ORDER BY sequence").to_a
|
|
133
|
+
}]
|
|
134
|
+
end
|
|
135
|
+
write_json("postgres/rows.json", rows)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def write_postgres_era(instances)
|
|
139
|
+
reset_dir("postgres_era")
|
|
140
|
+
rows = instances.to_h { |instance| [instance.aggregate.storage_name, era_rows(instance)] }
|
|
141
|
+
write_json("postgres_era/rows.json", rows)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def era_rows(instance)
|
|
145
|
+
adapter = Hecks::Adapters::PostgresEra.new(aggregate: instance.aggregate,
|
|
146
|
+
settings: { database: SCRATCH[:postgres_era] })
|
|
147
|
+
adapter.save(instance)
|
|
148
|
+
db = adapter.instance_variable_get(:@db)
|
|
149
|
+
journal = adapter.instance_variable_get(:@lineage).quoted_journal
|
|
150
|
+
snapshot = adapter.send(:quoted_head_snapshot)
|
|
151
|
+
{
|
|
152
|
+
"journal" => db.exec_params(
|
|
153
|
+
"SELECT ordinal, era, aggregate, aggregate_id, operation, state, mirrors FROM #{journal} " \
|
|
154
|
+
"WHERE aggregate = $1 ORDER BY ordinal", [instance.aggregate.storage_name]
|
|
155
|
+
).to_a,
|
|
156
|
+
"head_snapshot" => db.exec("SELECT id, ordinal, operation, state FROM #{snapshot} ORDER BY id").to_a
|
|
157
|
+
}
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|