hecks 3.4.2 → 3.6.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/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +1 -1
- data/lib/hecks/adapters/driven/claude_code.rb +11 -7
- data/lib/hecks/adapters/driven/d1/connection.rb +90 -0
- data/lib/hecks/adapters/driven/d1.rb +48 -314
- data/lib/hecks/adapters/driven/folder.rb +20 -10
- data/lib/hecks/adapters/driven/google_authentication.rb +18 -4
- data/lib/hecks/adapters/driven/governance_authorization.rb +2 -2
- data/lib/hecks/adapters/driven/heki/journal.rb +11 -10
- data/lib/hecks/adapters/driven/heki/saga_store.rb +4 -6
- data/lib/hecks/adapters/driven/heki/sagas.rb +55 -0
- data/lib/hecks/adapters/driven/heki.rb +21 -66
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +37 -12
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +1 -8
- data/lib/hecks/adapters/driven/memory/outbox_rows.rb +76 -0
- data/lib/hecks/adapters/driven/memory/shared_elements/values.rb +117 -0
- data/lib/hecks/adapters/driven/memory/shared_elements.rb +10 -97
- data/lib/hecks/adapters/driven/memory.rb +3 -65
- data/lib/hecks/adapters/driven/postgres/codec.rb +29 -26
- data/lib/hecks/adapters/driven/postgres/ddl.rb +50 -0
- data/lib/hecks/adapters/driven/postgres/dialect.rb +93 -0
- data/lib/hecks/adapters/driven/postgres/events.rb +57 -0
- data/lib/hecks/adapters/driven/postgres/journal.rb +127 -0
- data/lib/hecks/adapters/driven/postgres/outbox.rb +39 -31
- data/lib/hecks/adapters/driven/postgres/repository.rb +190 -0
- data/lib/hecks/adapters/driven/postgres/sagas.rb +72 -0
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +13 -41
- data/lib/hecks/adapters/driven/postgres.rb +61 -528
- data/lib/hecks/adapters/driven/prism.rb +1 -1
- data/lib/hecks/adapters/driven/sql_query_builder.rb +45 -53
- data/lib/hecks/adapters/driven/sql_value_members.rb +57 -0
- data/lib/hecks/adapters/driven/sqlite/codec.rb +32 -29
- data/lib/hecks/adapters/driven/sqlite/ddl.rb +68 -0
- data/lib/hecks/adapters/driven/sqlite/dialect.rb +55 -0
- data/lib/hecks/adapters/driven/sqlite/events.rb +61 -0
- data/lib/hecks/adapters/driven/sqlite/journal.rb +125 -0
- data/lib/hecks/adapters/driven/sqlite/outbox.rb +98 -0
- data/lib/hecks/adapters/driven/sqlite/projection.rb +82 -63
- data/lib/hecks/adapters/driven/sqlite/repository.rb +146 -0
- data/lib/hecks/adapters/driven/sqlite/sagas.rb +69 -0
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +8 -55
- data/lib/hecks/adapters/driven/sqlite.rb +36 -513
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +13 -7
- data/lib/hecks/adapters/driving/github_webhook.rb +11 -8
- data/lib/hecks/behaviors/dsl.rb +17 -12
- data/lib/hecks/behaviors/expectations/boot.rb +81 -0
- data/lib/hecks/behaviors/expectations/checks.rb +178 -0
- data/lib/hecks/behaviors/expectations/dispatching.rb +93 -0
- data/lib/hecks/behaviors/expectations/qualify.rb +81 -0
- data/lib/hecks/behaviors/expectations.rb +39 -355
- data/lib/hecks/behaviors/rspec.rb +12 -12
- data/lib/hecks/behaviors/runner.rb +20 -11
- data/lib/hecks/bench/cli.rb +16 -13
- data/lib/hecks/bench/environment.rb +1 -1
- data/lib/hecks/bench/report.rb +11 -7
- data/lib/hecks/bench/ruby_runner.rb +13 -8
- data/lib/hecks/bench/rust_runner.rb +19 -11
- data/lib/hecks/bench/suite.rb +48 -20
- data/lib/hecks/bench/workload.rb +42 -31
- data/lib/hecks/bluebook/aggregate.rb +15 -21
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +18 -21
- data/lib/hecks/bluebook/assembly/build.rb +12 -7
- data/lib/hecks/bluebook/assembly/contracts/read_models.rb +70 -0
- data/lib/hecks/bluebook/assembly/contracts/rules.rb +84 -0
- data/lib/hecks/bluebook/assembly/contracts/sagas.rb +109 -0
- data/lib/hecks/bluebook/assembly/contracts/structure.rb +91 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +9 -319
- data/lib/hecks/bluebook/assembly/marks.rb +9 -8
- data/lib/hecks/bluebook/attribute.rb +13 -10
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -3
- data/lib/hecks/bluebook/behaviour/read_model.rb +26 -13
- data/lib/hecks/bluebook/chapter.rb +22 -14
- data/lib/hecks/bluebook/command.rb +14 -18
- data/lib/hecks/bluebook/domain_port.rb +11 -8
- data/lib/hecks/bluebook/dsl/aggregate_builder/correction_sealing.rb +78 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/draining.rb +74 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/query_field_sealing.rb +105 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/query_sealing.rb +121 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +128 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/rules.rb +84 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +61 -249
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +51 -285
- data/lib/hecks/bluebook/dsl/attribute_collector/identity_resolution.rb +113 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +58 -117
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +24 -19
- data/lib/hecks/bluebook/dsl/bluebook_builder/pending_givens.rb +109 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +105 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/event_shapes.rb +126 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/hop_tails.rb +79 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +76 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +65 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/query_hops.rb +123 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/references.rb +112 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +126 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +34 -595
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +18 -107
- data/lib/hecks/bluebook/dsl/command_builder/implicit_attributes.rb +132 -0
- data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +190 -0
- data/lib/hecks/bluebook/dsl/command_builder/owner.rb +22 -0
- data/lib/hecks/bluebook/dsl/command_builder/rules.rb +57 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +60 -360
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +19 -13
- data/lib/hecks/bluebook/dsl/entity_builder/rules.rb +96 -0
- data/lib/hecks/bluebook/dsl/entity_builder/scope.rb +25 -0
- data/lib/hecks/bluebook/dsl/entity_builder/sealing.rb +94 -0
- data/lib/hecks/bluebook/dsl/entity_builder.rb +35 -169
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +53 -24
- data/lib/hecks/bluebook/dsl/hecksagon_builder/chapter_scope.rb +133 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -97
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +73 -73
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +7 -3
- data/lib/hecks/bluebook/dsl/need_word.rb +1 -1
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +34 -29
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +57 -41
- data/lib/hecks/bluebook/dsl/query_builder.rb +12 -15
- data/lib/hecks/bluebook/dsl/read_model_builder/sealing.rb +116 -0
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +25 -102
- data/lib/hecks/bluebook/dsl/rule_reference.rb +26 -12
- data/lib/hecks/bluebook/dsl/translation_builder.rb +24 -14
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +29 -19
- data/lib/hecks/bluebook/dsl/word_gate.rb +34 -27
- data/lib/hecks/bluebook/entity.rb +13 -17
- data/lib/hecks/bluebook/expression/ast_json/emitters.rb +93 -0
- data/lib/hecks/bluebook/expression/ast_json/emitters.rb-e +88 -0
- data/lib/hecks/bluebook/expression/ast_json.rb +49 -76
- data/lib/hecks/bluebook/expression/ast_reader.rb +95 -28
- data/lib/hecks/bluebook/expression/canonical_form.rb +6 -26
- data/lib/hecks/bluebook/expression/evaluator/parser.rb +62 -0
- data/lib/hecks/bluebook/expression/evaluator/scanning.rb +122 -0
- data/lib/hecks/bluebook/expression/evaluator.rb +11 -111
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +28 -44
- data/lib/hecks/bluebook/expression/resolver/lookups.rb +77 -0
- data/lib/hecks/bluebook/expression/resolver/operations.rb +78 -0
- data/lib/hecks/bluebook/expression/resolver/parsing.rb +110 -0
- data/lib/hecks/bluebook/expression/resolver/scanning.rb +139 -0
- data/lib/hecks/bluebook/expression/resolver/values.rb +115 -0
- data/lib/hecks/bluebook/expression/resolver.rb +16 -414
- data/lib/hecks/bluebook/{hexagon.rb → hecksagon.rb} +22 -14
- data/lib/hecks/bluebook/keyword_fields.rb +42 -0
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +7 -6
- data/lib/hecks/bluebook/meta_validator/judge/cells.rb +99 -0
- data/lib/hecks/bluebook/meta_validator/judge/dispatching.rb +111 -0
- data/lib/hecks/bluebook/meta_validator/judge/identity.rb +108 -0
- data/lib/hecks/bluebook/meta_validator/judge/walking.rb +141 -0
- data/lib/hecks/bluebook/meta_validator/judge.rb +31 -376
- data/lib/hecks/bluebook/meta_validator/modes.rb +137 -0
- data/lib/hecks/bluebook/meta_validator/plan/category.rb +44 -0
- data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +73 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +38 -122
- data/lib/hecks/bluebook/meta_validator/readings/fields.rb +100 -0
- data/lib/hecks/bluebook/meta_validator/readings.rb +10 -95
- data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +89 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +96 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -151
- data/lib/hecks/bluebook/meta_validator/shapes/helpers.rb +83 -0
- data/lib/hecks/bluebook/meta_validator/shapes.rb +8 -75
- data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +77 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +31 -95
- data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +74 -0
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +15 -65
- data/lib/hecks/bluebook/meta_validator/verdict_cache/tagging.rb +63 -0
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +22 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +8 -4
- data/lib/hecks/bluebook/meta_validator.rb +59 -175
- data/lib/hecks/bluebook/model_check/lifecycle_checks.rb +122 -0
- data/lib/hecks/bluebook/model_check/policy_checks.rb +129 -0
- data/lib/hecks/bluebook/model_check/saga_checks.rb +134 -0
- data/lib/hecks/bluebook/model_check/verbs.rb +69 -0
- data/lib/hecks/bluebook/model_check.rb +73 -413
- data/lib/hecks/bluebook/pattern_subset/refusals.rb +54 -0
- data/lib/hecks/bluebook/pattern_subset/scan.rb +58 -0
- data/lib/hecks/bluebook/pattern_subset.rb +93 -134
- data/lib/hecks/bluebook/process_manager.rb +10 -9
- data/lib/hecks/bluebook/project_discovery.rb +10 -7
- data/lib/hecks/bluebook/project_register.rb +42 -41
- data/lib/hecks/bluebook/query.rb +19 -12
- data/lib/hecks/bluebook/read_model.rb +41 -39
- data/lib/hecks/bluebook/smoke_test.rb +51 -36
- data/lib/hecks/bluebook/synthesizer.rb +13 -5
- data/lib/hecks/bluebook/translation.rb +12 -12
- data/lib/hecks/bluebook.rb +1 -1
- data/lib/hecks/chapters.rb +32 -16
- data/lib/hecks/cli/behaviors.rb +22 -15
- data/lib/hecks/cli/check_era.rb +2 -2
- data/lib/hecks/cli/command_table.rb +72 -0
- data/lib/hecks/cli/console.rb +10 -7
- data/lib/hecks/cli/deploy_template_diff.rb +22 -9
- data/lib/hecks/cli/document.rb +14 -10
- data/lib/hecks/cli/domain_stub.rb +1 -1
- data/lib/hecks/cli/domain_writer.rb +1 -1
- data/lib/hecks/cli/expression_projection.rb +8 -6
- data/lib/hecks/cli/follow.rb +10 -4
- data/lib/hecks/cli/interview_aggregate.rb +132 -0
- data/lib/hecks/cli/interview_draft.rb +16 -200
- data/lib/hecks/cli/interview_record.rb +130 -0
- data/lib/hecks/cli/interview_run.rb +19 -8
- data/lib/hecks/cli/interview_session/agent_state.rb +70 -0
- data/lib/hecks/cli/interview_session/catalog.rb +76 -0
- data/lib/hecks/cli/interview_session/manual_findings.rb +48 -0
- data/lib/hecks/cli/interview_session/proposals.rb +90 -0
- data/lib/hecks/cli/interview_session.rb +8 -205
- data/lib/hecks/cli/interview_shape.rb +13 -6
- data/lib/hecks/cli/ir.rb +8 -11
- data/lib/hecks/cli/launcher_words.rb +168 -0
- data/lib/hecks/cli/model_check/examination.rb +93 -0
- data/lib/hecks/cli/model_check/sources.rb +57 -0
- data/lib/hecks/cli/model_check.rb +28 -134
- data/lib/hecks/cli/project_cli/launcher_source.rb +177 -0
- data/lib/hecks/cli/project_cli/templates.rb +106 -0
- data/lib/hecks/cli/project_cli.rb +57 -236
- data/lib/hecks/cli/project_diagrams.rb +26 -4
- data/lib/hecks/cli/project_glossary.rb +19 -9
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +29 -13
- data/lib/hecks/cli/release.rb +29 -22
- data/lib/hecks/cli/release_gem.rb +12 -6
- data/lib/hecks/cli/rspec_io_parallel_files.rb +87 -30
- data/lib/hecks/cli/rspec_shard_files.rb +24 -9
- data/lib/hecks/cli/run.rb +25 -44
- data/lib/hecks/cli/run_expectations.rb +63 -0
- data/lib/hecks/cli/seed_semantics_corpus.rb +37 -17
- data/lib/hecks/cli/smoke_http/checks.rb +66 -0
- data/lib/hecks/cli/smoke_http/settings.rb +63 -0
- data/lib/hecks/cli/smoke_http/transport.rb +45 -0
- data/lib/hecks/cli/smoke_http.rb +8 -142
- data/lib/hecks/cli/smoke_test.rb +18 -4
- data/lib/hecks/cli/stores.rb +7 -4
- data/lib/hecks/cli/stress_concurrency_specs/reporting.rb +44 -0
- data/lib/hecks/cli/stress_concurrency_specs/usage.rb +28 -0
- data/lib/hecks/cli/stress_concurrency_specs.rb +82 -80
- data/lib/hecks/cli.rb +32 -208
- data/lib/hecks/codemod/runner.rb +92 -0
- data/lib/hecks/codemod/sweep.rb +94 -0
- data/lib/hecks/codemod.rb +22 -165
- data/lib/hecks/corpus/routes.rb +34 -0
- data/lib/hecks/corpus/rust.rb +193 -0
- data/lib/hecks/corpus/sources.rb +46 -0
- data/lib/hecks/corpus.rb +28 -265
- data/lib/hecks/deploy/bluebook/deploy.bluebook +1510 -3
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +57 -0
- data/lib/hecks/deploy/oidc.json +225 -0
- data/lib/hecks/doc/reference/coverage.rb +70 -0
- data/lib/hecks/doc/reference/harvester.rb +55 -0
- data/lib/hecks/doc/reference/readme.rb +89 -0
- data/lib/hecks/doc/reference/rendering.rb +149 -0
- data/lib/hecks/doc/reference.rb +14 -273
- data/lib/hecks/doors/cli_door/nesting.rb +34 -0
- data/lib/hecks/doors/cli_door/shorthand.rb +85 -0
- data/lib/hecks/doors/cli_door.rb +23 -95
- data/lib/hecks/doors/cli_runner/answers.rb +138 -0
- data/lib/hecks/doors/cli_runner/resolution.rb +146 -0
- data/lib/hecks/doors/cli_runner/settling.rb +115 -0
- data/lib/hecks/doors/cli_runner/streaming.rb +90 -0
- data/lib/hecks/doors/cli_runner/suggestions.rb +43 -0
- data/lib/hecks/doors/cli_runner.rb +12 -336
- data/lib/hecks/doors/command_request.rb +42 -31
- data/lib/hecks/doors/handle.rb +32 -30
- data/lib/hecks/doors/launcher_options.rb +62 -7
- data/lib/hecks/doors/mcp_door/properties.rb +47 -0
- data/lib/hecks/doors/mcp_door/tool_calls.rb +113 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +51 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +69 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +97 -0
- data/lib/hecks/doors/mcp_door/tool_definitions.rb +15 -0
- data/lib/hecks/doors/mcp_door.rb +55 -301
- data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +92 -0
- data/lib/hecks/doors/mcp_door_scope/env_problems.rb +55 -0
- data/lib/hecks/doors/mcp_door_scope/presenter.rb +78 -0
- data/lib/hecks/doors/mcp_door_scope.rb +16 -172
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +1 -1
- data/lib/hecks/doors/ruby_door/chapter.rb +33 -16
- data/lib/hecks/doors/ruby_door.rb +14 -11
- data/lib/hecks/doors/usage_cache.rb +14 -8
- data/lib/hecks/doors.rb +10 -4
- data/lib/hecks/embryonaut_bluebook/manifest.rb +11 -3
- data/lib/hecks/embryonaut_bluebook/registry/changelog.rb +26 -0
- data/lib/hecks/embryonaut_bluebook/registry/versions.rb +27 -0
- data/lib/hecks/embryonaut_bluebook/registry.rb +27 -37
- data/lib/hecks/embryonaut_bluebook/vendor/acceptance.rb +37 -0
- data/lib/hecks/embryonaut_bluebook/vendor.rb +22 -36
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +9 -6
- data/lib/hecks/embryonaut_bluebook.rb +16 -11
- data/lib/hecks/engine_agreement.rb +24 -17
- data/lib/hecks/forms/app/commands.rb +98 -0
- data/lib/hecks/forms/app/queries.rb +62 -0
- data/lib/hecks/forms/app/records.rb +67 -0
- data/lib/hecks/forms/app/responses.rb +46 -0
- data/lib/hecks/forms/app.rb +33 -221
- data/lib/hecks/forms/banking_presentation.rb +5 -0
- data/lib/hecks/forms/command_form_renderer.rb +55 -14
- data/lib/hecks/forms/field_controls.rb +95 -0
- data/lib/hecks/forms/field_renderer.rb +34 -88
- data/lib/hecks/forms/field_shape.rb +9 -34
- data/lib/hecks/forms/html.rb +1 -1
- data/lib/hecks/forms/index_renderer.rb +14 -9
- data/lib/hecks/forms/page.rb +2 -106
- data/lib/hecks/forms/page_assets.rb +88 -0
- data/lib/hecks/forms/page_script.rb +28 -0
- data/lib/hecks/forms/params.rb +17 -8
- data/lib/hecks/forms/query_form_renderer.rb +11 -7
- data/lib/hecks/forms/record_renderer.rb +28 -19
- data/lib/hecks/forms/reference_options.rb +1 -1
- data/lib/hecks/forms/text_shape.rb +40 -0
- data/lib/hecks/fqn.rb +64 -32
- data/lib/hecks/framework.rb +10 -3
- data/lib/hecks/freezer.rb +10 -1
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions/fragments.rb +61 -0
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions/productions.rb +217 -0
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +5 -194
- data/lib/hecks/fuzzing/combination_miner.rb +23 -12
- data/lib/hecks/fuzzing/concurrent_dispatch/racing.rb +64 -0
- data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +66 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +31 -107
- data/lib/hecks/fuzzing/coverage_campaign.rb +7 -7
- data/lib/hecks/fuzzing/differential/wire_comparison.rb +74 -0
- data/lib/hecks/fuzzing/differential.rb +59 -84
- data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +70 -0
- data/lib/hecks/fuzzing/domain_generator/builder/attribute_shapes.rb +105 -0
- data/lib/hecks/fuzzing/domain_generator/builder/shapes.rb +97 -0
- data/lib/hecks/fuzzing/domain_generator/builder/wiring.rb +128 -0
- data/lib/hecks/fuzzing/domain_generator/builder.rb +105 -0
- data/lib/hecks/fuzzing/domain_generator/pruning.rb +90 -0
- data/lib/hecks/fuzzing/domain_generator/removals.rb +62 -0
- data/lib/hecks/fuzzing/domain_generator/rendering.rb +94 -0
- data/lib/hecks/fuzzing/domain_generator/tokens.rb +38 -0
- data/lib/hecks/fuzzing/domain_generator.rb +7 -555
- data/lib/hecks/fuzzing/era_boundary.rb +34 -24
- data/lib/hecks/fuzzing/form_census.rb +18 -8
- data/lib/hecks/fuzzing/generated_domain_check.rb +23 -11
- data/lib/hecks/fuzzing/isolated_boot/copying.rb +62 -0
- data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +133 -0
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +102 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +25 -252
- data/lib/hecks/fuzzing/persistence_parity.rb +5 -5
- data/lib/hecks/fuzzing/properties/aggregation_recompute.rb +121 -0
- data/lib/hecks/fuzzing/properties/catalog.rb +138 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +23 -20
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +64 -185
- data/lib/hecks/fuzzing/properties/group_by_recompute.rb +69 -0
- data/lib/hecks/fuzzing/properties/guards.rb +76 -108
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +66 -227
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +46 -35
- data/lib/hecks/fuzzing/properties/mutation_recompute.rb +162 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +41 -24
- data/lib/hecks/fuzzing/properties/piece_invariants.rb +61 -0
- data/lib/hecks/fuzzing/properties/policy_wiring.rb +140 -0
- data/lib/hecks/fuzzing/properties/query_rows.rb +67 -0
- data/lib/hecks/fuzzing/properties/querying.rb +69 -90
- data/lib/hecks/fuzzing/properties/references.rb +100 -0
- data/lib/hecks/fuzzing/properties/tenant_scope.rb +84 -0
- data/lib/hecks/fuzzing/properties.rb +6 -119
- data/lib/hecks/fuzzing/qa_settings.rb +23 -17
- data/lib/hecks/fuzzing/replay/fan_out.rb +78 -0
- data/lib/hecks/fuzzing/replay/filters.rb +72 -0
- data/lib/hecks/fuzzing/replay/guard_check.rb +88 -0
- data/lib/hecks/fuzzing/replay/mutation_trace.rb +117 -0
- data/lib/hecks/fuzzing/replay/observation.rb +60 -0
- data/lib/hecks/fuzzing/replay/read_only_steps.rb +84 -0
- data/lib/hecks/fuzzing/replay/session.rb +151 -0
- data/lib/hecks/fuzzing/replay.rb +35 -442
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +3 -4
- data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +133 -0
- data/lib/hecks/fuzzing/self_consistency/sagas.rb +93 -0
- data/lib/hecks/fuzzing/self_consistency/value_objects.rb +87 -0
- data/lib/hecks/fuzzing/self_consistency.rb +8 -213
- data/lib/hecks/fuzzing/sequence_generator/adversary/argument_mutations.rb +116 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/caller_draw.rb +68 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/identity_mutations.rb +62 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/precedence_mutations.rb +126 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +23 -283
- data/lib/hecks/fuzzing/sequence_generator/argument_drawing.rb +78 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +69 -53
- data/lib/hecks/fuzzing/sequence_generator/identity_shaping.rb +85 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +20 -16
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +12 -6
- data/lib/hecks/fuzzing/sequence_generator/prefixing.rb +45 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +19 -8
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +43 -144
- data/lib/hecks/fuzzing/sequence_generator.rb +65 -63
- data/lib/hecks/fuzzing/shrinker.rb +33 -29
- data/lib/hecks/fuzzing/target_capabilities.rb +10 -4
- data/lib/hecks/fuzzing/value_generator.rb +27 -17
- data/lib/hecks/gate/stages.yml +10 -0
- data/lib/hecks/grammar/evolve/arguments.rb +90 -0
- data/lib/hecks/grammar/evolve/keywords.rb +81 -0
- data/lib/hecks/grammar/evolve/seeds.rb +172 -0
- data/lib/hecks/grammar/evolve.rb +22 -263
- data/lib/hecks/grammar/operators.rb +111 -0
- data/lib/hecks/grammar.rb +53 -126
- data/lib/hecks/hecks/adapters/bluebook_report.rb +91 -0
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +23 -9
- data/lib/hecks/hecks/adapters/codebase/language/edits.rb +75 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +30 -72
- data/lib/hecks/hecks/adapters/codebase/promotion/candidates.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/gate.rb +50 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/move.rb +70 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/standing.rb +88 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/watch.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/promotion.rb +115 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +31 -12
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +43 -6
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +16 -5
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +9 -1
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/style.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +11 -5
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +27 -8
- data/lib/hecks/hecks/adapters/console_capture.rb +21 -17
- data/lib/hecks/hecks/adapters/cost_explorer.rb +11 -6
- data/lib/hecks/hecks/adapters/deploy_plans.rb +49 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain/answers.rb +141 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain/scripts.rb +95 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +74 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +122 -59
- data/lib/hecks/hecks/adapters/finding_github.rb +2 -2
- data/lib/hecks/hecks/adapters/first_admin.rb +22 -8
- data/lib/hecks/hecks/adapters/git.rb +18 -5
- data/lib/hecks/hecks/adapters/git_refs.rb +144 -0
- data/lib/hecks/hecks/adapters/github_rulesets.rb +126 -0
- data/lib/hecks/hecks/adapters/host_http.rb +16 -6
- data/lib/hecks/hecks/adapters/in_process_boot.rb +9 -5
- data/lib/hecks/hecks/adapters/in_process_operations/tailing.rb +61 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +39 -37
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +21 -15
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +29 -12
- data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +52 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +52 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +5 -62
- data/lib/hecks/hecks/adapters/local_files.rb +27 -10
- data/lib/hecks/hecks/adapters/pg_admin/ownership.rb +115 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +14 -87
- data/lib/hecks/hecks/adapters/process_pool.rb +54 -22
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +12 -4
- data/lib/hecks/hecks/adapters/site_toolchain.rb +19 -10
- data/lib/hecks/hecks/adapters/terminal.rb +13 -9
- data/lib/hecks/hecks/codebase.bluebook +322 -5
- data/lib/hecks/hecks/custodian.bluebook +12 -2
- data/lib/hecks/hecks/hecks.hecksagon +73 -0
- data/lib/hecks/hecks/hecks.world +15 -3
- data/lib/hecks/kernel_capabilities/templates.rb +92 -0
- data/lib/hecks/kernel_capabilities.rb +18 -85
- data/lib/hecks/language/bluebook/vocabulary.bluebook +43 -1
- data/lib/hecks/literal/item_splitter.rb +50 -0
- data/lib/hecks/literal.rb +29 -38
- data/lib/hecks/mcp_stdio_guard.rb +8 -8
- data/lib/hecks/naming.rb +9 -3
- data/lib/hecks/persistence_legacy_fixture/postgres_stores.rb +81 -0
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +26 -66
- data/lib/hecks/persistence_legacy_fixture.rb +13 -10
- data/lib/hecks/ports/access_control.rb +13 -10
- data/lib/hecks/ports/agent/answers.rb +2 -2
- data/lib/hecks/ports/agent.rb +13 -10
- data/lib/hecks/ports/authentication.rb +13 -10
- data/lib/hecks/ports/authorization.rb +13 -10
- data/lib/hecks/ports/clock.rb +13 -10
- data/lib/hecks/ports/extraction.rb +13 -12
- data/lib/hecks/ports/identity_assignment.rb +13 -10
- data/lib/hecks/ports/identity_generation.rb +13 -10
- data/lib/hecks/ports/identity_resolution.rb +13 -10
- data/lib/hecks/ports/key_vault.rb +13 -10
- data/lib/hecks/ports/persistence/append_only.rb +5 -5
- data/lib/hecks/ports/persistence/binding_policy.rb +33 -9
- data/lib/hecks/ports/persistence/codec_boundary.rb +22 -11
- data/lib/hecks/ports/persistence/constants.rb +10 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +18 -16
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +27 -18
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +52 -23
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +14 -8
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +17 -6
- data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +58 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +130 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +25 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +20 -180
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +41 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/class_methods.rb +105 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/dialect.rb +137 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +25 -28
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/head_writes.rb +62 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/journal.rb +128 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +74 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/chain_sql.rb +169 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +91 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_integrity.rb +99 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +0 -73
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +55 -39
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +51 -222
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/merge_writes.rb +120 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +85 -60
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +97 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +19 -19
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/sql_templates.rb +88 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +77 -118
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +3 -117
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_sql.rb +116 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +3 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/context.rb +38 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +43 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +62 -38
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +21 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +66 -86
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +75 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +27 -9
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/query_phases.rb +63 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/sagas.rb +78 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +28 -482
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +40 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +22 -15
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +39 -19
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -16
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +48 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +60 -99
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/path_diff.rb +57 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +21 -11
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +13 -4
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +4 -2
- data/lib/hecks/ports/persistence/postgres_dump.rb +13 -7
- data/lib/hecks/ports/persistence/repository_factory.rb +35 -11
- data/lib/hecks/ports/persistence/state_codec.rb +10 -0
- data/lib/hecks/ports/persistence.rb +1 -10
- data/lib/hecks/ports/projection.rb +34 -21
- data/lib/hecks/ports/query/in_memory.rb +16 -8
- data/lib/hecks/projection_files/expression_tables.rb +64 -0
- data/lib/hecks/projection_files/texts.rb +67 -0
- data/lib/hecks/projection_files.rb +19 -103
- data/lib/hecks/projections/bootstrap_table.rb +43 -29
- data/lib/hecks/projections/deploy/bastion_lines.rb +32 -0
- data/lib/hecks/projections/deploy/box/access.rb +73 -0
- data/lib/hecks/projections/deploy/box/caddy.rb +87 -0
- data/lib/hecks/projections/deploy/box/compose.rb +70 -0
- data/lib/hecks/projections/deploy/box/hosting.rb +16 -108
- data/lib/hecks/projections/deploy/box/hosting_parts.rb +97 -0
- data/lib/hecks/projections/deploy/box/hosting_settings.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_recipe.rb +62 -0
- data/lib/hecks/projections/deploy/box/roll_scripts.rb +135 -0
- data/lib/hecks/projections/deploy/box/settings/checks.rb +38 -0
- data/lib/hecks/projections/deploy/box/settings/containers.rb +123 -0
- data/lib/hecks/projections/deploy/box/settings/origin.rb +56 -0
- data/lib/hecks/projections/deploy/box/settings/patterns.rb +43 -0
- data/lib/hecks/projections/deploy/box/settings/types.rb +72 -0
- data/lib/hecks/projections/deploy/box/settings.rb +58 -263
- data/lib/hecks/projections/deploy/box/stack_yaml.rb +107 -0
- data/lib/hecks/projections/deploy/box/templates/MIGRATION.md.tmpl +39 -0
- data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +24 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +51 -4
- data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +4 -3
- data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +16 -4
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +8 -7
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef.part +1 -1
- data/lib/hecks/projections/deploy/box/templates/deploy-usage-services.tmpl +4 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-usage-taskdef.tmpl +5 -0
- data/lib/hecks/projections/deploy/box/templates/ecr-repository.yaml.tmpl +9 -0
- data/lib/hecks/projections/deploy/box/templates/hosting.mk.tmpl +6 -3
- data/lib/hecks/projections/deploy/box/templates/mode-summary-services.tmpl +2 -0
- data/lib/hecks/projections/deploy/box/templates/mode-summary-taskdef.tmpl +4 -0
- data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +8 -3
- data/lib/hecks/projections/deploy/box/templates/services-block.tmpl +9 -0
- data/lib/hecks/projections/deploy/box/templates/tunnel-egress.yaml.tmpl +11 -0
- data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +2 -2
- data/lib/hecks/projections/deploy/box/templates/writable-secrets.yaml.tmpl +7 -0
- data/lib/hecks/projections/deploy/box.rb +37 -503
- data/lib/hecks/projections/deploy/fargate/assembly.rb +13 -142
- data/lib/hecks/projections/deploy/fargate/cdn/behaviors.rb +76 -0
- data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +112 -0
- data/lib/hecks/projections/deploy/fargate/cdn/options.rb +85 -0
- data/lib/hecks/projections/deploy/fargate/cdn.rb +23 -215
- data/lib/hecks/projections/deploy/fargate/check.rb +16 -6
- data/lib/hecks/projections/deploy/fargate/containers/definition_lines.rb +61 -0
- data/lib/hecks/projections/deploy/fargate/containers/reading.rb +86 -0
- data/lib/hecks/projections/deploy/fargate/containers/rendering.rb +132 -0
- data/lib/hecks/projections/deploy/fargate/containers/routing.rb +93 -0
- data/lib/hecks/projections/deploy/fargate/containers.rb +10 -286
- data/lib/hecks/projections/deploy/fargate/extras/reading.rb +90 -0
- data/lib/hecks/projections/deploy/fargate/extras/rendering.rb +81 -0
- data/lib/hecks/projections/deploy/fargate/extras.rb +9 -158
- data/lib/hecks/projections/deploy/fargate/monitoring/alarms.rb +115 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/reading.rb +84 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/topic.rb +59 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/warmer.rb +90 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/warmer_roles.rb +76 -0
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +14 -348
- data/lib/hecks/projections/deploy/fargate/sections.rb +115 -0
- data/lib/hecks/projections/deploy/fargate/settings/ids.rb +55 -0
- data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +77 -0
- data/lib/hecks/projections/deploy/fargate/settings.rb +17 -104
- data/lib/hecks/projections/deploy/fargate/stack/blocks.rb +91 -0
- data/lib/hecks/projections/deploy/fargate/stack/readers.rb +87 -0
- data/lib/hecks/projections/deploy/fargate/stack/recipes.rb +106 -0
- data/lib/hecks/projections/deploy/fargate/stack.rb +146 -0
- data/lib/hecks/projections/deploy/fargate/task_sections.rb +56 -0
- data/lib/hecks/projections/deploy/fargate/yaml.rb +1 -1
- data/lib/hecks/projections/deploy/fargate.rb +51 -756
- data/lib/hecks/projections/deploy/lambda/pii.rb +49 -0
- data/lib/hecks/projections/deploy/lambda/stack/blocks.rb +118 -0
- data/lib/hecks/projections/deploy/lambda/stack/checks.rb +64 -0
- data/lib/hecks/projections/deploy/lambda/stack/deploy_chain.rb +119 -0
- data/lib/hecks/projections/deploy/lambda/stack/readers.rb +62 -0
- data/lib/hecks/projections/deploy/lambda/stack/reading.rb +170 -0
- data/lib/hecks/projections/deploy/lambda/stack/reading_web.rb +53 -0
- data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +112 -0
- data/lib/hecks/projections/deploy/lambda/stack/web.rb +57 -0
- data/lib/hecks/projections/deploy/lambda/stack.rb +54 -0
- data/lib/hecks/projections/deploy/lambda.rb +77 -1885
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +8 -74
- data/lib/hecks/projections/deploy/preview/containers.rb +18 -7
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +15 -87
- data/lib/hecks/projections/deploy/preview/settings.rb +7 -4
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +42 -106
- data/lib/hecks/projections/deploy/preview/template.rb +11 -106
- data/lib/hecks/projections/deploy/preview/yaml_text.rb +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/settings.rb +14 -6
- data/lib/hecks/projections/deploy/scripts.rb +11 -9
- data/lib/hecks/projections/deploy/shared/rows.rb +48 -0
- data/lib/hecks/projections/deploy/shared.rb +89 -449
- data/lib/hecks/projections/deploy/smoke.rb +15 -10
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +21 -147
- data/lib/hecks/projections/deploy/template_diff/normalizer.rb +60 -0
- data/lib/hecks/projections/deploy/template_diff/value_diff.rb +136 -0
- data/lib/hecks/projections/deploy/template_diff.rb +8 -3
- data/lib/hecks/projections/deploy/templates/fargate/Dockerfile.tmpl +28 -0
- data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +63 -0
- data/lib/hecks/projections/deploy/templates/fargate/always_params.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/fargate/deploy_plain.tmpl +1 -0
- data/lib/hecks/projections/deploy/templates/fargate/deploy_shared.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/fargate/mint_era_own.tmpl +44 -0
- data/lib/hecks/projections/deploy/templates/fargate/mint_era_shared.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/fargate/missing_owner.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_params.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_task_env.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_task_policy.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/fargate/owning_params.tmpl +33 -0
- data/lib/hecks/projections/deploy/templates/fargate/template.yaml.tmpl +281 -0
- data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +218 -0
- data/lib/hecks/projections/deploy/templates/lambda/aurora_depends.tmpl +18 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_dispatch_none.tmpl +10 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_pg.tmpl +15 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_plain.tmpl +2 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_web.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/lambda/env_blind_guard.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/lambda/mint_era_own.tmpl +122 -0
- data/lib/hecks/projections/deploy/templates/lambda/mint_era_shared.tmpl +47 -0
- data/lib/hecks/projections/deploy/templates/lambda/missing_owner.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +14 -0
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_plain.tmpl +3 -0
- data/lib/hecks/projections/deploy/templates/lambda/oauth_note.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/params_oauth.tmpl +13 -0
- data/lib/hecks/projections/deploy/templates/lambda/params_shared.tmpl +33 -0
- data/lib/hecks/projections/deploy/templates/lambda/pg_native.tmpl +71 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_oac.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_permission.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_resources.tmpl +116 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge.tmpl +30 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_oauth.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_plain.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/rename_schema_own.tmpl +93 -0
- data/lib/hecks/projections/deploy/templates/lambda/rename_schema_shared.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_env.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_policy.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_session_secret.tmpl +13 -0
- data/lib/hecks/projections/deploy/templates/lambda/samconfig.toml.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/shared_note.tmpl +6 -0
- data/lib/hecks/projections/deploy/templates/lambda/sync_oauth.tmpl +23 -0
- data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +187 -0
- data/lib/hecks/projections/deploy/templates/lambda/translation_own.tmpl +46 -0
- data/lib/hecks/projections/deploy/templates/lambda/translation_shared.tmpl +2 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_function.tmpl +207 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_google_oauth_env.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_no_oauth_env.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_oauth_policy.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/lambda/webhook_secret_resource.tmpl +20 -0
- data/lib/hecks/projections/deploy/templates/preview/alb.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/preview/alb_security_group.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/assume_role.tmpl +6 -0
- data/lib/hecks/projections/deploy/templates/preview/base_parameters.tmpl +24 -0
- data/lib/hecks/projections/deploy/templates/preview/cluster.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/preview/container_secret.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_script.sh.tmpl +23 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_secrets.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_task.tmpl +39 -0
- data/lib/hecks/projections/deploy/templates/preview/desired_count.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/distribution.tmpl +24 -0
- data/lib/hecks/projections/deploy/templates/preview/execution_role.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/preview/header.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/preview/ingress.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/preview/listener.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/listener_rule.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/log_group.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/log_options.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/outputs.tmpl +14 -0
- data/lib/hecks/projections/deploy/templates/preview/service.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/preview/session_secret.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/target_group.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/task_definition.tmpl +15 -0
- data/lib/hecks/projections/deploy/templates/preview/task_role.tmpl +22 -0
- data/lib/hecks/projections/deploy/templates/shared/aurora_db.tmpl +52 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion.tmpl +74 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion_own_public.tmpl +41 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion_reuse_public.tmpl +10 -0
- data/lib/hecks/projections/deploy/templates/shared/nat_gateway.tmpl +102 -0
- data/lib/hecks/projections/deploy/templates/shared/oauth_egress.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/shared/plain_db.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/shared/vpc_and_database.tmpl +67 -0
- data/lib/hecks/projections/deploy/text_template.rb +35 -0
- data/lib/hecks/projections/diagrams/dispatch.rb +114 -0
- data/lib/hecks/projections/diagrams/statecharts.rb +59 -0
- data/lib/hecks/projections/diagrams/structure.rb +114 -0
- data/lib/hecks/projections/diagrams.rb +33 -256
- data/lib/hecks/projections/glossary/entries.rb +140 -0
- data/lib/hecks/projections/glossary/html/page.rb +96 -0
- data/lib/hecks/projections/glossary/html/parser.rb +66 -0
- data/lib/hecks/projections/glossary/html/sections.rb +78 -0
- data/lib/hecks/projections/glossary/html.rb +7 -179
- data/lib/hecks/projections/glossary/index.rb +45 -0
- data/lib/hecks/projections/glossary/markdown.rb +22 -11
- data/lib/hecks/projections/glossary/mermaid.rb +44 -31
- data/lib/hecks/projections/glossary/sensitivity.rb +7 -4
- data/lib/hecks/projections/glossary/sentences/value_objects.rb +77 -0
- data/lib/hecks/projections/glossary/sentences.rb +42 -81
- data/lib/hecks/projections/glossary/slugs.rb +33 -0
- data/lib/hecks/projections/glossary.rb +22 -190
- data/lib/hecks/projections/model.rb +20 -14
- data/lib/hecks/projections/rust_vocabulary/arguments/support.rb +33 -0
- data/lib/hecks/projections/rust_vocabulary/arguments.rb +171 -0
- data/lib/hecks/projections/rust_vocabulary/enum_body.rb +114 -0
- data/lib/hecks/projections/rust_vocabulary/tests.rb +144 -0
- data/lib/hecks/projections/rust_vocabulary.rb +24 -293
- data/lib/hecks/projections/site/admin.rb +146 -0
- data/lib/hecks/projections/site/admin_cms/templates/membership.rb +115 -0
- data/lib/hecks/projections/site/admin_cms/templates/session_strategy.rb +90 -0
- data/lib/hecks/projections/site/admin_cms/templates/sso.rb +101 -0
- data/lib/hecks/projections/site/admin_cms/templates/sso_tail.rb +54 -0
- data/lib/hecks/projections/site/admin_cms/templates/users.rb +83 -0
- data/lib/hecks/projections/site/admin_cms/templates.rb +33 -0
- data/lib/hecks/projections/site/admin_cms.rb +78 -0
- data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
- data/lib/hecks/projections/site/edge/checks.rb +30 -80
- data/lib/hecks/projections/site/edge/findings.rb +28 -0
- data/lib/hecks/projections/site/edge/route_checks.rb +110 -0
- data/lib/hecks/projections/site/edge/row_reader.rb +52 -0
- data/lib/hecks/projections/site/edge/rules.rb +28 -26
- data/lib/hecks/projections/site/edge.rb +20 -31
- data/lib/hecks/projections/site/live_edge.rb +9 -7
- data/lib/hecks/projections/site/payload/fields/definitions.rb +90 -0
- data/lib/hecks/projections/site/payload/fields/readers.rb +69 -0
- data/lib/hecks/projections/site/payload/fields.rb +137 -0
- data/lib/hecks/projections/site/payload/lifecycle/text.rb +84 -0
- data/lib/hecks/projections/site/payload/lifecycle/text_tail.rb +106 -0
- data/lib/hecks/projections/site/payload/lifecycle.rb +33 -0
- data/lib/hecks/projections/site/payload/model.rb +128 -0
- data/lib/hecks/projections/site/payload/specs/wire.rb +69 -0
- data/lib/hecks/projections/site/payload/specs.rb +135 -0
- data/lib/hecks/projections/site/payload_driver.rb +95 -0
- data/lib/hecks/projections/site/root_rows.rb +67 -0
- data/lib/hecks/projections/site/routes_ts/helpers.rb +79 -0
- data/lib/hecks/projections/site/routes_ts/listings.rb +75 -0
- data/lib/hecks/projections/site/routes_ts/navigation.rb +79 -0
- data/lib/hecks/projections/site/routes_ts.rb +27 -175
- data/lib/hecks/projections/site/site_admin/access.rb +104 -0
- data/lib/hecks/projections/site/site_admin/session.rb +127 -0
- data/lib/hecks/projections/site/site_admin.rb +85 -0
- data/lib/hecks/projections/site/site_cdn.rb +12 -7
- data/lib/hecks/projections/site/site_host/dockerfile.rb +75 -0
- data/lib/hecks/projections/site/site_host/templates.rb +109 -0
- data/lib/hecks/projections/site/site_host.rb +58 -0
- data/lib/hecks/projections/site/site_root/workflow.rb +65 -0
- data/lib/hecks/projections/site/site_root.rb +128 -0
- data/lib/hecks/projections/site/table/checks.rb +28 -57
- data/lib/hecks/projections/site/table/link_builder.rb +14 -5
- data/lib/hecks/projections/site/table/navigation_checks.rb +75 -0
- data/lib/hecks/projections/site/table/row_builder.rb +31 -53
- data/lib/hecks/projections/site/table/row_defaults.rb +65 -0
- data/lib/hecks/projections/site/table.rb +9 -5
- data/lib/hecks/projections/vocabulary.rb +34 -31
- data/lib/hecks/projector/cli_audience.rb +42 -0
- data/lib/hecks/projector/cli_projector/claims.rb +149 -0
- data/lib/hecks/projector/cli_projector/command_help.rb +65 -0
- data/lib/hecks/projector/cli_projector/command_specs.rb +133 -0
- data/lib/hecks/projector/cli_projector/listing.rb +100 -0
- data/lib/hecks/projector/cli_projector/option_specs.rb +116 -0
- data/lib/hecks/projector/cli_projector/query_specs.rb +67 -0
- data/lib/hecks/projector/cli_projector/usage.rb +101 -0
- data/lib/hecks/projector/cli_projector.rb +15 -532
- data/lib/hecks/projector/docs_projector/attributes.rb +78 -0
- data/lib/hecks/projector/docs_projector/behaviour.rb +127 -0
- data/lib/hecks/projector/docs_projector/closing.rb +40 -0
- data/lib/hecks/projector/docs_projector.rb +58 -192
- data/lib/hecks/projector/exporter/bindings.rb +174 -0
- data/lib/hecks/projector/exporter/translations.rb +127 -0
- data/lib/hecks/projector/exporter.rb +8 -279
- data/lib/hecks/projector/narrate_projector/commands.rb +108 -0
- data/lib/hecks/projector/narrate_projector/reactions.rb +33 -0
- data/lib/hecks/projector/narrate_projector.rb +60 -160
- data/lib/hecks/projector.rb +22 -13
- data/lib/hecks/quality_control/adapters/agent_profile.rb +25 -16
- data/lib/hecks/quality_control/adapters/github_checks.rb +42 -6
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +1 -1
- data/lib/hecks/quality_control/adapters/github_issues.rb +22 -10
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/parsing.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/reporting.rb +44 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +119 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +28 -155
- data/lib/hecks/quality_control/cli/qa_domain_novelty/verdict.rb +76 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +33 -66
- data/lib/hecks/quality_control/cli/qa_generated_domains/arguments.rb +62 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/blueprints.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/reporting.rb +97 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/shrinking.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +43 -327
- data/lib/hecks/quality_control/cli/qa_log_bug/arguments.rb +55 -0
- data/lib/hecks/quality_control/cli/qa_log_bug/proof.rb +65 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +18 -81
- data/lib/hecks/quality_control/cli/qa_mine_combinations/arguments.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations/booting.rb +96 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +45 -109
- data/lib/hecks/quality_control/cli/qa_open_pr/arguments.rb +55 -0
- data/lib/hecks/quality_control/cli/qa_open_pr/recording.rb +79 -0
- data/lib/hecks/quality_control/cli/qa_open_pr/rules.rb +122 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +41 -200
- data/lib/hecks/quality_control/cli/qa_postgres_migrate/copying.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate/reporting.rb +33 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +37 -63
- data/lib/hecks/quality_control/cli/qa_postgres_role/ownership.rb +57 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +66 -71
- data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +118 -0
- data/lib/hecks/quality_control/cli/qa_pr_check/reporting.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +28 -145
- data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +80 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +13 -86
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +80 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode/report.rb +125 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +63 -193
- data/lib/hecks/quality_control/cli/qa_sweep/checks/boundary.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/engines.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/seeds.rb +86 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +10 -248
- data/lib/hecks/quality_control/cli/qa_sweep/conclusion.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep/depth.rb +61 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +26 -13
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report/shrunk.rb +42 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +40 -41
- data/lib/hecks/quality_control/cli/qa_sweep/parsing/validation.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +35 -65
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +41 -22
- data/lib/hecks/quality_control/cli/qa_sweep/scratch.rb +67 -0
- data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +94 -0
- data/lib/hecks/quality_control/cli/qa_sweep/seed_loop.rb +149 -0
- data/lib/hecks/quality_control/cli/qa_sweep/target_setup.rb +115 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +22 -445
- data/lib/hecks/quality_control/cli/qa_tick/output.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_tick/preflight.rb +95 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +42 -175
- data/lib/hecks/query_ir/formatting.rb +86 -0
- data/lib/hecks/query_ir/rules.rb +132 -0
- data/lib/hecks/query_ir/touchpoints.rb +104 -0
- data/lib/hecks/query_ir.rb +33 -281
- data/lib/hecks/query_ir_mcp/tools.rb +68 -0
- data/lib/hecks/query_ir_mcp.rb +27 -71
- data/lib/hecks/query_specification/common/comparison.rb +25 -5
- data/lib/hecks/query_specification/common/dsl.rb +1 -1
- data/lib/hecks/query_specification/common/null_policy.rb +9 -6
- data/lib/hecks/query_specification/common/options.rb +21 -14
- data/lib/hecks/query_specification/field_path.rb +5 -2
- data/lib/hecks/query_specification/hop_path.rb +15 -18
- data/lib/hecks/release/lane.rb +22 -0
- data/lib/hecks/release/runner/clean_tree.rb +2 -2
- data/lib/hecks/release/runner/commands.rb +1 -1
- data/lib/hecks/release/runner/options.rb +82 -0
- data/lib/hecks/release/runner/preflight.rb +12 -7
- data/lib/hecks/release/runner/publishing.rb +86 -0
- data/lib/hecks/release/runner/tagger.rb +8 -3
- data/lib/hecks/release/runner.rb +40 -156
- data/lib/hecks/rendering.rb +13 -9
- data/lib/hecks/router/door.rb +37 -0
- data/lib/hecks/router/namespace_installer.rb +45 -83
- data/lib/hecks/router/options_proxy.rb +44 -0
- data/lib/hecks/runtime/adapter_lookup.rb +45 -24
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -8
- data/lib/hecks/runtime/command_interpreter/delegation.rb +116 -0
- data/lib/hecks/runtime/command_interpreter/enforcement.rb +38 -0
- data/lib/hecks/runtime/command_interpreter/hydration.rb +139 -0
- data/lib/hecks/runtime/command_interpreter/list_mutations.rb +98 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +67 -114
- data/lib/hecks/runtime/command_interpreter/persisting.rb +96 -0
- data/lib/hecks/runtime/command_interpreter.rb +57 -352
- data/lib/hecks/runtime/command_rules/admissibility.rb +64 -147
- data/lib/hecks/runtime/command_rules/arithmetic.rb +13 -72
- data/lib/hecks/runtime/command_rules/authorization.rb +9 -9
- data/lib/hecks/runtime/command_rules/emission.rb +13 -14
- data/lib/hecks/runtime/command_rules/guard_state.rb +49 -0
- data/lib/hecks/runtime/command_rules/invariants.rb +84 -0
- data/lib/hecks/runtime/command_rules/operands.rb +88 -0
- data/lib/hecks/runtime/command_rules/references.rb +59 -57
- data/lib/hecks/runtime/command_rules/tenant_boundary.rb +69 -0
- data/lib/hecks/runtime/dependency_planning/analyzer.rb +90 -0
- data/lib/hecks/runtime/dependency_planning/expression_reads.rb +73 -0
- data/lib/hecks/runtime/dependency_planning/mutation_analysis.rb +89 -0
- data/lib/hecks/runtime/dependency_planning/rule_analysis.rb +82 -0
- data/lib/hecks/runtime/dependency_planning.rb +3 -250
- data/lib/hecks/runtime/dispatcher/queries.rb +62 -0
- data/lib/hecks/runtime/dispatcher/result.rb +55 -0
- data/lib/hecks/runtime/dispatcher/routing.rb +107 -0
- data/lib/hecks/runtime/dispatcher.rb +64 -209
- data/lib/hecks/runtime/entity_element/location.rb +124 -0
- data/lib/hecks/runtime/entity_element/mutations.rb +150 -0
- data/lib/hecks/runtime/entity_element.rb +5 -177
- data/lib/hecks/runtime/entity_interpreter/enforcement.rb +51 -0
- data/lib/hecks/runtime/entity_interpreter/locating.rb +62 -0
- data/lib/hecks/runtime/entity_interpreter/resolution.rb +42 -0
- data/lib/hecks/runtime/entity_interpreter/saving.rb +49 -0
- data/lib/hecks/runtime/entity_interpreter.rb +45 -164
- data/lib/hecks/runtime/identity.rb +15 -9
- data/lib/hecks/runtime/instance.rb +11 -7
- data/lib/hecks/runtime/interpreting.rb +16 -8
- data/lib/hecks/runtime/invocation.rb +3 -155
- data/lib/hecks/runtime/invocation_builder.rb +132 -0
- data/lib/hecks/runtime/invocation_facts.rb +87 -0
- data/lib/hecks/runtime/loader/boot_steps.rb +96 -0
- data/lib/hecks/runtime/loader/described.rb +27 -0
- data/lib/hecks/runtime/loader.rb +27 -114
- data/lib/hecks/runtime/outbox/consumer_runner.rb +40 -0
- data/lib/hecks/runtime/outbox/fanout.rb +82 -0
- data/lib/hecks/runtime/outbox/relay.rb +149 -0
- data/lib/hecks/runtime/outbox.rb +3 -214
- data/lib/hecks/runtime/policy_interpreter/arguments.rb +67 -0
- data/lib/hecks/runtime/policy_interpreter/fan_out.rb +96 -0
- data/lib/hecks/runtime/policy_interpreter.rb +22 -137
- data/lib/hecks/runtime/port_operation_interpreter.rb +18 -17
- data/lib/hecks/runtime/query_interpreter/arguments.rb +51 -0
- data/lib/hecks/runtime/query_interpreter/entity_rows.rb +82 -0
- data/lib/hecks/runtime/query_interpreter/outside_answer.rb +89 -0
- data/lib/hecks/runtime/query_interpreter.rb +43 -191
- data/lib/hecks/runtime/reaction_invocation/identities.rb +92 -0
- data/lib/hecks/runtime/reaction_invocation/target_resolution.rb +88 -0
- data/lib/hecks/runtime/reaction_invocation.rb +66 -183
- data/lib/hecks/runtime/reaction_outcome.rb +7 -3
- data/lib/hecks/runtime/read_model_interpreter/head_ordering.rb +49 -0
- data/lib/hecks/runtime/read_model_interpreter/reductions.rb +123 -0
- data/lib/hecks/runtime/read_model_interpreter/shaping.rb +100 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +71 -214
- data/lib/hecks/runtime/reference_hop.rb +11 -11
- data/lib/hecks/runtime/refusal_wording.rb +11 -8
- data/lib/hecks/runtime/registry/chapter_verification.rb +84 -0
- data/lib/hecks/runtime/registry/declarations.rb +17 -0
- data/lib/hecks/runtime/registry/durability_warnings.rb +71 -0
- data/lib/hecks/runtime/registry/hecksagon_rules.rb +124 -0
- data/lib/hecks/runtime/registry/merging.rb +49 -0
- data/lib/hecks/runtime/registry/providers.rb +139 -0
- data/lib/hecks/runtime/registry/query_verification.rb +144 -0
- data/lib/hecks/runtime/registry/read_repository.rb +61 -0
- data/lib/hecks/runtime/registry/runtime_state.rb +27 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +12 -8
- data/lib/hecks/runtime/registry/verification.rb +45 -389
- data/lib/hecks/runtime/registry/world_defaults.rb +3 -3
- data/lib/hecks/runtime/registry.rb +58 -296
- data/lib/hecks/runtime/remote_dispatcher.rb +47 -31
- data/lib/hecks/runtime/saga_interpreter/compensation.rb +90 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +19 -10
- data/lib/hecks/runtime/saga_interpreter/delivery.rb +147 -0
- data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +63 -0
- data/lib/hecks/runtime/saga_interpreter/transitions.rb +112 -0
- data/lib/hecks/runtime/saga_interpreter.rb +41 -320
- data/lib/hecks/runtime/tenant_check.rb +14 -9
- data/lib/hecks/runtime/value/admission.rb +28 -19
- data/lib/hecks/runtime/value/coercion.rb +55 -404
- data/lib/hecks/runtime/value/entity_list_coercion.rb +27 -29
- data/lib/hecks/runtime/value/field_checks.rb +57 -100
- data/lib/hecks/runtime/value/flags.rb +65 -0
- data/lib/hecks/runtime/value/identifiers.rb +64 -0
- data/lib/hecks/runtime/value/references.rb +195 -0
- data/lib/hecks/runtime/value/shape_checks.rb +61 -0
- data/lib/hecks/runtime/value/validation.rb +125 -0
- data/lib/hecks/runtime/value.rb +18 -6
- data/lib/hecks/rust_build/conformance/surface.rb +75 -0
- data/lib/hecks/rust_build/conformance.rb +27 -59
- data/lib/hecks/rust_build/conformance_fuzz.rb +26 -15
- data/lib/hecks/rust_build/coverage.rb +32 -104
- data/lib/hecks/rust_build/coverage_parts/expected.rb +68 -0
- data/lib/hecks/rust_build/coverage_parts/printer.rb +75 -0
- data/lib/hecks/rust_build/host.rb +23 -13
- data/lib/hecks/rust_build/kernel_input.rb +19 -12
- data/lib/hecks/rust_build/native_build.rb +19 -15
- data/lib/hecks/rust_build/project_rust/domain_loader.rb +75 -0
- data/lib/hecks/rust_build/project_rust/root_mod/notes.rb +66 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +22 -55
- data/lib/hecks/rust_build/project_rust/target_ir.rb +74 -0
- data/lib/hecks/rust_build/project_rust.rb +21 -89
- data/lib/hecks/rust_build/wasm.rb +11 -4
- data/lib/hecks/rust_build/wasm_browser.rb +7 -7
- data/lib/hecks/rust_build/write_if_changed.rb +3 -6
- data/lib/hecks/rust_build.rb +7 -3
- data/lib/hecks/site/bluebook/site.bluebook +7 -1
- data/lib/hecks/storehouse/audit.rb +106 -0
- data/lib/hecks/storehouse/callers.rb +73 -0
- data/lib/hecks/storehouse/dispatching.rb +149 -0
- data/lib/hecks/storehouse/introspection.rb +145 -0
- data/lib/hecks/storehouse/querying.rb +78 -0
- data/lib/hecks/storehouse.rb +43 -451
- data/lib/hecks/tickets/bluebook/tickets.bluebook +29 -0
- data/lib/hecks/tools/argument_gate_matrix/dispatching.rb +69 -0
- data/lib/hecks/tools/argument_gate_matrix/rows.rb +121 -0
- data/lib/hecks/tools/argument_gate_matrix/violations.rb +108 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +43 -212
- data/lib/hecks/tools/ci_gate_decision.rb +21 -14
- data/lib/hecks/tools/ci_gates.rb +40 -26
- data/lib/hecks/tools/comment_style/baseline.rb +41 -0
- data/lib/hecks/tools/comment_style/caps_words.rb +104 -0
- data/lib/hecks/tools/comment_style/cli.rb +121 -0
- data/lib/hecks/tools/comment_style/dictionary.rb +60 -0
- data/lib/hecks/tools/comment_style/fixing.rb +119 -0
- data/lib/hecks/tools/comment_style/long_blocks.rb +51 -0
- data/lib/hecks/tools/comment_style/masking.rb +94 -0
- data/lib/hecks/tools/comment_style/patterns.rb +61 -0
- data/lib/hecks/tools/comment_style/run.rb +161 -0
- data/lib/hecks/tools/comment_style/signature.rb +59 -0
- data/lib/hecks/tools/comment_style/source_file.rb +105 -0
- data/lib/hecks/tools/comment_style/structure_checks.rb +113 -0
- data/lib/hecks/tools/comment_style/text_checks.rb +67 -0
- data/lib/hecks/tools/comment_style/vocabulary.rb +55 -0
- data/lib/hecks/tools/comment_style/walker.rb +136 -0
- data/lib/hecks/tools/comment_style.rb +17 -1000
- data/lib/hecks/tools/corpus_report.rb +26 -16
- data/lib/hecks/tools/deploy_recipe/targets.rb +61 -0
- data/lib/hecks/tools/deploy_recipe/worlds.rb +114 -0
- data/lib/hecks/tools/deploy_recipe.rb +60 -174
- data/lib/hecks/tools/deploy_recipe_lint/checks.rb +78 -0
- data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +88 -0
- data/lib/hecks/tools/deploy_recipe_lint/makefile.rb +84 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +29 -192
- data/lib/hecks/tools/drop_implicit_append_fields.rb +20 -12
- data/lib/hecks/tools/era_projection_backfill.rb +50 -33
- data/lib/hecks/tools/era_reattest/reporting.rb +55 -0
- data/lib/hecks/tools/era_reattest.rb +32 -43
- data/lib/hecks/tools/evolve_run/arguments.rb +49 -0
- data/lib/hecks/tools/evolve_run/words.rb +60 -0
- data/lib/hecks/tools/evolve_run.rb +43 -90
- data/lib/hecks/tools/fuzz_sweep/findings.rb +106 -0
- data/lib/hecks/tools/fuzz_sweep/options.rb +69 -0
- data/lib/hecks/tools/fuzz_sweep/pool.rb +74 -0
- data/lib/hecks/tools/fuzz_sweep/reporting.rb +88 -0
- data/lib/hecks/tools/fuzz_sweep.rb +75 -273
- data/lib/hecks/tools/gate.rb +31 -16
- data/lib/hecks/tools/heki_compaction.rb +63 -42
- data/lib/hecks/tools/hoist_local_givens/rewriting.rb +119 -0
- data/lib/hecks/tools/hoist_local_givens.rb +89 -157
- data/lib/hecks/tools/journal_compaction.rb +40 -31
- data/lib/hecks/tools/lanes/files.rb +82 -0
- data/lib/hecks/tools/lanes/live.rb +41 -0
- data/lib/hecks/tools/lanes/rows.rb +45 -0
- data/lib/hecks/tools/lanes/ruleset.rb +44 -0
- data/lib/hecks/tools/lanes/watch_workflow.rb +82 -0
- data/lib/hecks/tools/lanes/workflow.rb +79 -0
- data/lib/hecks/tools/lanes.rb +71 -0
- data/lib/hecks/tools/oidc_manifests.rb +10 -9
- data/lib/hecks/tools/query_ir_run.rb +7 -3
- data/lib/hecks/tools/regeneration_run.rb +40 -26
- data/lib/hecks/tools/rust_comment_style/caps_words.rb +98 -0
- data/lib/hecks/tools/rust_comment_style/fixing.rb +102 -0
- data/lib/hecks/tools/rust_comment_style/masking.rb +85 -0
- data/lib/hecks/tools/rust_comment_style/run.rb +94 -0
- data/lib/hecks/tools/rust_comment_style/source_file.rb +71 -0
- data/lib/hecks/tools/rust_comment_style/structure.rb +79 -0
- data/lib/hecks/tools/rust_comment_style/text_checks.rb +63 -0
- data/lib/hecks/tools/rust_comment_style/tokenizer.rb +102 -0
- data/lib/hecks/tools/rust_comment_style.rb +38 -535
- data/lib/hecks/tools/sequence_script.rb +20 -14
- data/lib/hecks/tools/site_routes/cli.rb +70 -0
- data/lib/hecks/tools/site_routes/root_files.rb +59 -0
- data/lib/hecks/tools/site_routes/templates.rb +77 -0
- data/lib/hecks/tools/site_routes.rb +102 -108
- data/lib/hecks/tools/tail_merge.rb +45 -37
- data/lib/hecks/tools/tenant_provisioning.rb +45 -31
- data/lib/hecks/tools/tools_doc.rb +42 -19
- data/lib/hecks/tools/translation_audit/domain_loading.rb +71 -0
- data/lib/hecks/tools/translation_audit/edges.rb +71 -0
- data/lib/hecks/tools/translation_audit/verdicts.rb +107 -0
- data/lib/hecks/tools/translation_audit.rb +30 -161
- data/lib/hecks/tools/translation_scaffold/reporting.rb +40 -0
- data/lib/hecks/tools/translation_scaffold.rb +77 -60
- data/lib/hecks/tools.rb +1 -0
- data/lib/hecks/vendoring.rb +37 -11
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +16 -1
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +7 -9
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +8 -6
- data/rust/.cargo/mutants.toml +8 -0
- data/rust/host/Cargo.toml +5 -0
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/auth.rs +32 -0
- data/rust/host/src/web.rs +2 -3
- data/rust/src/kernel/dispatch.rs +4 -0
- data/rust/src/kernel/dispatch_guard_tests.rs +506 -0
- data/rust/src/kernel/orchestrate.rs +4 -0
- data/rust/src/kernel/orchestrate_guard_tests.rs +708 -0
- metadata +607 -3
- /data/lib/hecks/bluebook/behaviour/{hexagon.rb → hecksagon.rb} +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
require "hecks/vocabulary"
|
|
2
|
+
require_relative "keyword_fields"
|
|
2
3
|
require_relative "model_check/client_profile"
|
|
4
|
+
require_relative "model_check/lifecycle_checks"
|
|
5
|
+
require_relative "model_check/saga_checks"
|
|
6
|
+
require_relative "model_check/policy_checks"
|
|
7
|
+
require_relative "model_check/verbs"
|
|
3
8
|
|
|
4
9
|
module Hecks
|
|
5
10
|
module Bluebook
|
|
@@ -19,43 +24,69 @@ module Hecks
|
|
|
19
24
|
# The profiles `call` accepts; `nil` is the default, unprofiled run.
|
|
20
25
|
PROFILES = %i[client].freeze
|
|
21
26
|
|
|
27
|
+
# What `call` takes from one corpus scan besides the chapter, and each key's default.
|
|
28
|
+
CONTEXT_DEFAULTS = {
|
|
29
|
+
hecksagon: nil, known_domains: nil, global_emitted_events: nil, rust_target: false, strict: false
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
extend LifecycleChecks
|
|
33
|
+
extend SagaChecks
|
|
34
|
+
extend PolicyChecks
|
|
35
|
+
extend Verbs
|
|
36
|
+
|
|
22
37
|
module_function
|
|
23
38
|
|
|
24
39
|
# Runs every static model check over `bluebook` and returns what it finds.
|
|
25
40
|
#
|
|
26
41
|
# @param bluebook [Bluebook::Chapter] the assembled chapter to check
|
|
27
|
-
# @param hecksagon [Bluebook::Hecksagon, nil] this bluebook's own sibling wiring
|
|
28
|
-
# file, if the caller loaded one
|
|
29
|
-
# @param known_domains [Set<String>, nil] every bluebook/hecksagon name booted
|
|
30
|
-
# anywhere in this corpus scan, checked to catch a typo'd across/attaches target
|
|
31
|
-
# @param global_emitted_events [Set<String>, nil] every event emitted anywhere in
|
|
32
|
-
# the corpus, checked as a fallback so a translates reaction isn't flagged deaf
|
|
33
42
|
# @param profile [Symbol, nil] :client adds ClientProfile's error findings
|
|
43
|
+
# @param context [Hash] the rest of what one corpus scan knows, each key optional:
|
|
44
|
+
# `hecksagon` (this bluebook's own sibling wiring file, if the caller loaded one),
|
|
45
|
+
# `known_domains` (every bluebook/hecksagon name booted anywhere in this corpus scan,
|
|
46
|
+
# checked to catch a typo'd across/attaches target), `global_emitted_events` (every
|
|
47
|
+
# event emitted anywhere in the corpus, checked as a fallback so a translates reaction
|
|
48
|
+
# isn't flagged deaf), `rust_target` and `strict` (see `rust_reserved_name_findings`)
|
|
34
49
|
# @return [Array<Finding>] every finding this bluebook triggers
|
|
35
|
-
# @raise [ArgumentError] if profile is neither nil nor :client
|
|
36
|
-
def call(bluebook,
|
|
37
|
-
profile: nil)
|
|
50
|
+
# @raise [ArgumentError] if profile is neither nil nor :client, or a context key is unknown
|
|
51
|
+
def call(bluebook, profile: nil, **context)
|
|
38
52
|
unless profile.nil? || PROFILES.include?(profile)
|
|
39
53
|
raise ArgumentError, "unknown profile #{profile.inspect} (known: #{PROFILES.inspect})"
|
|
40
54
|
end
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
bluebook
|
|
44
|
-
|
|
45
|
-
aggregate.entities.each { |entity| findings.concat(lifecycle_findings(aggregate, entity)) }
|
|
46
|
-
end
|
|
47
|
-
bluebook.process_managers.each { |process_manager| findings.concat(saga_findings(bluebook, process_manager)) }
|
|
48
|
-
bluebook.policies.each do |policy|
|
|
49
|
-
findings.concat(policy_findings(bluebook, policy, hecksagon, known_domains, global_emitted_events))
|
|
50
|
-
end
|
|
51
|
-
findings.concat(rust_reserved_name_findings(domain_name: bluebook.name,
|
|
52
|
-
aggregate_names: bluebook.aggregates.map(&:hecks_name),
|
|
53
|
-
rust_target: rust_target, strict: strict))
|
|
54
|
-
findings.concat(external_query_findings(bluebook, rust_target: rust_target))
|
|
55
|
-
findings.concat(ClientProfile.call(bluebook, hecksagon: hecksagon)) if profile == :client
|
|
56
|
+
options = KeywordFields.fill(context, CONTEXT_DEFAULTS)
|
|
57
|
+
findings = [*modelled_findings(bluebook, options), *target_findings(bluebook, options)]
|
|
58
|
+
findings.concat(ClientProfile.call(bluebook, hecksagon: options[:hecksagon])) if profile == :client
|
|
56
59
|
findings
|
|
57
60
|
end
|
|
58
61
|
|
|
62
|
+
# Lifecycles, sagas and policies: what the model says about itself.
|
|
63
|
+
def modelled_findings(bluebook, options)
|
|
64
|
+
[
|
|
65
|
+
*bluebook.aggregates.flat_map { |aggregate| aggregate_lifecycle_findings(aggregate) },
|
|
66
|
+
*bluebook.process_managers.flat_map { |process_manager| saga_findings(bluebook, process_manager) },
|
|
67
|
+
*bluebook.policies.flat_map do |policy|
|
|
68
|
+
policy_findings(bluebook, policy, options[:hecksagon], options[:known_domains],
|
|
69
|
+
options[:global_emitted_events])
|
|
70
|
+
end
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Names and queries a Rust target would not accept.
|
|
75
|
+
def target_findings(bluebook, options)
|
|
76
|
+
[
|
|
77
|
+
*rust_reserved_name_findings(domain_name: bluebook.name,
|
|
78
|
+
aggregate_names: bluebook.aggregates.map(&:hecks_name),
|
|
79
|
+
rust_target: options[:rust_target], strict: options[:strict]),
|
|
80
|
+
*external_query_findings(bluebook, rust_target: options[:rust_target])
|
|
81
|
+
]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @return [Array<Finding>] the aggregate's own lifecycle findings, then each entity's
|
|
85
|
+
def aggregate_lifecycle_findings(aggregate)
|
|
86
|
+
lifecycle_findings(aggregate, aggregate) +
|
|
87
|
+
aggregate.entities.flat_map { |entity| lifecycle_findings(aggregate, entity) }
|
|
88
|
+
end
|
|
89
|
+
|
|
59
90
|
# Flags a query the hecksagon binds to a port's adapter. Only the Ruby runtime asks an
|
|
60
91
|
# adapter for an answer; a Rust host would find nothing behind the query.
|
|
61
92
|
#
|
|
@@ -68,16 +99,18 @@ module Hecks
|
|
|
68
99
|
|
|
69
100
|
bluebook.aggregates.flat_map do |aggregate|
|
|
70
101
|
aggregate.ports.flat_map do |port|
|
|
71
|
-
port.answered_queries.map
|
|
72
|
-
Finding.new(kind: :external_query, severity: :error,
|
|
73
|
-
subject: "#{aggregate.hecks_name}.#{answer.name}",
|
|
74
|
-
message: "the #{port.name} port's adapter answers this query, and only the Ruby " \
|
|
75
|
-
"runtime asks an adapter — the Rust host cannot serve it")
|
|
76
|
-
end
|
|
102
|
+
port.answered_queries.map { |answer| external_query_finding(aggregate, port, answer) }
|
|
77
103
|
end
|
|
78
104
|
end
|
|
79
105
|
end
|
|
80
106
|
|
|
107
|
+
def external_query_finding(aggregate, port, answer)
|
|
108
|
+
Finding.new(kind: :external_query, severity: :error,
|
|
109
|
+
subject: "#{aggregate.hecks_name}.#{answer.name}",
|
|
110
|
+
message: "the #{port.name} port's adapter answers this query, and only the Ruby " \
|
|
111
|
+
"runtime asks an adapter — the Rust host cannot serve it")
|
|
112
|
+
end
|
|
113
|
+
|
|
81
114
|
# Flags an aggregate or domain name that collides with a Rust keyword or reserved
|
|
82
115
|
# Cargo key — both become bare module identifiers with no `r#` escape hatch.
|
|
83
116
|
#
|
|
@@ -92,18 +125,21 @@ module Hecks
|
|
|
92
125
|
severity = rust_target || strict ? :error : :warning
|
|
93
126
|
keywords = Hecks::Vocabulary.fetch("RustReservedWord")
|
|
94
127
|
|
|
95
|
-
findings = aggregate_names.filter_map
|
|
96
|
-
module_name = rust_module_name(name)
|
|
97
|
-
next unless keywords.include?(module_name)
|
|
98
|
-
|
|
99
|
-
Finding.new(kind: :rust_reserved_name, severity: severity, subject: name.to_s,
|
|
100
|
-
message: "the aggregate's Rust module `#{module_name}` is a Rust keyword (RustReservedWord) — " \
|
|
101
|
-
"`pub mod #{module_name};` has no raw-identifier escape; rename the aggregate")
|
|
102
|
-
end
|
|
128
|
+
findings = aggregate_names.filter_map { |name| reserved_aggregate_finding(name, keywords, severity) }
|
|
103
129
|
findings.concat(domain_reserved_name_findings(domain_name, keywords, severity)) if domain_name
|
|
104
130
|
findings
|
|
105
131
|
end
|
|
106
132
|
|
|
133
|
+
# @return [Finding, nil] the finding for an aggregate whose Rust module is a keyword
|
|
134
|
+
def reserved_aggregate_finding(name, keywords, severity)
|
|
135
|
+
module_name = rust_module_name(name)
|
|
136
|
+
return unless keywords.include?(module_name)
|
|
137
|
+
|
|
138
|
+
Finding.new(kind: :rust_reserved_name, severity: severity, subject: name.to_s,
|
|
139
|
+
message: "the aggregate's Rust module `#{module_name}` is a Rust keyword (RustReservedWord) — " \
|
|
140
|
+
"`pub mod #{module_name};` has no raw-identifier escape; rename the aggregate")
|
|
141
|
+
end
|
|
142
|
+
|
|
107
143
|
# The domain-level half of rust_reserved_name_findings — same tables, one name.
|
|
108
144
|
def domain_reserved_name_findings(domain_name, keywords, severity)
|
|
109
145
|
module_name = rust_module_name(domain_name)
|
|
@@ -120,382 +156,6 @@ module Hecks
|
|
|
120
156
|
end
|
|
121
157
|
|
|
122
158
|
def rust_module_name(name) = name.to_s.downcase
|
|
123
|
-
|
|
124
|
-
# Runs every lifecycle-shaped check for one declaring construct — the aggregate
|
|
125
|
-
# itself, or one of its entities — if it declares a lifecycle at all.
|
|
126
|
-
def lifecycle_findings(aggregate, declaring)
|
|
127
|
-
lifecycle = declaring.lifecycle
|
|
128
|
-
return [] unless lifecycle
|
|
129
|
-
|
|
130
|
-
subject = declaring.equal?(aggregate) ? aggregate.hecks_name : "#{aggregate.hecks_name}::#{declaring.hecks_name}"
|
|
131
|
-
commands = Array(declaring.commands).map(&:hecks_name)
|
|
132
|
-
|
|
133
|
-
full = full_states(lifecycle)
|
|
134
|
-
reached = reachable_states(lifecycle)
|
|
135
|
-
|
|
136
|
-
findings = []
|
|
137
|
-
findings.concat(unknown_transition_commands(lifecycle, commands, subject))
|
|
138
|
-
findings.concat(unreachable_state_findings(lifecycle, full, reached, subject))
|
|
139
|
-
findings.concat(dead_transition_findings(lifecycle, reached, subject))
|
|
140
|
-
findings.concat(stuck_state_findings(lifecycle, reached, subject))
|
|
141
|
-
findings
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# Finds every declared state the lifecycle's own reachability walk never reaches.
|
|
145
|
-
def unreachable_state_findings(lifecycle, full, reached, subject)
|
|
146
|
-
(full - reached.to_a).map do |state|
|
|
147
|
-
Finding.new(kind: :unreachable_state, severity: :error, subject: subject,
|
|
148
|
-
message: "#{state.inspect} is declared (in a transition's from: or target) " \
|
|
149
|
-
"but no path from #{lifecycle.default.inspect} ever reaches it")
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# Finds every constrained transition whose from: states are all unreached.
|
|
154
|
-
def dead_transition_findings(lifecycle, reached, subject)
|
|
155
|
-
lifecycle.transitions.filter_map do |command, transition|
|
|
156
|
-
next unless transition.constrained?
|
|
157
|
-
next if Array(transition.from).any? { |source| reached.include?(source) }
|
|
158
|
-
|
|
159
|
-
Finding.new(kind: :dead_transition, severity: :error, subject: subject,
|
|
160
|
-
message: "#{command} from #{Array(transition.from).inspect} can never fire — " \
|
|
161
|
-
"none of those states is ever reached")
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Finds every reached state with no transition ever leaving it, unless any
|
|
166
|
-
# transition in this lifecycle is unconstrained.
|
|
167
|
-
def stuck_state_findings(lifecycle, reached, subject)
|
|
168
|
-
any_unconstrained = lifecycle.transitions.any? { |_, t| !t.constrained? }
|
|
169
|
-
(reached - terminal_exempt(lifecycle)).filter_map do |state|
|
|
170
|
-
next if any_unconstrained
|
|
171
|
-
next if lifecycle.transitions.any? { |_, t| t.constrained? && Array(t.from).include?(state) }
|
|
172
|
-
|
|
173
|
-
Finding.new(kind: :stuck_state, severity: :warning, subject: subject,
|
|
174
|
-
message: "#{state.inspect} is reached but no transition ever leaves it — " \
|
|
175
|
-
"fine if that is meant to be terminal")
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
# Finds every transition named after a command the construct doesn't declare.
|
|
180
|
-
def unknown_transition_commands(lifecycle, commands, subject)
|
|
181
|
-
lifecycle.transitions.filter_map do |command, _transition|
|
|
182
|
-
next if commands.include?(command)
|
|
183
|
-
|
|
184
|
-
Finding.new(kind: :unknown_command, severity: :error, subject: subject,
|
|
185
|
-
message: "a transition names #{command.inspect}, which this construct declares no command for")
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# Every state `lifecycle` declares in any role — default, target, or from,
|
|
190
|
-
# unique.
|
|
191
|
-
#
|
|
192
|
-
# @param lifecycle [Bluebook::Lifecycle] the lifecycle being checked
|
|
193
|
-
# @return [Array<String>] every state lifecycle declares, unique
|
|
194
|
-
def full_states(lifecycle)
|
|
195
|
-
(
|
|
196
|
-
[lifecycle.default] +
|
|
197
|
-
lifecycle.transitions.map { |_, t| t.target } +
|
|
198
|
-
lifecycle.transitions.flat_map { |_, t| Array(t.from) }
|
|
199
|
-
).uniq
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
# Least fixpoint from the default state: an unconstrained transition always
|
|
203
|
-
# fires; a constrained one fires once any of its named sources is reached.
|
|
204
|
-
def reachable_states(lifecycle)
|
|
205
|
-
reached = Set.new([lifecycle.default])
|
|
206
|
-
loop do
|
|
207
|
-
grown = false
|
|
208
|
-
# `transitions` is an Array of [from, transition] pairs, not a Hash, so
|
|
209
|
-
# Style/HashEachMethods' each_value rewrite is a false positive here.
|
|
210
|
-
# rubocop:disable-next Style/HashEachMethods
|
|
211
|
-
lifecycle.transitions.each do |_, transition|
|
|
212
|
-
next if reached.include?(transition.target)
|
|
213
|
-
next if transition.constrained? && Array(transition.from).none? { |source| reached.include?(source) }
|
|
214
|
-
|
|
215
|
-
reached << transition.target
|
|
216
|
-
grown = true
|
|
217
|
-
end
|
|
218
|
-
break unless grown
|
|
219
|
-
end
|
|
220
|
-
reached
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
# Exempts only the lifecycle's own default state, and only when the lifecycle
|
|
224
|
-
# declares real transitions elsewhere: entering default implies nothing about
|
|
225
|
-
# ever leaving it, unlike a state some transition explicitly delivered to. An
|
|
226
|
-
# empty lifecycle still warns — that reads as unfinished wiring, not a deliberate rest.
|
|
227
|
-
def terminal_exempt(lifecycle)
|
|
228
|
-
return [] if lifecycle.transitions.empty?
|
|
229
|
-
|
|
230
|
-
outgoing_sources = lifecycle.transitions.flat_map { |_, t| Array(t.from) }.to_set
|
|
231
|
-
outgoing_sources.include?(lifecycle.default) ? [] : [lifecycle.default]
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
# Runs every saga-shaped check for one process manager.
|
|
235
|
-
def saga_findings(bluebook, process_manager)
|
|
236
|
-
emitted = emitted_events(bluebook)
|
|
237
|
-
# Parsed as (domain, aggregate, command) triples via Naming.split_verb, not
|
|
238
|
-
# compared as raw strings — that's what makes an entity verb's two legitimate
|
|
239
|
-
# spellings compare equal (see handler_findings' unknown_dispatch check).
|
|
240
|
-
verbs = verbs_of(bluebook).map { |verb| Naming.split_verb(verb) }
|
|
241
|
-
reached = pm_reachable_states(process_manager, emitted)
|
|
242
|
-
|
|
243
|
-
findings = []
|
|
244
|
-
findings.concat(deaf_trigger_findings(process_manager, emitted))
|
|
245
|
-
findings.concat(unreachable_pm_state_findings(process_manager, reached))
|
|
246
|
-
process_manager.handlers.each do |handler|
|
|
247
|
-
findings.concat(handler_findings(bluebook, process_manager, emitted, verbs, handler))
|
|
248
|
-
end
|
|
249
|
-
findings.concat(dead_compensation_findings(process_manager, reached))
|
|
250
|
-
findings
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
# Finds every declared starts_on/ends_on event this domain never emits.
|
|
254
|
-
def deaf_trigger_findings(process_manager, emitted)
|
|
255
|
-
[process_manager.starts_on, process_manager.ends_on].compact.filter_map do |event|
|
|
256
|
-
next if emitted.include?(bare(event))
|
|
257
|
-
|
|
258
|
-
Finding.new(kind: :deaf_trigger, severity: :error, subject: process_manager.name,
|
|
259
|
-
message: "starts_on/ends_on names #{event.inspect}, which no command in this " \
|
|
260
|
-
"domain emits")
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
# Finds every declared state no handler chain ever reaches.
|
|
265
|
-
def unreachable_pm_state_findings(process_manager, reached)
|
|
266
|
-
(Array(process_manager.states) - reached.to_a).map do |state|
|
|
267
|
-
Finding.new(kind: :unreachable_pm_state, severity: :error, subject: process_manager.name,
|
|
268
|
-
message: "#{state.inspect} is declared but no handler chain from " \
|
|
269
|
-
"#{process_manager.states.first.inspect} ever reaches it")
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
# One handler's own deaf_handler/unknown_dispatch/unarmed_compensation findings.
|
|
274
|
-
def handler_findings(bluebook, process_manager, emitted, verbs, handler)
|
|
275
|
-
findings = []
|
|
276
|
-
|
|
277
|
-
# The compensating leg answers `REFUSED`, a synthetic trigger no command
|
|
278
|
-
# ever emits by name — deliberately exempt from the deaf-handler check.
|
|
279
|
-
if handler.event_type != ProcessManager::REFUSED && !emitted.include?(bare(handler.event_type))
|
|
280
|
-
findings << Finding.new(kind: :deaf_handler, severity: :error, subject: process_manager.name,
|
|
281
|
-
message: "a handler answers #{handler.event_type.inspect}, which no command " \
|
|
282
|
-
"in this domain emits")
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
handler.dispatches.each do |dispatch|
|
|
286
|
-
# Always qualified against this domain's own name (no saga dispatches
|
|
287
|
-
# cross-domain) and compared as a parsed triple, not a string, so an
|
|
288
|
-
# entity verb's two legitimate spellings compare equal.
|
|
289
|
-
qualified = Naming.split_verb("#{bluebook.name}::#{dispatch.command_name}")
|
|
290
|
-
next if verbs.include?(qualified)
|
|
291
|
-
|
|
292
|
-
findings << Finding.new(kind: :unknown_dispatch, severity: :error, subject: process_manager.name,
|
|
293
|
-
message: "dispatches #{dispatch.command_name.inspect}, which this domain " \
|
|
294
|
-
"declares no command at — cross-domain dispatch is out of this " \
|
|
295
|
-
"checker's scope, same as CommandRules#resolve_references")
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
# No handler anywhere answers `REFUSED` means SagaInterpreter#unwind never
|
|
299
|
-
# runs for this process manager, so a declared compensates is structurally
|
|
300
|
-
# unreachable — a dead declaration, not a style warning.
|
|
301
|
-
if !process_manager.saga? && handler.dispatches.any?(&:compensates)
|
|
302
|
-
handler.dispatches.select(&:compensates).each do |dispatch|
|
|
303
|
-
findings << Finding.new(kind: :unarmed_compensation, severity: :error, subject: process_manager.name,
|
|
304
|
-
message: "#{dispatch.command_name} compensates #{dispatch.compensates.command_name}, " \
|
|
305
|
-
"but no handler anywhere in this saga answers a refusal — the " \
|
|
306
|
-
"compensation is declared and can never fire")
|
|
307
|
-
end
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
findings
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
# Checks whether a saga's own compensation leaves an unreachable state.
|
|
314
|
-
def dead_compensation_findings(process_manager, reached)
|
|
315
|
-
return [] unless process_manager.saga? && !reached.include?(process_manager.saga.from_state)
|
|
316
|
-
|
|
317
|
-
[Finding.new(kind: :dead_compensation, severity: :error, subject: process_manager.name,
|
|
318
|
-
message: "the compensation leaves #{process_manager.saga.from_state.inspect}, which no " \
|
|
319
|
-
"handler chain ever reaches — a refusal here can never fire it")]
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
# Only a handler that can actually fire extends the closure — `REFUSED` always
|
|
323
|
-
# can (it's a compensation trigger, not an event); any other handler needs its
|
|
324
|
-
# event genuinely emitted. Otherwise a deaf handler's edge would read as
|
|
325
|
-
# connected even though nothing can ever traverse it.
|
|
326
|
-
def pm_reachable_states(process_manager, emitted)
|
|
327
|
-
return Set.new if Array(process_manager.states).empty?
|
|
328
|
-
|
|
329
|
-
reached = Set.new([process_manager.states.first])
|
|
330
|
-
loop do
|
|
331
|
-
grown = false
|
|
332
|
-
process_manager.handlers.each do |handler|
|
|
333
|
-
next unless handler.event_type == ProcessManager::REFUSED || emitted.include?(bare(handler.event_type))
|
|
334
|
-
next unless reached.include?(handler.from_state)
|
|
335
|
-
next if reached.include?(handler.to_state)
|
|
336
|
-
|
|
337
|
-
reached << handler.to_state
|
|
338
|
-
grown = true
|
|
339
|
-
end
|
|
340
|
-
break unless grown
|
|
341
|
-
end
|
|
342
|
-
reached
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
# Runs every same-domain policy check, or defers to
|
|
346
|
-
# cross_domain_policy_findings for a cross-domain policy.
|
|
347
|
-
def policy_findings(bluebook, policy, hecksagon, known_domains, global_emitted_events = nil)
|
|
348
|
-
return cross_domain_policy_findings(policy, hecksagon, known_domains) if policy.target_domain
|
|
349
|
-
|
|
350
|
-
emitted = emitted_events(bluebook)
|
|
351
|
-
findings = []
|
|
352
|
-
|
|
353
|
-
# `policy.event_name`, not `bare` — an aggregate-scoped on_event carries a
|
|
354
|
-
# "." qualifier bare doesn't strip. `global_emitted_events` is a fallback for
|
|
355
|
-
# a translates reaction, whose whole point is reacting to a foreign event.
|
|
356
|
-
unless emitted.include?(policy.event_name) || global_emitted_events&.include?(policy.event_name)
|
|
357
|
-
findings << Finding.new(kind: :deaf_policy, severity: :error, subject: policy.name,
|
|
358
|
-
message: "on #{policy.on_event.inspect}, which no command in this domain emits")
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
# Completed to the same FQN verbs_of builds, then compared as a parsed
|
|
362
|
-
# triple — not a string — so a port-operation trigger's spelling matches
|
|
363
|
-
# the same way an entity command's does (see handler_findings above).
|
|
364
|
-
qualified = Naming.split_verb("#{bluebook.name}::#{policy.trigger_command}")
|
|
365
|
-
unless qualified && triggerable_verbs(bluebook).include?(qualified)
|
|
366
|
-
findings << Finding.new(kind: :unknown_trigger, severity: :error, subject: policy.name,
|
|
367
|
-
message: "trigger #{policy.trigger_command.inspect} resolves to no command " \
|
|
368
|
-
"this domain declares")
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
findings
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
# `attaches` is a Shared Kernel relationship (X merges in, no boundary);
|
|
375
|
-
# `across` is Customer/Supplier (real cross-Lambda RPC). This checks the choice
|
|
376
|
-
# between them instead of leaving it as an unenforced comment. (ADR 0025)
|
|
377
|
-
def cross_domain_policy_findings(policy, hecksagon, known_domains)
|
|
378
|
-
return expected_undelivered_findings(policy, hecksagon, known_domains) if policy.expect_undelivered
|
|
379
|
-
# No sibling hecksagon loaded — nothing to check a relationship against.
|
|
380
|
-
return [] unless hecksagon
|
|
381
|
-
|
|
382
|
-
target = policy.target_domain
|
|
383
|
-
findings = []
|
|
384
|
-
|
|
385
|
-
if hecksagon.attaches?(target)
|
|
386
|
-
# Shared Kernel and Customer/Supplier are mutually exclusive claims about
|
|
387
|
-
# the same target — declaring both means either a pointless RPC to a
|
|
388
|
-
# domain already local, or an attaches that isn't doing its job.
|
|
389
|
-
findings << Finding.new(kind: :contradictory_relationship, severity: :error, subject: policy.name,
|
|
390
|
-
message: "across #{target.inspect} dispatches over RPC (Customer/Supplier), " \
|
|
391
|
-
"but this hecksagon also attaches #{target.inspect} (Shared " \
|
|
392
|
-
"Kernel) — #{target} is already loaded in-process here, so the two " \
|
|
393
|
-
"relationship declarations contradict each other for the same " \
|
|
394
|
-
"target domain")
|
|
395
|
-
elsif hecksagon.subscriptions.none? { |subscribed| Naming.qualifier(subscribed) == target }
|
|
396
|
-
# Checked here at model-check time; subscribe itself is never routed at
|
|
397
|
-
# runtime (see hecksagon.md's own "checked, not routed" section).
|
|
398
|
-
findings << Finding.new(kind: :unacknowledged_relationship, severity: :error, subject: policy.name,
|
|
399
|
-
message: "across #{target.inspect} declares a Customer/Supplier " \
|
|
400
|
-
"relationship, but nothing in this hecksagon records the " \
|
|
401
|
-
"expectation — add subscribe \"#{target}.SomeEvent\" for what " \
|
|
402
|
-
"you expect back from it, or attaches #{target.inspect} to " \
|
|
403
|
-
"attach it in-process instead")
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
# A heuristic, not proof: an external hecks consumer's own domain lives in a
|
|
407
|
-
# repo this corpus scan can't see, so "unknown here" isn't necessarily a typo.
|
|
408
|
-
# A domain undefined on purpose declares so via expect_undelivered instead.
|
|
409
|
-
if known_domains && !known_domains.include?(target)
|
|
410
|
-
findings << Finding.new(kind: :unknown_target_domain, severity: :error, subject: policy.name,
|
|
411
|
-
message: "across #{target.inspect} names a domain nowhere in the corpus " \
|
|
412
|
-
"this check has booted — a typo, or a target intentionally never " \
|
|
413
|
-
"reached, which the policy itself declares with " \
|
|
414
|
-
"across #{target.inspect}, expect_undelivered: true")
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
findings
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
# Holds an expect_undelivered declaration to its word: the two findings an
|
|
421
|
-
# unreachable target would otherwise raise are suppressed (that's the point of
|
|
422
|
-
# the declaration), but if the target turns out reachable after all, the stale
|
|
423
|
-
# declaration itself is now the error.
|
|
424
|
-
def expected_undelivered_findings(policy, hecksagon, known_domains)
|
|
425
|
-
target = policy.target_domain
|
|
426
|
-
reached = []
|
|
427
|
-
reached << "#{target} is a domain this corpus boots" if known_domains&.include?(target)
|
|
428
|
-
if hecksagon
|
|
429
|
-
reached << "this hecksagon attaches #{target.inspect}" if hecksagon.attaches?(target)
|
|
430
|
-
if hecksagon.subscriptions.any? { |subscribed| Naming.qualifier(subscribed) == target }
|
|
431
|
-
reached << "this hecksagon subscribes to #{target}"
|
|
432
|
-
end
|
|
433
|
-
end
|
|
434
|
-
return [] if reached.empty?
|
|
435
|
-
|
|
436
|
-
[Finding.new(kind: :stale_undelivered_expectation, severity: :error, subject: policy.name,
|
|
437
|
-
message: "across #{target.inspect}, expect_undelivered: true — but #{reached.join(' and ')}, " \
|
|
438
|
-
"so the reaction can be delivered after all; drop expect_undelivered: or remove " \
|
|
439
|
-
"what reaches #{target}")]
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
# Every bare event name this domain's commands and port operations emit,
|
|
443
|
-
# answer, or refuse — an outbound `asks` port operation has no `.emits`.
|
|
444
|
-
#
|
|
445
|
-
# @param bluebook [Bluebook::Chapter] the assembled chapter to enumerate
|
|
446
|
-
# @return [Array<String>] every bare event name emitted, answered, or refused
|
|
447
|
-
# across this domain, unique
|
|
448
|
-
def emitted_events(bluebook)
|
|
449
|
-
aggregate_emits = bluebook.aggregates.flat_map do |aggregate|
|
|
450
|
-
aggregate.commands.map(&:emits) +
|
|
451
|
-
aggregate.entities.flat_map { |entity| entity.commands.map(&:emits) } +
|
|
452
|
-
port_operation_events(aggregate.ports)
|
|
453
|
-
end
|
|
454
|
-
chapter_emits = port_operation_events(bluebook.ports)
|
|
455
|
-
|
|
456
|
-
(aggregate_emits + chapter_emits).flatten.compact.uniq
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
# One port's own emitted/answered/refused event names — an inbound operation's
|
|
460
|
-
# answers/refuses are always nil, compacted by the caller.
|
|
461
|
-
def port_operation_events(ports)
|
|
462
|
-
ports.flat_map { |port| port.operations.flat_map { |op| [*op.emits, op.answers, op.refuses] } }
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
# Every command's own fully-qualified verb: "Domain::Aggregate.Command" or
|
|
466
|
-
# "Domain::Aggregate.Entity.Command".
|
|
467
|
-
def verbs_of(bluebook)
|
|
468
|
-
bluebook.aggregates.flat_map do |aggregate|
|
|
469
|
-
verbs = aggregate.commands.map { |command| "#{bluebook.name}::#{aggregate.hecks_name}.#{command.hecks_name}" }
|
|
470
|
-
verbs + aggregate.entities.flat_map do |entity|
|
|
471
|
-
entity.commands.map do |command|
|
|
472
|
-
"#{bluebook.name}::#{aggregate.hecks_name}.#{entity.hecks_name}.#{command.hecks_name}"
|
|
473
|
-
end
|
|
474
|
-
end
|
|
475
|
-
end
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
# Every aggregate-owned port operation's own fully-qualified verb — only an
|
|
479
|
-
# aggregate's own ports are in scope; a policy trigger never names a
|
|
480
|
-
# chapter-level port directly.
|
|
481
|
-
def port_verbs_of(bluebook)
|
|
482
|
-
bluebook.aggregates.flat_map do |aggregate|
|
|
483
|
-
aggregate.ports.flat_map do |port|
|
|
484
|
-
port.operations.map do |operation|
|
|
485
|
-
"#{bluebook.name}::#{aggregate.hecks_name}.#{port.name}.#{operation.hecks_name}"
|
|
486
|
-
end
|
|
487
|
-
end
|
|
488
|
-
end
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
# Every triggerable verb — ordinary/entity commands plus port operations —
|
|
492
|
-
# parsed through Naming.split_verb so callers never compare raw spellings.
|
|
493
|
-
def triggerable_verbs(bluebook)
|
|
494
|
-
(verbs_of(bluebook) + port_verbs_of(bluebook)).to_set { |verb| Naming.split_verb(verb) }
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
# Strips a domain qualifier off an event name.
|
|
498
|
-
def bare(event) = event.to_s.split("::").last
|
|
499
159
|
end
|
|
500
160
|
end
|
|
501
161
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
# The refusal each excluded regex construct answers with: its name and the reason it is refused.
|
|
4
|
+
module PatternSubset
|
|
5
|
+
Rejection = Struct.new(:construct, :reason)
|
|
6
|
+
|
|
7
|
+
REASONS = {
|
|
8
|
+
backreference:
|
|
9
|
+
"backreferences cannot be matched in linear time and portable " \
|
|
10
|
+
"engines refuse them ; a declared pattern may not depend on one",
|
|
11
|
+
named_backreference:
|
|
12
|
+
"a named backreference is still a backreference — it cannot be " \
|
|
13
|
+
"matched in linear time ; a declared pattern may not depend on one",
|
|
14
|
+
perl_class:
|
|
15
|
+
"engines read it in OPPOSITE directions : ASCII in some and " \
|
|
16
|
+
"Unicode in others, so an Arabic-Indic digit satisfies one and not " \
|
|
17
|
+
"the other. Spell the range you mean — [0-9], [A-Za-z0-9_], [ \t] " \
|
|
18
|
+
"— which every engine reads the same way",
|
|
19
|
+
posix_class:
|
|
20
|
+
"[:digit:] and friends flip between ASCII and Unicode across " \
|
|
21
|
+
"engines — the mirror of the perl classes, and wrong in the same " \
|
|
22
|
+
"way. Spell the range you mean",
|
|
23
|
+
lookahead:
|
|
24
|
+
"lookahead cannot be matched in linear time and portable engines " \
|
|
25
|
+
"refuse it ; a declared pattern may not depend on it",
|
|
26
|
+
lookbehind:
|
|
27
|
+
"lookbehind cannot be matched in linear time and portable engines " \
|
|
28
|
+
"refuse it ; a declared pattern may not depend on it",
|
|
29
|
+
atomic_group:
|
|
30
|
+
"an atomic group is a backtracking-engine control knob — " \
|
|
31
|
+
"linear-time engines reject `(?>` as a syntax error",
|
|
32
|
+
possessive:
|
|
33
|
+
"a possessive quantifier is a backtracking-engine control knob — " \
|
|
34
|
+
"linear-time engines reject it as a syntax error"
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
# Spelled out, not derived from the key: callers read these strings in refusals.
|
|
38
|
+
CONSTRUCTS = {
|
|
39
|
+
backreference: "backreference",
|
|
40
|
+
named_backreference: "named backreference",
|
|
41
|
+
perl_class: "perl character class",
|
|
42
|
+
posix_class: "posix bracket class",
|
|
43
|
+
lookahead: "lookahead",
|
|
44
|
+
lookbehind: "lookbehind",
|
|
45
|
+
atomic_group: "atomic group",
|
|
46
|
+
possessive: "possessive quantifier"
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
module_function
|
|
50
|
+
|
|
51
|
+
def refuse(key) = Rejection.new(CONSTRUCTS.fetch(key), REASONS.fetch(key))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Bluebook
|
|
3
|
+
module PatternSubset
|
|
4
|
+
# A left-to-right reading position in a pattern's characters, tracking whether it is inside
|
|
5
|
+
# a `[...]` class: there quantifier characters are literals, and `]` closes the class
|
|
6
|
+
# unless it is the first character after `[` or `[^`.
|
|
7
|
+
class Scan
|
|
8
|
+
attr_reader :chars, :index
|
|
9
|
+
|
|
10
|
+
# @param chars [Array<String>] the pattern's characters
|
|
11
|
+
def initialize(chars)
|
|
12
|
+
@chars = chars
|
|
13
|
+
@index = 0
|
|
14
|
+
@in_class = false
|
|
15
|
+
@class_start = nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Boolean] whether every character has been read
|
|
19
|
+
def done? = @index >= @chars.length
|
|
20
|
+
|
|
21
|
+
# @return [String, nil] the character at the current position
|
|
22
|
+
def char = @chars[@index]
|
|
23
|
+
|
|
24
|
+
# @param offset [Integer] how far past the current position to look
|
|
25
|
+
# @return [String, nil] the character `offset` places ahead
|
|
26
|
+
def peek(offset = 1) = @chars[@index + offset]
|
|
27
|
+
|
|
28
|
+
# @return [Boolean] whether the position is inside a `[...]` class
|
|
29
|
+
def in_class? = @in_class
|
|
30
|
+
|
|
31
|
+
# @return [Boolean] whether the current `]` closes the open class
|
|
32
|
+
def closing_bracket? = char == "]" && @index != @class_start
|
|
33
|
+
|
|
34
|
+
# Reads `count` characters.
|
|
35
|
+
#
|
|
36
|
+
# @param count [Integer] how many characters to consume
|
|
37
|
+
# @return [String] the characters read, as text
|
|
38
|
+
def take(count = 1)
|
|
39
|
+
text = @chars[@index, count].join
|
|
40
|
+
@index += count
|
|
41
|
+
text
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Opens a class at the current `[`, without consuming it.
|
|
45
|
+
#
|
|
46
|
+
# @return [void]
|
|
47
|
+
def enter_class
|
|
48
|
+
@in_class = true
|
|
49
|
+
@class_start = @index + 1
|
|
50
|
+
@class_start += 1 if @chars[@class_start] == "^"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [void]
|
|
54
|
+
def leave_class = @in_class = false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|