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
|
@@ -2,15 +2,52 @@
|
|
|
2
2
|
Hecks.hecksagon "Deploy" do
|
|
3
3
|
persisted_by "Memory"
|
|
4
4
|
|
|
5
|
-
# `
|
|
6
|
-
#
|
|
5
|
+
# `Tenant.Provision` and `Tenant.Reprovision` dispatch this through their policies; `directory` is a real filesystem path, which `Tenant`'s
|
|
6
|
+
# declared `domain` name cannot supply. `adapter` may be left to the record, which leaves it to
|
|
7
|
+
# the adapter's PostgresEra.
|
|
7
8
|
Deploy::Tenant.port "TenantProvisioning" do
|
|
8
|
-
asks "
|
|
9
|
+
asks "WriteOverlay", to: Tenant do
|
|
9
10
|
attribute :database, DatabaseName
|
|
10
|
-
attribute :adapter, AdapterName
|
|
11
|
+
attribute :adapter, AdapterName, optional: true
|
|
11
12
|
attribute :directory, DirectoryPath
|
|
12
13
|
answers "TenantProvisioned"
|
|
13
14
|
refuses "ProvisioningRefused"
|
|
14
15
|
end
|
|
15
16
|
end
|
|
17
|
+
|
|
18
|
+
# Each run below asks the DeployToolchain adapter, which the Hecks domain supplies
|
|
19
|
+
# (lib/hecks/hecks/adapters/deploy_toolchain.rb): the outside a recipe, a lint, a comparison or
|
|
20
|
+
# a manifest reaches. Every ask is answered with the record's own arguments or refused with
|
|
21
|
+
# a reason.
|
|
22
|
+
Deploy::Recipe.port "DeployToolchain" do
|
|
23
|
+
asks "Generate", to: Recipe do
|
|
24
|
+
attribute :run, RunKey
|
|
25
|
+
answers "RecipeAnswered"
|
|
26
|
+
refuses "RecipeRefused"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Deploy::MakefileCheck.port "DeployToolchain" do
|
|
31
|
+
asks "Scan", to: MakefileCheck do
|
|
32
|
+
attribute :run, RunKey
|
|
33
|
+
answers "LintAnswered"
|
|
34
|
+
refuses "LintRefused"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Deploy::TemplateComparison.port "DeployToolchain" do
|
|
39
|
+
asks "Compare", to: TemplateComparison do
|
|
40
|
+
attribute :run, RunKey
|
|
41
|
+
answers "ComparisonAnswered"
|
|
42
|
+
refuses "ComparisonUnreadable"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Deploy::OidcManifest.port "DeployToolchain" do
|
|
47
|
+
asks "Manifest", to: OidcManifest do
|
|
48
|
+
attribute :run, RunKey
|
|
49
|
+
answers "ManifestAnswered"
|
|
50
|
+
refuses "ManifestRefused"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
16
53
|
end
|
data/lib/hecks/deploy/oidc.json
CHANGED
|
@@ -12,8 +12,88 @@
|
|
|
12
12
|
"role": null
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"scope": "deploy:
|
|
16
|
-
"verb": "Deploy::
|
|
15
|
+
"scope": "deploy:makefile_check.flag",
|
|
16
|
+
"verb": "Deploy::MakefileCheck.Flag",
|
|
17
|
+
"role": null
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"scope": "deploy:makefile_check.lint",
|
|
21
|
+
"verb": "Deploy::MakefileCheck.Lint",
|
|
22
|
+
"role": null
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"scope": "deploy:makefile_check.pass",
|
|
26
|
+
"verb": "Deploy::MakefileCheck.Pass",
|
|
27
|
+
"role": null
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"scope": "deploy:oidc_manifest.complete",
|
|
31
|
+
"verb": "Deploy::OidcManifest.Complete",
|
|
32
|
+
"role": null
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"scope": "deploy:oidc_manifest.fault",
|
|
36
|
+
"verb": "Deploy::OidcManifest.Fault",
|
|
37
|
+
"role": null
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"scope": "deploy:oidc_manifest.project_oidc",
|
|
41
|
+
"verb": "Deploy::OidcManifest.ProjectOidc",
|
|
42
|
+
"role": null
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"scope": "deploy:recipe.complete",
|
|
46
|
+
"verb": "Deploy::Recipe.Complete",
|
|
47
|
+
"role": null
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"scope": "deploy:recipe.fault",
|
|
51
|
+
"verb": "Deploy::Recipe.Fault",
|
|
52
|
+
"role": null
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"scope": "deploy:recipe.project",
|
|
56
|
+
"verb": "Deploy::Recipe.Project",
|
|
57
|
+
"role": null
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"scope": "deploy:template_comparison.diff",
|
|
61
|
+
"verb": "Deploy::TemplateComparison.Diff",
|
|
62
|
+
"role": null
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"scope": "deploy:template_comparison.drift",
|
|
66
|
+
"verb": "Deploy::TemplateComparison.Drift",
|
|
67
|
+
"role": null
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"scope": "deploy:template_comparison.match",
|
|
71
|
+
"verb": "Deploy::TemplateComparison.Match",
|
|
72
|
+
"role": null
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"scope": "deploy:template_comparison.refuse",
|
|
76
|
+
"verb": "Deploy::TemplateComparison.Refuse",
|
|
77
|
+
"role": null
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"scope": "deploy:tenant.abandon",
|
|
81
|
+
"verb": "Deploy::Tenant.Abandon",
|
|
82
|
+
"role": null
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"scope": "deploy:tenant.complete",
|
|
86
|
+
"verb": "Deploy::Tenant.Complete",
|
|
87
|
+
"role": null
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"scope": "deploy:tenant.provision",
|
|
91
|
+
"verb": "Deploy::Tenant.Provision",
|
|
92
|
+
"role": null
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"scope": "deploy:tenant.reprovision",
|
|
96
|
+
"verb": "Deploy::Tenant.Reprovision",
|
|
17
97
|
"role": null
|
|
18
98
|
}
|
|
19
99
|
],
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
require_relative "../bluebook/meta_validator"
|
|
2
|
+
require_relative "../naming"
|
|
3
|
+
|
|
4
|
+
module Hecks
|
|
5
|
+
module Doc
|
|
6
|
+
# The DSL reference, projected from the language's own Syntax chapter so
|
|
7
|
+
# its tables can never drift from the live builders. Regenerate with `hecks project_reference`.
|
|
8
|
+
module Reference
|
|
9
|
+
GENERATED_END = "<!-- generated:end -->".freeze
|
|
10
|
+
TODO_SENTINEL = "<!-- TODO: document this word -->".freeze
|
|
11
|
+
|
|
12
|
+
# A page's hand-written opening, keyed under a Symbol so it can never
|
|
13
|
+
# collide with a word (words are always Strings off the Syntax chapter).
|
|
14
|
+
PREAMBLE = :preamble
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# The marker opening one word's generated region.
|
|
19
|
+
def generated_begin(word) = "<!-- generated:begin word=#{word} -->"
|
|
20
|
+
|
|
21
|
+
# Same marker convention as generated_begin, keyed by region id for
|
|
22
|
+
# parts of a page not about one word (a lede, README's indexes).
|
|
23
|
+
def region_begin(id) = "<!-- generated:begin id=#{id} -->"
|
|
24
|
+
|
|
25
|
+
# The language's own Syntax aggregate, read off the judged grammar chapter.
|
|
26
|
+
def syntax
|
|
27
|
+
meta = Bluebook::MetaValidator.grammar_registry.bluebook("Bluebook")
|
|
28
|
+
meta.aggregates.find { |aggregate| aggregate.hecks_name == "Syntax" }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Reads one closed-set value object's declared members off the Syntax
|
|
32
|
+
# aggregate, as string-valued Hashes.
|
|
33
|
+
def rows(name)
|
|
34
|
+
syntax.value_objects.find { |vo| vo.hecks_name == name }
|
|
35
|
+
.members.map { |row| row.to_h.transform_values(&:to_s) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Delegates to SyntaxBoot.call's own cache instead of memoizing here —
|
|
39
|
+
# a second cache could lock in a stale set with no way to invalidate (ADR 0026).
|
|
40
|
+
def keywords = Bluebook::MetaValidator::SyntaxBoot.call[:keywords]
|
|
41
|
+
|
|
42
|
+
# Every declared Argument row.
|
|
43
|
+
def arguments = Bluebook::MetaValidator::SyntaxBoot.call[:arguments]
|
|
44
|
+
|
|
45
|
+
# Reads a row's declared status, defaulting to "admitted" when it declared none.
|
|
46
|
+
def status_of(row) = row[:status].to_s.empty? ? "admitted" : row[:status].to_s
|
|
47
|
+
|
|
48
|
+
# Whether a row is still current enough to appear in the reference.
|
|
49
|
+
def live?(row) = %w[admitted deprecated].include?(status_of(row))
|
|
50
|
+
|
|
51
|
+
# Every distinct context a keyword is declared in.
|
|
52
|
+
def contexts = keywords.map { |row| row[:context] }.uniq
|
|
53
|
+
|
|
54
|
+
# Derives a context's reference page filename.
|
|
55
|
+
def page_name(context) = "#{Naming.snake(context)}.md"
|
|
56
|
+
|
|
57
|
+
# Every reference page, rendered fresh: prose carried over from the
|
|
58
|
+
# committed pages, new words seeded with the sentinel, orphaned prose refused.
|
|
59
|
+
def pages(directory)
|
|
60
|
+
contexts.each_with_object({}) do |context, pages|
|
|
61
|
+
path = File.join(directory, page_name(context))
|
|
62
|
+
prose = File.exist?(path) ? harvest(File.read(path)) : {}
|
|
63
|
+
pages[page_name(context)] = render_page(context, prose, path)
|
|
64
|
+
end.merge("index.md" => render_index)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Renders one context's page, grouped by word (not per form) so a
|
|
68
|
+
# two-form word doesn't repeat its heading and prose.
|
|
69
|
+
def render_page(context, prose, path)
|
|
70
|
+
words = keywords.select { |row| row[:context] == context }.group_by { |row| row[:word] }
|
|
71
|
+
orphans = prose.keys - words.keys - [PREAMBLE]
|
|
72
|
+
unless orphans.empty?
|
|
73
|
+
raise "#{path} carries prose for #{orphans.join(', ')}, which the language no longer " \
|
|
74
|
+
"declares in #{context} — deleting writing is a human's decision, so decide"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
sections = words.map { |word, forms| render_word(forms, prose[word]) }
|
|
78
|
+
preamble = prose[PREAMBLE].to_s.strip
|
|
79
|
+
<<~PAGE
|
|
80
|
+
# #{context}
|
|
81
|
+
|
|
82
|
+
#{region_begin('page')}
|
|
83
|
+
#{context_lede(context)}
|
|
84
|
+
|
|
85
|
+
*The tables on this page are generated from the language's own
|
|
86
|
+
aggregate-local syntax tables (`lib/hecks/language/**/*.bluebook`)
|
|
87
|
+
by `hecks project_reference` — do not edit inside the markers. The prose
|
|
88
|
+
between them is hand-written and survives regeneration.*
|
|
89
|
+
#{GENERATED_END}
|
|
90
|
+
#{"\n#{preamble}\n" unless preamble.empty?}
|
|
91
|
+
#{sections.join("\n")}
|
|
92
|
+
PAGE
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The one-line description of where a context's words are typed.
|
|
96
|
+
def context_lede(context)
|
|
97
|
+
openers = keywords.select { |row| row[:opens] == context }
|
|
98
|
+
return "Words available at the top of a file." if context == "File"
|
|
99
|
+
return "Words available in the type position of an `attribute`." if context == "Type"
|
|
100
|
+
|
|
101
|
+
inside = openers.map { |row| "`#{row[:word]} do ... end`" }.uniq.join(" / ")
|
|
102
|
+
inside.empty? ? "Words available in the #{context} body." : "Words available inside #{inside}."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# One section per word, built off forms.first — spelling is the only
|
|
106
|
+
# column that differs between a word's two forms.
|
|
107
|
+
def render_word(forms, prose)
|
|
108
|
+
row = forms.first
|
|
109
|
+
table = argument_table(row)
|
|
110
|
+
facts = []
|
|
111
|
+
facts << "opens a `#{row[:opens]}` body" unless row[:opens].to_s.empty?
|
|
112
|
+
facts << "fills `#{row[:fills]}`" unless row[:fills].to_s.empty?
|
|
113
|
+
facts << "**status: #{status_of(row)}**" unless status_of(row) == "admitted"
|
|
114
|
+
facts << "was `#{row[:was]}`" unless row[:was].to_s.empty?
|
|
115
|
+
spellings = forms.map { |form| "`#{signature(form)}`" }.join(" / ")
|
|
116
|
+
|
|
117
|
+
<<~WORD
|
|
118
|
+
## #{row[:word]}
|
|
119
|
+
|
|
120
|
+
#{generated_begin(row[:word])}
|
|
121
|
+
#{spellings}#{" — #{facts.join(', ')}" unless facts.empty?}
|
|
122
|
+
#{table}#{GENERATED_END}
|
|
123
|
+
|
|
124
|
+
#{prose_or_sentinel(prose)}
|
|
125
|
+
WORD
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Falls back to the TODO sentinel when a word has no prose yet.
|
|
129
|
+
def prose_or_sentinel(prose)
|
|
130
|
+
text = prose.to_s.strip
|
|
131
|
+
text.empty? ? TODO_SENTINEL : text
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# The Argument rows declared for one Keyword row's word, in its context.
|
|
135
|
+
def word_arguments(row)
|
|
136
|
+
arguments.select { |arg| arg[:keyword] == row[:word] && arg[:context] == row[:context] }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Builds the call spelling shown for one word: positional arguments
|
|
140
|
+
# then named ones, with a trailing `do ... end` unless its body is "none".
|
|
141
|
+
def signature(row)
|
|
142
|
+
positional = word_arguments(row).reject { |arg| arg[:at].to_s.empty? }
|
|
143
|
+
.sort_by { |arg| arg[:at].to_i }
|
|
144
|
+
.map { |arg| arg[:fills].to_s.empty? ? arg[:kind] : arg[:fills] }
|
|
145
|
+
named = word_arguments(row).select { |arg| arg[:at].to_s.empty? }
|
|
146
|
+
.map { |arg| "#{arg[:named]}:" }
|
|
147
|
+
parts = positional + named
|
|
148
|
+
base = parts.empty? ? row[:word] : "#{row[:word]} #{parts.join(', ')}"
|
|
149
|
+
row[:body].to_s == "none" ? base : "#{base} do ... end"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Renders one word's arguments as a Markdown table, or "" if it declares none.
|
|
153
|
+
def argument_table(row)
|
|
154
|
+
args = word_arguments(row)
|
|
155
|
+
return "" if args.empty?
|
|
156
|
+
|
|
157
|
+
lines = ["", "| argument | kind | required | fills |", "|---|---|---|---|"]
|
|
158
|
+
args.each do |arg|
|
|
159
|
+
name = arg[:at].to_s.empty? ? "`#{arg[:named]}:`" : "positional #{arg[:at]}"
|
|
160
|
+
lines << "| #{name} | #{arg[:kind]} | #{arg[:required]} | #{arg[:fills]} |"
|
|
161
|
+
end
|
|
162
|
+
"#{lines.join("\n")}\n"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Renders the reference index page, one linked entry per context.
|
|
166
|
+
def render_index
|
|
167
|
+
listed = contexts.map do |context|
|
|
168
|
+
count = keywords.select { |row| row[:context] == context }.map { |row| row[:word] }.uniq.size
|
|
169
|
+
"- [#{context}](#{page_name(context)}) — #{count} #{count == 1 ? 'word' : 'words'}"
|
|
170
|
+
end
|
|
171
|
+
<<~INDEX
|
|
172
|
+
# The DSL reference
|
|
173
|
+
|
|
174
|
+
One page per context — the place in a file where a word may be
|
|
175
|
+
typed. Generated by `hecks project_reference` from the Syntax chapter;
|
|
176
|
+
the prose between the generated markers is hand-written and
|
|
177
|
+
survives regeneration.
|
|
178
|
+
|
|
179
|
+
#{listed.join("\n")}
|
|
180
|
+
INDEX
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Prose keyed by word: everything between a section's generated region
|
|
184
|
+
# and the next `## ` heading. Starts collecting under `PREAMBLE` (not nil)
|
|
185
|
+
# so a page written before that region existed still parses unchanged.
|
|
186
|
+
# rubocop:disable-next Metrics/PerceivedComplexity
|
|
187
|
+
def harvest(text)
|
|
188
|
+
prose = {}
|
|
189
|
+
current = PREAMBLE
|
|
190
|
+
collecting = false
|
|
191
|
+
buffer = []
|
|
192
|
+
|
|
193
|
+
# A `## ` line inside a fence is not a heading — it's a comment in
|
|
194
|
+
# the runnable example, not a section break.
|
|
195
|
+
in_fence = false
|
|
196
|
+
|
|
197
|
+
text.each_line do |line|
|
|
198
|
+
in_fence = !in_fence if line.start_with?("```")
|
|
199
|
+
|
|
200
|
+
if !in_fence && (match = line.match(/\A## (\S+)\s*\z/))
|
|
201
|
+
prose[current] = buffer.join.strip if current && collecting
|
|
202
|
+
current = match[1]
|
|
203
|
+
collecting = false
|
|
204
|
+
buffer = []
|
|
205
|
+
elsif line.include?(GENERATED_END)
|
|
206
|
+
collecting = true
|
|
207
|
+
elsif collecting
|
|
208
|
+
buffer << line
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
prose[current] = buffer.join.strip if current && collecting
|
|
212
|
+
prose.reject { |_word, text_| text_.empty? || text_ == TODO_SENTINEL }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Renders every reference page and writes each to `directory`.
|
|
216
|
+
def write!(directory)
|
|
217
|
+
FileUtils.mkdir_p(directory)
|
|
218
|
+
pages(directory).each do |name, content|
|
|
219
|
+
File.write(File.join(directory, name), content)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# README's own generated regions, keyed by region id instead of a word.
|
|
224
|
+
def readme_regions(root)
|
|
225
|
+
{
|
|
226
|
+
"guides" => guide_index(root),
|
|
227
|
+
"reference" => reference_index(root),
|
|
228
|
+
"corpus" => corpus_roster(root),
|
|
229
|
+
"diagrams" => diagram_showcase(root)
|
|
230
|
+
}
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Lists every committed guide, linked and titled by its own heading.
|
|
234
|
+
def guide_index(root)
|
|
235
|
+
paths = Dir.glob(File.join(root, "docs/implemented/guides/*.md"))
|
|
236
|
+
.reject { |p| %w[AUTHORING.md].include?(File.basename(p)) }
|
|
237
|
+
lines = paths.map do |path|
|
|
238
|
+
heading = File.foreach(path).find { |line| line.start_with?("# ") }
|
|
239
|
+
title = heading ? heading.sub(/\A#\s*/, "").strip : File.basename(path)
|
|
240
|
+
"- [#{title}](docs/implemented/guides/#{File.basename(path)})"
|
|
241
|
+
end
|
|
242
|
+
lines.join("\n")
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Links the reference index, with its context count.
|
|
246
|
+
def reference_index(_root)
|
|
247
|
+
count = contexts.size
|
|
248
|
+
"[The DSL reference](docs/implemented/reference/index.md) — #{count} contexts, generated from " \
|
|
249
|
+
"the aggregate-local tables under `lib/hecks/language/` and held to them by " \
|
|
250
|
+
"`spec/reference_golden_spec.rb`."
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Quotes the real, committed diagram file rather than re-deriving one,
|
|
254
|
+
# so this can't drift from `spec/diagrams_spec.rb`'s own check.
|
|
255
|
+
def diagram_showcase(root)
|
|
256
|
+
lifecycle = File.read(File.join(root, "docs/generated/diagrams/pizzas/Order_lifecycle.mmd")).strip
|
|
257
|
+
<<~MARKDOWN.strip
|
|
258
|
+
`hecks project_diagrams` reads a booted domain's own declaration and draws it as Mermaid — nine kinds so far: `<Name>_lifecycle.mmd`, `relationships.mmd`, `dispatch.mmd`, `roles.mmd`, `ports.mmd`, `read_models.mmd`, `<Name>_surface.mmd` (what a command does, and what it writes), `<Name>_saga.mmd`, and `frameworks.mmd`. Nothing hand-drawn — the same reason a domain is data at all. Order's own lifecycle, straight off the bluebook above:
|
|
259
|
+
|
|
260
|
+
```mermaid
|
|
261
|
+
#{lifecycle}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The full set for every domain in this checkout — `examples/pizzas`, `examples/banking` — lives in [`docs/generated/diagrams/`](docs/generated/diagrams/), held to the declaration by `spec/diagrams_spec.rb` the same drift-refusing way this page is held to its own source.
|
|
265
|
+
MARKDOWN
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Lists every example domain with a `.bluebook` file, with its own declared vision.
|
|
269
|
+
def corpus_roster(root)
|
|
270
|
+
dirs = Dir.glob(File.join(root, "examples/*/"))
|
|
271
|
+
lines = dirs.filter_map do |dir|
|
|
272
|
+
name = File.basename(dir.chomp("/"))
|
|
273
|
+
bluebooks = Dir.glob(File.join(dir, "bluebook/*.bluebook"))
|
|
274
|
+
bluebooks = Dir.glob(File.join(dir, "*.bluebook")) if bluebooks.empty?
|
|
275
|
+
next if bluebooks.empty?
|
|
276
|
+
|
|
277
|
+
vision = bluebooks.filter_map { |bluebook| File.read(bluebook)[/vision\s+"([^"]*)"/, 1] }.first
|
|
278
|
+
"- **#{name}** — #{vision}"
|
|
279
|
+
end
|
|
280
|
+
lines.join("\n")
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Replaces every generated region inside `text` with its freshly rendered
|
|
284
|
+
# content, leaving the hand-written parts of README untouched.
|
|
285
|
+
def render_readme(root, text)
|
|
286
|
+
readme_regions(root).reduce(text) do |current, (id, content)|
|
|
287
|
+
pattern = /#{Regexp.escape(region_begin(id))}.*?#{Regexp.escape(GENERATED_END)}/m
|
|
288
|
+
current.sub(pattern) { "#{region_begin(id)}\n#{content}\n#{GENERATED_END}" }
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Regenerates README's generated regions in place.
|
|
293
|
+
def write_readme!(root)
|
|
294
|
+
path = File.join(root, "README.md")
|
|
295
|
+
File.write(path, render_readme(root, File.read(path)))
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Matches a runnable `ruby`/`ruby bluebook`/`ruby boot` fenced example;
|
|
299
|
+
# `ruby skip` and hidden boot blocks are setup, not an example, and don't count.
|
|
300
|
+
EXAMPLE_FENCE = /^```ruby(?: bluebook| boot)?[ \t]*$/
|
|
301
|
+
|
|
302
|
+
# Whether a word's prose carries a runnable example.
|
|
303
|
+
def exemplified?(prose) = prose.to_s.match?(EXAMPLE_FENCE)
|
|
304
|
+
|
|
305
|
+
# Every live word paired with its prose; shared by both coverage gates
|
|
306
|
+
# so their page-walks can't drift apart.
|
|
307
|
+
def live_words(directory)
|
|
308
|
+
rows = contexts.flat_map do |context|
|
|
309
|
+
path = File.join(directory, page_name(context))
|
|
310
|
+
prose = File.exist?(path) ? harvest(File.read(path)) : {}
|
|
311
|
+
keywords.select { |row| row[:context] == context && live?(row) }
|
|
312
|
+
.map { |row| [row[:word], context, prose[row[:word]]] }
|
|
313
|
+
end
|
|
314
|
+
rows.uniq { |word, context, _| [word, context] }
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Disambiguates a word by the context it is declared in.
|
|
318
|
+
def name_of(word, context) = "#{word} (#{context})"
|
|
319
|
+
|
|
320
|
+
# The coverage gate's question: every live word with no prose yet.
|
|
321
|
+
def undocumented(directory)
|
|
322
|
+
live_words(directory).reject { |_word, _context, prose| prose }
|
|
323
|
+
.map { |word, context, _| name_of(word, context) }
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# The second coverage gate: prose alone can go stale or describe
|
|
327
|
+
# unwired behavior; a runnable example is the only doc that can go red.
|
|
328
|
+
def unexemplified(directory)
|
|
329
|
+
live_words(directory).reject { |_word, _context, prose| exemplified?(prose) }
|
|
330
|
+
.map { |word, context, _| name_of(word, context) }
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Both coverage gates, worded for a person: each gap section lists the words that owe it,
|
|
334
|
+
# and a word missing both kinds is listed twice, one repair each.
|
|
335
|
+
#
|
|
336
|
+
# @param directory [String] the reference pages
|
|
337
|
+
# @return [Array(Boolean, String)] whether every live word is covered, and what to print
|
|
338
|
+
def coverage_report(directory)
|
|
339
|
+
gaps = [[undocumented(directory), "no prose — write their sections"],
|
|
340
|
+
[unexemplified(directory), "no running example — write one in each word's own section"]]
|
|
341
|
+
sections = gaps.reject { |words, _| words.empty? }.map do |words, owed|
|
|
342
|
+
head = "#{words.size} live #{words.size == 1 ? 'word carries' : 'words carry'} #{owed}:\n"
|
|
343
|
+
"#{head}#{words.map { |word| " #{word}\n" }.join}\n"
|
|
344
|
+
end
|
|
345
|
+
return [true, "every live word carries prose and a running example."] if sections.empty?
|
|
346
|
+
|
|
347
|
+
[false, sections.join]
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|