hecks 2.9.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +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 +4 -2
- 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 +7 -4
- 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 +6 -3
- 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
|
@@ -10,8 +10,32 @@ module Hecks
|
|
|
10
10
|
module Reattest
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Says how an edited era text stands against the shape the era was frozen with, without
|
|
14
|
+
# refusing anything: the facts `Era.Permit`'s givens hold, and what `shape_guard!` raises on.
|
|
15
|
+
#
|
|
16
|
+
# @param text [String] the held era's bluebook source as it now stands
|
|
17
|
+
# @param stored_hash [String, nil] the era's minted shape hash (SHA-256 hex); nil if unnamed
|
|
18
|
+
# @param stored_projection [Hash{String => Object}, nil] the stored
|
|
19
|
+
# `Runtime::StorageShape.project` result as parsed JSON; nil when absent
|
|
20
|
+
# @return [Symbol] `:cosmetic` when the shape is unchanged, `:unnamed` when neither a
|
|
21
|
+
# projection nor a hash is stored, `:changed` when the text projects to another shape,
|
|
22
|
+
# `:unloadable` when the text does not load as a bluebook
|
|
23
|
+
def verdict(text:, stored_hash:, stored_projection: nil)
|
|
24
|
+
bluebook = shadow(text)
|
|
25
|
+
return :unloadable unless bluebook
|
|
26
|
+
|
|
27
|
+
# The stored projection is compared first: it is version-free, so a new canonical form
|
|
28
|
+
# cannot make a cosmetic edit look like a shape change. The hash is the fallback.
|
|
29
|
+
if stored_projection
|
|
30
|
+
edited = JSON.parse(JSON.generate(Runtime::StorageShape.project(bluebook)))
|
|
31
|
+
return edited == stored_projection ? :cosmetic : :changed
|
|
32
|
+
end
|
|
33
|
+
return :unnamed unless stored_hash
|
|
34
|
+
|
|
35
|
+
Runtime::StorageShape.mint_hash(bluebook) == stored_hash ? :cosmetic : :changed
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Refuses an edited era text that projects to another shape than the era froze with.
|
|
15
39
|
#
|
|
16
40
|
# @param domain [String] the domain's name, used in refusal messages
|
|
17
41
|
# @param ordinal [Integer] the era's ordinal, used in refusal messages
|
|
@@ -23,36 +47,31 @@ module Hecks
|
|
|
23
47
|
# projection nor a hash is stored
|
|
24
48
|
# @raise [Runtime::WiringError] if `text` does not load, or projects to another shape
|
|
25
49
|
def shape_guard!(domain:, ordinal:, text:, stored_hash:, stored_projection: nil)
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
found = verdict(text: text, stored_hash: stored_hash, stored_projection: stored_projection)
|
|
51
|
+
return found if %i[cosmetic unnamed].include?(found)
|
|
52
|
+
|
|
53
|
+
if found == :unloadable
|
|
28
54
|
raise Runtime::WiringError,
|
|
29
55
|
"cannot re-attest era #{ordinal} of #{domain}: the edited text does not load as a " \
|
|
30
56
|
"bluebook — a held era text is bootable source; restore a loadable text"
|
|
31
57
|
end
|
|
58
|
+
raise Runtime::WiringError, changed_shape_message(domain, ordinal, text, stored_hash, stored_projection)
|
|
59
|
+
end
|
|
32
60
|
|
|
33
|
-
|
|
34
|
-
|
|
61
|
+
# The refusal for an edit that changed the era's shape.
|
|
62
|
+
#
|
|
63
|
+
# @return [String] names the minted label when the era was compared by hash
|
|
64
|
+
def changed_shape_message(domain, ordinal, text, stored_hash, stored_projection)
|
|
65
|
+
head = "cannot re-attest era #{ordinal} of #{domain}: the edit changed the era's SHAPE, not just "
|
|
66
|
+
tail = "Attesting would retroactively redefine what era #{ordinal} meant for data already written " \
|
|
67
|
+
"under it; restore a text with the original shape"
|
|
35
68
|
if stored_projection
|
|
36
|
-
|
|
37
|
-
return :cosmetic if edited == stored_projection
|
|
38
|
-
|
|
39
|
-
raise Runtime::WiringError,
|
|
40
|
-
"cannot re-attest era #{ordinal} of #{domain}: the edit changed the era's SHAPE, not just " \
|
|
41
|
-
"its text — the text no longer projects to the shape frozen for era #{ordinal}. " \
|
|
42
|
-
"Attesting would retroactively redefine what era #{ordinal} meant for data already written " \
|
|
43
|
-
"under it; restore a text with the original shape"
|
|
69
|
+
return "#{head}its text — the text no longer projects to the shape frozen for era #{ordinal}. #{tail}"
|
|
44
70
|
end
|
|
45
|
-
return :unnamed unless stored_hash
|
|
46
|
-
|
|
47
|
-
computed = Runtime::StorageShape.mint_hash(bluebook)
|
|
48
|
-
return :cosmetic if computed == stored_hash
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"a different shape (the text now projects to #{computed[0, Runtime::StorageShape::LABEL_LENGTH]}). " \
|
|
54
|
-
"Attesting would retroactively redefine what era #{ordinal} meant for data already written " \
|
|
55
|
-
"under it; restore a text with the original shape"
|
|
72
|
+
label = Runtime::StorageShape::LABEL_LENGTH
|
|
73
|
+
"#{head}its text — its name #{stored_hash[0, label]} was minted from a different shape (the text " \
|
|
74
|
+
"now projects to #{Runtime::StorageShape.mint_hash(shadow(text))[0, label]}). #{tail}"
|
|
56
75
|
end
|
|
57
76
|
|
|
58
77
|
# Parses bluebook source in a scratch registry, through a temporary file that is
|
|
@@ -211,7 +211,16 @@ module Hecks
|
|
|
211
211
|
return true if attribute.nil? || value.nil? || attribute.reference?
|
|
212
212
|
return composite_decoded?(aggregate, attribute.type.to_s, value) unless attribute.list?
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
return true unless value.is_a?(Array)
|
|
215
|
+
|
|
216
|
+
# The element type resolves once per list, not once per element.
|
|
217
|
+
fields = :unresolved
|
|
218
|
+
value.all? do |element|
|
|
219
|
+
next true unless element.is_a?(Hash)
|
|
220
|
+
|
|
221
|
+
fields = composite_fields(aggregate, attribute.type.to_s) if fields == :unresolved
|
|
222
|
+
fields.nil? || hash_decoded?(aggregate, fields, element)
|
|
223
|
+
end
|
|
215
224
|
end
|
|
216
225
|
|
|
217
226
|
# Checks one stored value object or entity, the mirror of `decode_composite`.
|
|
@@ -225,13 +234,23 @@ module Hecks
|
|
|
225
234
|
def composite_decoded?(aggregate, type, value)
|
|
226
235
|
return true unless value.is_a?(Hash)
|
|
227
236
|
|
|
237
|
+
fields = composite_fields(aggregate, type)
|
|
238
|
+
fields.nil? || hash_decoded?(aggregate, fields, value)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Maps the declared keys of a stored value object or entity, looked up by type name.
|
|
242
|
+
#
|
|
243
|
+
# @param aggregate [Bluebook::Aggregate, Bluebook::Entity] the root construct that
|
|
244
|
+
# declares, or whose chapter declares, the type
|
|
245
|
+
# @param type [String] the declared type name
|
|
246
|
+
# @return [Hash{Symbol => Bluebook::Attribute, nil}, nil] the entity's fields, else the
|
|
247
|
+
# unambiguous value object's; nil when `type` names neither
|
|
248
|
+
def composite_fields(aggregate, type)
|
|
228
249
|
entity = Runtime::Value.find_entity(aggregate, type)
|
|
229
|
-
return
|
|
250
|
+
return entity_fields(entity) if entity
|
|
230
251
|
|
|
231
252
|
value_object = Runtime::Value.value_object_for(aggregate, type)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
hash_decoded?(aggregate, value_object.attributes.to_h { |field| [field.name, field] }, value)
|
|
253
|
+
value_object&.attributes&.to_h { |field| [field.name, field] }
|
|
235
254
|
end
|
|
236
255
|
end
|
|
237
256
|
end
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
require "tempfile"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
# What each `project_*` generator of the language writes, held as data: absolute path to text.
|
|
9
|
+
#
|
|
10
|
+
# The tables of the language (the model's holding half, the vocabulary, the parser's keywords, the
|
|
11
|
+
# Rust vocabulary, reserved names, field hints, the expression tables and the DSL reference) are
|
|
12
|
+
# projected from the Bluebook chapter's own declarations. Building them apart from writing them
|
|
13
|
+
# lets a caller compare a projection with the tree before anything is changed: a
|
|
14
|
+
# `hecks project_*` verb writes the answer, and the Hecks domain's Language commands report
|
|
15
|
+
# drift and write only when confirmed.
|
|
16
|
+
module ProjectionFiles
|
|
17
|
+
# The repository root this file lives in.
|
|
18
|
+
ROOT = File.expand_path("../..", __dir__)
|
|
19
|
+
|
|
20
|
+
# Raised when a projection would leave the language unable to boot.
|
|
21
|
+
class Refused < StandardError; end
|
|
22
|
+
|
|
23
|
+
# The files a projection writes, and the ones it leaves stale.
|
|
24
|
+
#
|
|
25
|
+
# @!attribute [r] content
|
|
26
|
+
# @return [Hash{String => String}] absolute path to the text it should hold
|
|
27
|
+
# @!attribute [r] stale
|
|
28
|
+
# @return [Array<String>] absolute paths the projection does not emit and removes
|
|
29
|
+
Result = Struct.new(:content, :stale)
|
|
30
|
+
|
|
31
|
+
# Rust keyword and Cargo name tables, by the constant each becomes.
|
|
32
|
+
RESERVED_TABLES = {
|
|
33
|
+
"RUST_KEYWORDS" => "RustReservedWord",
|
|
34
|
+
"CARGO_RESERVED_DOMAIN_NAMES" => "CargoReservedName"
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
# Names of the projections, in the order a full regeneration runs them.
|
|
38
|
+
NAMES = %i[model vocabulary rust_vocabulary reserved_names parser_table bootstrap_table
|
|
39
|
+
field_hints expression_tables reference].freeze
|
|
40
|
+
|
|
41
|
+
module_function
|
|
42
|
+
|
|
43
|
+
# Builds one projection without writing anything.
|
|
44
|
+
#
|
|
45
|
+
# @param name [Symbol] one of `NAMES`
|
|
46
|
+
# @param root [String] the checkout the projection is for
|
|
47
|
+
# @return [Result] what it would write and remove
|
|
48
|
+
# @raise [ArgumentError] if the projection is not known
|
|
49
|
+
# @raise [Refused] if the projection would leave the language unable to boot
|
|
50
|
+
def build(name, root: ROOT)
|
|
51
|
+
raise ArgumentError, "no projection named #{name.inspect}" unless NAMES.include?(name.to_sym)
|
|
52
|
+
|
|
53
|
+
public_send(name, root)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Writes one projection, each file through a temporary file and a rename so a reader never sees
|
|
57
|
+
# a partial file, and removes what it does not emit.
|
|
58
|
+
#
|
|
59
|
+
# @param name [Symbol] one of `NAMES`
|
|
60
|
+
# @param root [String] the checkout the projection is for
|
|
61
|
+
# @return [Array<String>] one `wrote <path>` or `removed <path>` line for each change
|
|
62
|
+
def write(name, root: ROOT)
|
|
63
|
+
result = build(name, root: root)
|
|
64
|
+
lines = result.content.map { |path, text| write_atomically(path, text) }
|
|
65
|
+
lines + result.stale.map { |path| File.delete(path) && "removed #{path}" }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Writes one projection and prints what changed, as the `project_*` commands do.
|
|
69
|
+
#
|
|
70
|
+
# @param name [Symbol] one of `NAMES`
|
|
71
|
+
# @param root [String] the checkout the projection is for
|
|
72
|
+
# @return [void] the `wrote`/`removed` lines go to stdout
|
|
73
|
+
# @raise [SystemExit] with the reason on stderr when the projection is refused
|
|
74
|
+
def run(name, root: ROOT)
|
|
75
|
+
puts write(name, root: root)
|
|
76
|
+
rescue Refused => e
|
|
77
|
+
abort e.message
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Replaces a file through a same-directory temporary file and a rename.
|
|
81
|
+
#
|
|
82
|
+
# @param target [String] the file to write
|
|
83
|
+
# @param text [String] what it holds afterwards
|
|
84
|
+
# @return [String] the `wrote <path>` line
|
|
85
|
+
def write_atomically(target, text)
|
|
86
|
+
FileUtils.mkdir_p(File.dirname(target))
|
|
87
|
+
Tempfile.create(File.basename(target), File.dirname(target)) do |tmp|
|
|
88
|
+
tmp.write(text)
|
|
89
|
+
tmp.flush
|
|
90
|
+
File.rename(tmp.path, target)
|
|
91
|
+
end
|
|
92
|
+
"wrote #{target}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param root [String] the checkout
|
|
96
|
+
# @return [Result] the model's holding half, one file for each thing the chapter holds
|
|
97
|
+
def model(root)
|
|
98
|
+
require "hecks"
|
|
99
|
+
files = Projector.call(:model, bluebook: chapter)
|
|
100
|
+
out = File.join(root, "lib/hecks/bluebook")
|
|
101
|
+
Result.new(files.to_h { |relative, text| [File.join(out, relative), text] }, [])
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @param root [String] the checkout
|
|
105
|
+
# @return [Result] `lib/hecks/vocabulary.rb`, the language's closed sets
|
|
106
|
+
def vocabulary(root)
|
|
107
|
+
require "hecks"
|
|
108
|
+
Result.new({ File.join(root, "lib/hecks/vocabulary.rb") => artifact_text(:vocabulary) }, [])
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param root [String] the checkout
|
|
112
|
+
# @return [Result] one Rust enum a table under `rust/src/kernel/vocab/`; files it does
|
|
113
|
+
# not emit are stale
|
|
114
|
+
def rust_vocabulary(root)
|
|
115
|
+
require "hecks"
|
|
116
|
+
kernel = File.join(root, "rust/src/kernel")
|
|
117
|
+
files = Projector.call(:rust_vocabulary, bluebook: chapter)
|
|
118
|
+
content = files.to_h { |relative, text| [File.join(kernel, relative), text] }
|
|
119
|
+
Result.new(content, Dir.glob(File.join(kernel, "vocab", "*.rs")) - content.keys)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @param root [String] the checkout
|
|
123
|
+
# @return [Result] `reserved_names.rs` for the codegen and build crates, which share no library
|
|
124
|
+
# @raise [Refused] if a vocabulary declares no members
|
|
125
|
+
def reserved_names(root)
|
|
126
|
+
require "hecks/vocabulary"
|
|
127
|
+
consts = RESERVED_TABLES.map do |const, vocabulary|
|
|
128
|
+
words = Hecks::Vocabulary.fetch(vocabulary)
|
|
129
|
+
raise Refused, "vocabulary #{vocabulary} declares no members" if words.empty?
|
|
130
|
+
|
|
131
|
+
lines = words.map { |word| " #{word.inspect}," }.join("\n")
|
|
132
|
+
"/// The `#{vocabulary}` vocabulary, #{words.size} entries.\n" \
|
|
133
|
+
"pub const #{const}: &[&str] = &[\n#{lines}\n];"
|
|
134
|
+
end
|
|
135
|
+
text = reserved_names_text(consts)
|
|
136
|
+
targets = %w[rust/codegen/src/reserved_names.rs rust/build/src/reserved_names.rs]
|
|
137
|
+
Result.new(targets.to_h { |target| [File.join(root, target), text] }, [])
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @param root [String] the checkout
|
|
141
|
+
# @return [Result] the Rust parser's keyword table
|
|
142
|
+
def parser_table(root)
|
|
143
|
+
require "hecks"
|
|
144
|
+
Result.new({ File.join(root, "rust/parser/src/keywords.rs") => artifact_text(:parser_table) }, [])
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# @param root [String] the checkout
|
|
148
|
+
# @return [Result] the DSL's bootstrap-window fallbacks
|
|
149
|
+
def bootstrap_table(root)
|
|
150
|
+
require "hecks"
|
|
151
|
+
path = File.join(root, "lib/hecks/bluebook/dsl/bootstrap_table.rb")
|
|
152
|
+
Result.new({ path => artifact_text(:bootstrap_table) }, [])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @param root [String] the checkout
|
|
156
|
+
# @return [Result] `rust/host/src/field_hints.rs`, the hints the host's form fields guess from
|
|
157
|
+
def field_hints(root)
|
|
158
|
+
require "hecks"
|
|
159
|
+
vocabulary = chapter.aggregates.find { |aggregate| aggregate.hecks_name == "Vocabulary" }
|
|
160
|
+
field_hint = vocabulary.value_objects.find { |value_object| value_object.hecks_name == "FieldHint" }
|
|
161
|
+
hints = field_hint.members.map(&:to_h)
|
|
162
|
+
Result.new({ File.join(root, "rust/host/src/field_hints.rs") => field_hints_text(hints) }, [])
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# @param root [String] the checkout
|
|
166
|
+
# @return [Result] `lib/hecks/bluebook/expression/projection.json`
|
|
167
|
+
# @raise [Refused] if an admitted operator has no declared algebra, or the projection drops an
|
|
168
|
+
# operator the language's own guards evaluate through
|
|
169
|
+
def expression_tables(root)
|
|
170
|
+
require "hecks"
|
|
171
|
+
require "hecks/grammar"
|
|
172
|
+
operators = expression_operators(Grammar.expression)
|
|
173
|
+
dropped = Grammar.self_bearing_operators.except(*operators.map { |row| row[:symbol] })
|
|
174
|
+
raise Refused, dropped_message(dropped) unless dropped.empty?
|
|
175
|
+
|
|
176
|
+
dispatcher = Grammar.expression
|
|
177
|
+
text = "#{JSON.pretty_generate(operators: operators, normalisations: Grammar.admitted_normalisations(dispatcher))}\n"
|
|
178
|
+
Result.new({ File.join(root, "lib/hecks/bluebook/expression/projection.json") => text }, [])
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# The DSL reference pages and the README regions generated from the same declarations.
|
|
182
|
+
#
|
|
183
|
+
# @param root [String] the checkout
|
|
184
|
+
# @return [Result] every page of `docs/implemented/reference/` and `README.md`
|
|
185
|
+
def reference(root)
|
|
186
|
+
require "hecks"
|
|
187
|
+
directory = File.join(root, "docs/implemented/reference")
|
|
188
|
+
pages = Projector.call(:reference, bluebook: chapter, options: { from: directory })
|
|
189
|
+
content = pages.to_h { |relative, text| [File.join(directory, relative), text] }
|
|
190
|
+
readme = File.join(root, "README.md")
|
|
191
|
+
content[readme] = Doc::Reference.render_readme(root, File.read(readme))
|
|
192
|
+
Result.new(content, [])
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# @param projection [Symbol] a projection registered with the projector
|
|
196
|
+
# @return [String] what it projects from the Bluebook chapter, as the text a file holds
|
|
197
|
+
def artifact_text(projection)
|
|
198
|
+
artifact = Projector.call(projection, bluebook: chapter)
|
|
199
|
+
artifact.is_a?(String) ? artifact : "#{JSON.pretty_generate(artifact)}\n"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# @return [Bluebook::Aggregate] the Bluebook chapter, which every projection reads
|
|
203
|
+
def chapter
|
|
204
|
+
Bluebook::MetaValidator.grammar_registry.bluebook("Bluebook")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @param dispatcher [Object] the expression dispatcher
|
|
208
|
+
# @return [Array<Hash>] each admitted operator, with the algebra a comparison declares
|
|
209
|
+
# @raise [Refused] if a comparison has no declared algebra
|
|
210
|
+
def expression_operators(dispatcher)
|
|
211
|
+
vocabulary = chapter.aggregates.find { |aggregate| aggregate.name == "Vocabulary" }
|
|
212
|
+
algebra = vocabulary.value_objects.find { |value_object| value_object.hecks_name == "Comparison" }
|
|
213
|
+
.members.to_h { |row| [row.to_h.values.first, row.to_h] }
|
|
214
|
+
Grammar.admitted_operators(dispatcher).map do |op|
|
|
215
|
+
row = { symbol: op[:symbol], category: op[:category], precedence: op[:precedence], arity: op[:arity] }
|
|
216
|
+
next row unless op[:category] == "comparison"
|
|
217
|
+
|
|
218
|
+
declared = algebra.fetch(op[:symbol]) do
|
|
219
|
+
raise Refused, "#{op[:symbol]} is admitted but Vocabulary::Comparison declares no algebra for it"
|
|
220
|
+
end
|
|
221
|
+
row.merge(compares_less_than: declared[:compares_less_than],
|
|
222
|
+
compares_equal: declared[:compares_equal], negated: declared[:negated])
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# @param dropped [Hash{String => Array<String>}] operator to the guards evaluating through it
|
|
227
|
+
# @return [String] one line for each operator a projection would strand
|
|
228
|
+
def dropped_message(dropped)
|
|
229
|
+
dropped.map do |symbol, sites|
|
|
230
|
+
"#{symbol} is self-bearing — the language's own predicates evaluate through it " \
|
|
231
|
+
"(#{sites.first(3).join('; ')}) — rewrite those guards before retiring it"
|
|
232
|
+
end.join("\n")
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# @param consts [Array<String>] the rendered Rust constants
|
|
236
|
+
# @return [String] the whole `reserved_names.rs`
|
|
237
|
+
def reserved_names_text(consts)
|
|
238
|
+
<<~RUST
|
|
239
|
+
// GENERATED by hecks project_reserved_names from the RustReservedWord and
|
|
240
|
+
// CargoReservedName vocabularies (lib/hecks/language/bluebook/
|
|
241
|
+
// vocabulary.bluebook). Do not hand-edit — re-run hecks project_reserved_names.
|
|
242
|
+
|
|
243
|
+
#{consts.join("\n\n")}
|
|
244
|
+
RUST
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# @param hints [Array<Hash>] the rows of `Vocabulary::FieldHint`
|
|
248
|
+
# @return [String] the whole `field_hints.rs`
|
|
249
|
+
def field_hints_text(hints)
|
|
250
|
+
consts = hints.map { |hint| field_hint_constant(hint) }.join("\n")
|
|
251
|
+
<<~RUST
|
|
252
|
+
// GENERATED by hecks project_field_hints from Vocabulary::FieldHint
|
|
253
|
+
// (lib/hecks/language/bluebook/vocabulary.bluebook). Do not
|
|
254
|
+
// hand-edit — re-run hecks project_field_hints instead.
|
|
255
|
+
//
|
|
256
|
+
// web.rs's `text_field` matches these in the SAME precedence Ruby's
|
|
257
|
+
// own `text_field` does: EMAIL_HINT, then URL_HINT, then TEL_HINT —
|
|
258
|
+
// against `html_type`, first match wins — then, only if `html_type`
|
|
259
|
+
// stayed "text", TEXTAREA_HINT against `kind`.
|
|
260
|
+
|
|
261
|
+
use regex::Regex;
|
|
262
|
+
use std::sync::LazyLock;
|
|
263
|
+
|
|
264
|
+
#{consts}
|
|
265
|
+
RUST
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# @param hint [Hash] one `FieldHint` row: its name, pattern and what it resolves to
|
|
269
|
+
# @return [String] the Rust `static` for it
|
|
270
|
+
def field_hint_constant(hint)
|
|
271
|
+
name = "#{hint[:name].upcase}_HINT"
|
|
272
|
+
<<~RUST
|
|
273
|
+
/// #{hint[:name].capitalize} hint, resolving to `#{hint[:resolves_to]}` on a match —
|
|
274
|
+
/// Vocabulary::FieldHint's own declared pattern, unmodified (the
|
|
275
|
+
/// same text `Regexp#source` reads off FieldShape's own
|
|
276
|
+
/// #{name}, which is built from this same row).
|
|
277
|
+
/// `(?i)` up front is this crate's spelling
|
|
278
|
+
/// of Ruby's trailing `/i` — the WHOLE pattern is case-insensitive
|
|
279
|
+
/// on both sides, never partially.
|
|
280
|
+
pub static #{name}: LazyLock<Regex> =
|
|
281
|
+
LazyLock::new(|| Regex::new(r#"(?i)#{hint[:pattern]}"#).expect("declared field-hint pattern must compile"));
|
|
282
|
+
RUST
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
@@ -21,7 +21,7 @@ module Hecks
|
|
|
21
21
|
# KeywordSeed under lib/hecks/language/).
|
|
22
22
|
#
|
|
23
23
|
# Do not edit. spec/bootstrap_table_spec.rb re-projects this in memory
|
|
24
|
-
# and refuses a diff — run
|
|
24
|
+
# and refuses a diff — run hecks project_bootstrap_table instead.
|
|
25
25
|
#
|
|
26
26
|
# Plain data, no requires: this is read while the grammar table it was
|
|
27
27
|
# projected from is still being built (`MetaValidator.bootstrapping?`).
|
|
@@ -253,7 +253,7 @@ module Hecks
|
|
|
253
253
|
parameters_yaml = [always_params_yaml, oauth_params_yaml, owning_params_yaml, extra_params_yaml].reject(&:empty?).join("\n")
|
|
254
254
|
|
|
255
255
|
template_yaml = <<~YAML
|
|
256
|
-
# GENERATED by
|
|
256
|
+
# GENERATED by hecks deploy project #{domain} — re-run it to refresh
|
|
257
257
|
# this file rather than hand-editing. Source: #{world_file}'s own
|
|
258
258
|
# deployed_to("AwsFargate") block.
|
|
259
259
|
#
|
|
@@ -569,7 +569,7 @@ module Hecks
|
|
|
569
569
|
)
|
|
570
570
|
|
|
571
571
|
dockerfile = <<~DOCKERFILE
|
|
572
|
-
# GENERATED by
|
|
572
|
+
# GENERATED by hecks deploy project #{domain} — re-run it to refresh this
|
|
573
573
|
# file rather than hand-editing. Modeled on a Ruby deployment's own
|
|
574
574
|
# Dockerfile shape: build the binary outside the image (this directory's own
|
|
575
575
|
# Makefile, before `docker build` runs), ship only the result — one COPY,
|
|
@@ -600,7 +600,7 @@ module Hecks
|
|
|
600
600
|
DOCKERFILE
|
|
601
601
|
|
|
602
602
|
makefile_content = <<~MAKE
|
|
603
|
-
# GENERATED by
|
|
603
|
+
# GENERATED by hecks deploy project #{domain} — re-run it to refresh
|
|
604
604
|
# this file rather than hand-editing.
|
|
605
605
|
#
|
|
606
606
|
# `make deploy` — builds rust/host for this domain, pushes it to this
|
|
@@ -630,11 +630,11 @@ module Hecks
|
|
|
630
630
|
\t@command -v aarch64-linux-gnu-gcc >/dev/null 2>&1 || { echo "aarch64-linux-gnu-gcc isn't on PATH. Install once with: brew tap messense/macos-cross-toolchains && brew install aarch64-unknown-linux-gnu"; exit 1; }
|
|
631
631
|
# The .wasm/.ir.json sidecars main.rs requires at boot,
|
|
632
632
|
# unconditionally — see template.yaml's own HECKS_WASM_PATH/
|
|
633
|
-
# HECKS_IR_PATH comment for why.
|
|
633
|
+
# HECKS_IR_PATH comment for why. `hecks build_wasm` is the same
|
|
634
634
|
# generator the Lambda deploy path already uses to produce
|
|
635
635
|
# rust/dist/#{domain_name}.wasm/.ir.json from this domain's own
|
|
636
636
|
# .bluebook.
|
|
637
|
-
\tcd $(ROOT) &&
|
|
637
|
+
\tcd $(ROOT) && HECKS_ENVIRONMENT=memory ruby exe/hecks build_wasm domain=$(DOMAIN) --wait
|
|
638
638
|
\tcd $(ROOT)/rust/host && CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc rustup run stable cargo build --release --target aarch64-unknown-linux-gnu --bin bootstrap
|
|
639
639
|
\tcp $(ROOT)/rust/host/target/aarch64-unknown-linux-gnu/release/bootstrap #{domain_name}-host
|
|
640
640
|
\tcp $(ROOT)/rust/dist/#{domain_name}.wasm #{domain_name}.wasm
|