hecks 2.8.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +50 -7
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +32 -100
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +149 -136
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +48 -38
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +16 -50
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +49 -67
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +39 -661
- data/lib/hecks/bluebook/hexagon.rb +18 -33
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +87 -352
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +122 -596
- data/lib/hecks/bluebook/pattern_subset.rb +49 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +27 -51
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +9 -99
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +5 -23
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +4 -6
- data/lib/hecks/cli/mcp.rb +5 -6
- data/lib/hecks/cli/model_check.rb +24 -88
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +223 -64
- data/lib/hecks/cli/project_diagrams.rb +4 -10
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +15 -61
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +7 -19
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -6
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +216 -73
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +14 -34
- data/lib/hecks/doors/handle.rb +206 -0
- data/lib/hecks/doors/json_door.rb +132 -0
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
- data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
- data/lib/hecks/doors/ruby_door.rb +77 -0
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +5 -72
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +23 -51
- data/lib/hecks/forms/app.rb +21 -76
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +31 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +19 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +47 -108
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +12 -44
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +40 -207
- data/lib/hecks/projections/deploy/lambda.rb +191 -708
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +3 -59
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +48 -147
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +22 -584
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +16 -43
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +13 -32
- data/lib/hecks/projections/reference.rb +4 -18
- data/lib/hecks/projections/rust_vocabulary.rb +13 -251
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +154 -400
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +5 -8
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +15 -9
- data/lib/hecks/release/runner/npm_publisher.rb +9 -53
- data/lib/hecks/release/runner/preflight.rb +29 -20
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +31 -23
- data/lib/hecks/release/runner.rb +60 -38
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +15 -39
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +50 -104
- data/lib/hecks/runtime/dispatcher.rb +134 -243
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +14 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +109 -194
- data/lib/hecks/runtime/outbox.rb +39 -262
- data/lib/hecks/runtime/policy_interpreter.rb +43 -202
- data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
- data/lib/hecks/runtime/query_interpreter.rb +122 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +28 -87
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +213 -227
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +156 -247
- data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +162 -760
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +15 -84
- data/lib/hecks/runtime.rb +35 -69
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +155 -582
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +52 -90
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +478 -12
- data/lib/hecks/facade/cli_door.rb +0 -178
- data/lib/hecks/facade/cli_runner.rb +0 -271
- data/lib/hecks/facade/handle.rb +0 -293
- data/lib/hecks/facade/json_door.rb +0 -247
- data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
- data/lib/hecks/facade/surface/chapter.rb +0 -116
- data/lib/hecks/facade/surface.rb +0 -61
- data/lib/hecks/mcp_door_scope.rb +0 -176
|
@@ -0,0 +1,1847 @@
|
|
|
1
|
+
Hecks.bluebook "Hecks" do
|
|
2
|
+
# Custodian: operating any domain. Each aggregate here is a concern a client runs against
|
|
3
|
+
# their own domain (ADR 0080, section 2).
|
|
4
|
+
|
|
5
|
+
aggregate "Introspection" do
|
|
6
|
+
description "A look at a booted domain, answered by the runtime without changing anything."
|
|
7
|
+
|
|
8
|
+
attribute :domain, DomainPath
|
|
9
|
+
identified_by :domain
|
|
10
|
+
|
|
11
|
+
value_object "DomainPath" do
|
|
12
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
13
|
+
|
|
14
|
+
invariant("a domain is named by its path") { !value.to_s.empty? }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
value_object "ChapterName" do
|
|
18
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
19
|
+
|
|
20
|
+
invariant("a chapter is named") { !value.to_s.empty? }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
value_object "AggregateName" do
|
|
24
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
25
|
+
|
|
26
|
+
invariant("an aggregate is named") { !value.to_s.empty? }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Each query below is answered by the DomainRuntime port's adapter: the domain is booted
|
|
30
|
+
# in-process and the answer is the exact text the matching bin script printed.
|
|
31
|
+
|
|
32
|
+
# An answer that is one document of text, exactly as the tool that produced it wrote it.
|
|
33
|
+
value_object "Document" do
|
|
34
|
+
attribute :text, String
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
query "Ir" do
|
|
38
|
+
description "The IR a domain's boot produces, as JSON: what golden specs pin and an era hashes."
|
|
39
|
+
attribute :domain, DomainPath, optional: true
|
|
40
|
+
attribute :translations, Boolean, optional: true
|
|
41
|
+
attribute :meta, Boolean, optional: true
|
|
42
|
+
returns Document
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
query "Shape" do
|
|
46
|
+
description "The storage shape an era's label is minted from: a bluebook file or a directory of them."
|
|
47
|
+
attribute :domain, DomainPath
|
|
48
|
+
returns Document
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
query "Stores" do
|
|
52
|
+
description "Every aggregate's current records: the head, not the journal."
|
|
53
|
+
attribute :domain, DomainPath
|
|
54
|
+
returns Document
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
query "History" do
|
|
58
|
+
description "Every journal entry a domain's append-only adapters hold: the whole write history."
|
|
59
|
+
attribute :domain, DomainPath
|
|
60
|
+
returns Document
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
query "Statements" do
|
|
64
|
+
description "A chapter's declared facts, as plain English sentences."
|
|
65
|
+
attribute :domain, DomainPath
|
|
66
|
+
attribute :chapter, ChapterName
|
|
67
|
+
returns Document
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
query "Narrate" do
|
|
71
|
+
description "A domain read back in English, whole or for one aggregate."
|
|
72
|
+
attribute :domain, DomainPath, optional: true
|
|
73
|
+
attribute :aggregate, AggregateName, optional: true
|
|
74
|
+
returns Document
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
query "Docs" do
|
|
78
|
+
description "A domain's usage document, whole or for one aggregate."
|
|
79
|
+
attribute :domain, DomainPath, optional: true
|
|
80
|
+
attribute :aggregate, AggregateName, optional: true
|
|
81
|
+
returns Document
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# One file a projection would have written, held as its name and its text.
|
|
85
|
+
value_object "ProjectedFile" do
|
|
86
|
+
attribute :name, String
|
|
87
|
+
attribute :text, String
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
query "ProjectDiagrams" do
|
|
91
|
+
description "A chapter's Mermaid diagrams, as file names mapped to their text; nothing is written."
|
|
92
|
+
attribute :domain, DomainPath
|
|
93
|
+
attribute :chapter, ChapterName
|
|
94
|
+
returns list_of(ProjectedFile)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
query "Glossary" do
|
|
98
|
+
description "A chapter's Ubiquitous Language glossary, as file names mapped to their text; nothing is written."
|
|
99
|
+
attribute :domain, DomainPath
|
|
100
|
+
attribute :chapter, ChapterName
|
|
101
|
+
returns list_of(ProjectedFile)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# A journaled command whose work happens outside the runtime (ADR 0080, section 11). Every
|
|
106
|
+
# command below that runs something follows this one shape, so later aggregates copy it:
|
|
107
|
+
#
|
|
108
|
+
# 1. A creating command records the request as a record in state "requested" and emits.
|
|
109
|
+
# 2. A policy on that event triggers an ask on one of the record's ports. The runtime hands
|
|
110
|
+
# the port's adapter the whole record, so the adapter does all the IO, and only there.
|
|
111
|
+
# 3. The adapter answers (a hash named like a command's arguments) or raises (its message
|
|
112
|
+
# is the refusal). One policy per outcome re-enters the record with a command that stores it.
|
|
113
|
+
#
|
|
114
|
+
# The ports are declared in hecks.hecksagon; each adapter is in adapters/.
|
|
115
|
+
|
|
116
|
+
aggregate "ModelCheckRun" do
|
|
117
|
+
description "One static analysis over domains' models, and what it found: a check's history."
|
|
118
|
+
|
|
119
|
+
attribute :run, RunKey
|
|
120
|
+
attribute :domains, DomainList, optional: true
|
|
121
|
+
attribute :profile, ProfileName, optional: true
|
|
122
|
+
attribute :strict, Switch, optional: true
|
|
123
|
+
attribute :report, Report, optional: true
|
|
124
|
+
attribute :refusal, Report, optional: true
|
|
125
|
+
identified_by :run
|
|
126
|
+
|
|
127
|
+
value_object "RunKey" do
|
|
128
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
129
|
+
|
|
130
|
+
invariant("a run is named") { !value.to_s.empty? }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
value_object "DomainList" do
|
|
134
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
value_object "ProfileName" do
|
|
138
|
+
attribute :value, String, pattern: '^client$'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
value_object "Switch" do
|
|
142
|
+
attribute :value, Boolean
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
value_object "Report" do
|
|
146
|
+
attribute :value, String
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
lifecycle :status, default: "requested" do
|
|
150
|
+
transition "Pass" => "clean", from: "requested"
|
|
151
|
+
transition "Flag" => "flagged", from: "requested"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
command "ModelCheck" do
|
|
155
|
+
role "Operator"
|
|
156
|
+
goal "Check domains for dead states and unreachable steps, and keep the verdict"
|
|
157
|
+
|
|
158
|
+
attribute :run, RunKey
|
|
159
|
+
attribute :domains, DomainList, optional: true
|
|
160
|
+
attribute :profile, ProfileName, optional: true
|
|
161
|
+
attribute :strict, Switch, optional: true
|
|
162
|
+
|
|
163
|
+
sets :run
|
|
164
|
+
sets :domains
|
|
165
|
+
sets :profile
|
|
166
|
+
sets :strict
|
|
167
|
+
|
|
168
|
+
emits ModelCheckRequested
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
command "Pass" do
|
|
172
|
+
role "System"
|
|
173
|
+
goal "Record that the analysis left no error"
|
|
174
|
+
|
|
175
|
+
reference_to ModelCheckRun
|
|
176
|
+
attribute :report, Report
|
|
177
|
+
|
|
178
|
+
sets :report
|
|
179
|
+
|
|
180
|
+
emits ModelCheckPassed
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
command "Flag" do
|
|
184
|
+
role "System"
|
|
185
|
+
goal "Record that the analysis found something, or could not run, and what it said"
|
|
186
|
+
|
|
187
|
+
reference_to ModelCheckRun
|
|
188
|
+
attribute :refusal, Report
|
|
189
|
+
|
|
190
|
+
sets :refusal
|
|
191
|
+
|
|
192
|
+
emits ModelCheckFlagged
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# `hecks model_check` answers once the request is recorded, so the verdict is read here.
|
|
196
|
+
query "Verdict" do
|
|
197
|
+
description "What one check found: its status, and the report or the reason it could not run."
|
|
198
|
+
attribute :run, RunKey
|
|
199
|
+
where(run: :run)
|
|
200
|
+
order_by :run
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
query "Flagged" do
|
|
204
|
+
description "Every check that left a finding or could not run."
|
|
205
|
+
where(status: "flagged")
|
|
206
|
+
order_by :run
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
policy "AnalyseWhenRequested" do
|
|
211
|
+
on "ModelCheckRun.ModelCheckRequested"
|
|
212
|
+
trigger ModelCheckRun::DomainRuntime::Check, with: { run: :run }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
policy "RecordTheClean" do
|
|
216
|
+
on "ModelCheckRun.ModelCheckAnswered"
|
|
217
|
+
trigger ModelCheckRun::Pass, with: { report: :report }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
policy "RecordTheFlag" do
|
|
221
|
+
on "ModelCheckRun.ModelCheckRefused"
|
|
222
|
+
trigger ModelCheckRun::Flag, with: { refusal: :refusal }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
aggregate "Operation" do
|
|
226
|
+
description "One thing an operator ran against a domain, and how it ended."
|
|
227
|
+
|
|
228
|
+
attribute :run, OperationKey
|
|
229
|
+
attribute :subject, Subject, optional: true
|
|
230
|
+
attribute :script, Script, optional: true
|
|
231
|
+
attribute :verb, Verb, optional: true
|
|
232
|
+
attribute :arguments, list_of(Word), optional: true
|
|
233
|
+
attribute :url, Address, optional: true
|
|
234
|
+
attribute :path, RoutePath, optional: true
|
|
235
|
+
attribute :header, HeaderName, optional: true
|
|
236
|
+
attribute :scheme, Scheme, optional: true
|
|
237
|
+
attribute :payload, Payload, optional: true
|
|
238
|
+
attribute :payload_file, PayloadFile, optional: true
|
|
239
|
+
attribute :health_path, RoutePath, optional: true
|
|
240
|
+
attribute :state_path, RoutePath, optional: true
|
|
241
|
+
attribute :output, Output, optional: true
|
|
242
|
+
attribute :refusal, Output, optional: true
|
|
243
|
+
identified_by :run
|
|
244
|
+
|
|
245
|
+
value_object "OperationKey" do
|
|
246
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
247
|
+
|
|
248
|
+
invariant("an operation is named") { !value.to_s.empty? }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# What the operation acts on: a domain directory, or a behaviors file or directory.
|
|
252
|
+
value_object "Subject" do
|
|
253
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
value_object "Script" do
|
|
257
|
+
attribute :value, String
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
value_object "Verb" do
|
|
261
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# One `name=value` word of the verb a run dispatches.
|
|
265
|
+
value_object "Word" do
|
|
266
|
+
attribute :value, String
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
value_object "Address" do
|
|
270
|
+
attribute :value, String, pattern: '^https?://'
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
value_object "RoutePath" do
|
|
274
|
+
attribute :value, String, pattern: '^/'
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
value_object "HeaderName" do
|
|
278
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
value_object "Scheme" do
|
|
282
|
+
attribute :value, String, pattern: '^(timestamped|sha256|hex)$'
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
value_object "Payload" do
|
|
286
|
+
attribute :value, String
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
value_object "PayloadFile" do
|
|
290
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
value_object "Output" do
|
|
294
|
+
attribute :value, String
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
lifecycle :status, default: "requested" do
|
|
298
|
+
transition "Succeed" => "succeeded", from: "requested"
|
|
299
|
+
transition "Fail" => "failed", from: "requested"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Runs one verb, or a JSON step list, against the domain: `hecks run [domain] script=steps.json`
|
|
303
|
+
# or `hecks run [domain] verb=create_pizza arguments=name.value=Margherita`. The signing secret
|
|
304
|
+
# for SmokeHttp is never an argument: it is read from SMOKE_WEBHOOK_SECRET.
|
|
305
|
+
command "Run" do
|
|
306
|
+
role "Operator"
|
|
307
|
+
goal "Dispatch a verb or a step list against a domain and keep what it reported"
|
|
308
|
+
|
|
309
|
+
attribute :run, OperationKey
|
|
310
|
+
attribute :subject, Subject, optional: true
|
|
311
|
+
attribute :script, Script, optional: true
|
|
312
|
+
attribute :verb, Verb, optional: true
|
|
313
|
+
attribute :arguments, list_of(Word), optional: true
|
|
314
|
+
|
|
315
|
+
given("exactly one of a script and a verb is named: pass script= or verb=, not both") do
|
|
316
|
+
(script.set? && verb.unset?) || (script.unset? && verb.set?)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
sets :run
|
|
320
|
+
sets :subject
|
|
321
|
+
sets :script
|
|
322
|
+
sets :verb
|
|
323
|
+
sets :arguments
|
|
324
|
+
|
|
325
|
+
emits RunRequested
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
command "RefreshProjections" do
|
|
329
|
+
role "Operator"
|
|
330
|
+
goal "Bring every read-model projection of a domain up to date now"
|
|
331
|
+
|
|
332
|
+
attribute :run, OperationKey
|
|
333
|
+
attribute :subject, Subject
|
|
334
|
+
|
|
335
|
+
sets :run
|
|
336
|
+
sets :subject
|
|
337
|
+
|
|
338
|
+
emits ProjectionsRefreshRequested
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
command "RunBehaviors" do
|
|
342
|
+
role "Operator"
|
|
343
|
+
goal "Run a domain's behavior tests and keep the verdict"
|
|
344
|
+
|
|
345
|
+
attribute :run, OperationKey
|
|
346
|
+
attribute :subject, Subject
|
|
347
|
+
|
|
348
|
+
sets :run
|
|
349
|
+
sets :subject
|
|
350
|
+
|
|
351
|
+
emits BehaviorsRequested
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
command "OpenConsole" do
|
|
355
|
+
role "Operator"
|
|
356
|
+
goal "Open an interactive console on a domain"
|
|
357
|
+
|
|
358
|
+
attribute :run, OperationKey
|
|
359
|
+
attribute :subject, Subject, optional: true
|
|
360
|
+
|
|
361
|
+
sets :run
|
|
362
|
+
sets :subject
|
|
363
|
+
|
|
364
|
+
emits ConsoleRequested
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
command "SmokeTest" do
|
|
368
|
+
role "Operator"
|
|
369
|
+
goal "Dispatch one synthesized call per command and report of a wired domain"
|
|
370
|
+
|
|
371
|
+
attribute :run, OperationKey
|
|
372
|
+
attribute :subject, Subject, optional: true
|
|
373
|
+
|
|
374
|
+
sets :run
|
|
375
|
+
sets :subject
|
|
376
|
+
|
|
377
|
+
emits SmokeTestRequested
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
command "SmokeHttp" do
|
|
381
|
+
role "Operator"
|
|
382
|
+
goal "Check that a running service refuses bad signatures and accepts a good one"
|
|
383
|
+
|
|
384
|
+
attribute :run, OperationKey
|
|
385
|
+
attribute :url, Address, optional: true
|
|
386
|
+
attribute :path, RoutePath
|
|
387
|
+
attribute :header, HeaderName, optional: true
|
|
388
|
+
attribute :scheme, Scheme, optional: true
|
|
389
|
+
attribute :payload, Payload, optional: true
|
|
390
|
+
attribute :payload_file, PayloadFile, optional: true
|
|
391
|
+
attribute :health_path, RoutePath, optional: true
|
|
392
|
+
attribute :state_path, RoutePath, optional: true
|
|
393
|
+
|
|
394
|
+
sets :run
|
|
395
|
+
sets :url
|
|
396
|
+
sets :path
|
|
397
|
+
sets :header
|
|
398
|
+
sets :scheme
|
|
399
|
+
sets :payload
|
|
400
|
+
sets :payload_file
|
|
401
|
+
sets :health_path
|
|
402
|
+
sets :state_path
|
|
403
|
+
|
|
404
|
+
emits SmokeHttpRequested
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
command "Succeed" do
|
|
408
|
+
role "System"
|
|
409
|
+
goal "Record that the operation ended well, and what it reported"
|
|
410
|
+
|
|
411
|
+
reference_to Operation
|
|
412
|
+
attribute :output, Output
|
|
413
|
+
|
|
414
|
+
sets :output
|
|
415
|
+
|
|
416
|
+
emits OperationSucceeded
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
command "Fail" do
|
|
420
|
+
role "System"
|
|
421
|
+
goal "Record that the operation was refused or found a problem, and what it said"
|
|
422
|
+
|
|
423
|
+
reference_to Operation
|
|
424
|
+
attribute :refusal, Output
|
|
425
|
+
|
|
426
|
+
sets :refusal
|
|
427
|
+
|
|
428
|
+
emits OperationFailed
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
query "Outcome" do
|
|
432
|
+
description "How one operation ended: its status, and what it reported or why it failed."
|
|
433
|
+
attribute :run, OperationKey
|
|
434
|
+
where(run: :run)
|
|
435
|
+
order_by :run
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
query "Failed" do
|
|
439
|
+
description "Every operation that was refused or found a problem."
|
|
440
|
+
where(status: "failed")
|
|
441
|
+
order_by :run
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# A follow's answer: the count to pass back as `since`, the entries past it, and when it looked.
|
|
445
|
+
value_object "Tail" do
|
|
446
|
+
attribute :cursor, Integer
|
|
447
|
+
attribute :events, list_of(FollowedEvent)
|
|
448
|
+
attribute :taken_at, String
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
# One entry of a persisted event log; the payload is its JSON text, since a value object
|
|
452
|
+
# holds no free-form map.
|
|
453
|
+
value_object "FollowedEvent" do
|
|
454
|
+
attribute :name, String
|
|
455
|
+
attribute :aggregate, String
|
|
456
|
+
attribute :id, String
|
|
457
|
+
attribute :payload, String
|
|
458
|
+
attribute :occurred_at, String
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
# A launcher answers once, so a follow is a bounded poll: it answers the entries past `since`
|
|
462
|
+
# and a `cursor` to pass as the next `since`, waiting up to `wait` seconds for the first one.
|
|
463
|
+
query "Follow" do
|
|
464
|
+
description "A domain's persisted event log past a cursor, for tailing it call by call."
|
|
465
|
+
attribute :domain, Subject
|
|
466
|
+
attribute :aggregate, Verb, optional: true
|
|
467
|
+
attribute :since, Integer, optional: true
|
|
468
|
+
attribute :from_now, Boolean, optional: true
|
|
469
|
+
attribute :wait, Integer, optional: true
|
|
470
|
+
attribute :interval, Float, optional: true
|
|
471
|
+
returns Tail
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
policy "RunWhenRequested" do
|
|
476
|
+
on "Operation.RunRequested"
|
|
477
|
+
trigger Operation::DomainRuntime::Execute, with: { run: :run }
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
policy "RefreshWhenRequested" do
|
|
481
|
+
on "Operation.ProjectionsRefreshRequested"
|
|
482
|
+
trigger Operation::DomainRuntime::Refresh, with: { run: :run }
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
policy "VerifyWhenRequested" do
|
|
486
|
+
on "Operation.BehaviorsRequested"
|
|
487
|
+
trigger Operation::DomainRuntime::Verify, with: { run: :run }
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
policy "SmokeWhenRequested" do
|
|
491
|
+
on "Operation.SmokeTestRequested"
|
|
492
|
+
trigger Operation::DomainRuntime::Smoke, with: { run: :run }
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
policy "OpenWhenRequested" do
|
|
496
|
+
on "Operation.ConsoleRequested"
|
|
497
|
+
trigger Operation::Terminal::Open, with: { run: :run }
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
policy "ProbeWhenRequested" do
|
|
501
|
+
on "Operation.SmokeHttpRequested"
|
|
502
|
+
trigger Operation::HostHttp::Probe, with: { run: :run }
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
policy "RecordTheOutput" do
|
|
506
|
+
on "Operation.OperationAnswered"
|
|
507
|
+
trigger Operation::Succeed, with: { output: :output }
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
policy "RecordTheFailure" do
|
|
511
|
+
on "Operation.OperationRefused"
|
|
512
|
+
trigger Operation::Fail, with: { refusal: :refusal }
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
aggregate "Host" do
|
|
516
|
+
description "A running rust/host, and the version and era it last reported."
|
|
517
|
+
|
|
518
|
+
attribute :host, Address
|
|
519
|
+
attribute :expected, ExpectedFile, optional: true
|
|
520
|
+
attribute :timeout, Seconds, optional: true
|
|
521
|
+
attribute :era, EraId, optional: true
|
|
522
|
+
attribute :version, VersionText, optional: true
|
|
523
|
+
attribute :report, Report, optional: true
|
|
524
|
+
attribute :refusal, Report, optional: true
|
|
525
|
+
identified_by :host
|
|
526
|
+
|
|
527
|
+
value_object "Address" do
|
|
528
|
+
attribute :value, String, pattern: '^https?://'
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
# The file listing the eras that should be running, one per line.
|
|
532
|
+
value_object "ExpectedFile" do
|
|
533
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
value_object "Seconds" do
|
|
537
|
+
attribute :value, Float
|
|
538
|
+
|
|
539
|
+
invariant("a timeout is positive") { value > 0 }
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
value_object "EraId" do
|
|
543
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
value_object "VersionText" do
|
|
547
|
+
attribute :value, String
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
value_object "Verdict" do
|
|
551
|
+
attribute :value, String, pattern: '^(match|unlisted|mismatch)$'
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
value_object "Report" do
|
|
555
|
+
attribute :value, String
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
lifecycle :status, default: "requested" do
|
|
559
|
+
transition "Recheck" => "requested", from: %w[observed drifted unreachable]
|
|
560
|
+
transition "Observe" => "observed", from: "requested"
|
|
561
|
+
transition "Drift" => "drifted", from: "requested"
|
|
562
|
+
transition "Lose" => "unreachable", from: "requested"
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
# `hecks check_era <url> expected=era-file [timeout=10]` records the first check of a host under
|
|
566
|
+
# its URL. A host is one record, and a creating command cannot repeat an identity, so a later
|
|
567
|
+
# check of the same host is `hecks recheck <url> expected=era-file`. Both are read with
|
|
568
|
+
# `hecks standing <url>`.
|
|
569
|
+
command "CheckEra" do
|
|
570
|
+
role "Operator"
|
|
571
|
+
goal "Ask a running host which era it reports, and keep whether it is one that should be running"
|
|
572
|
+
|
|
573
|
+
attribute :host, Address
|
|
574
|
+
attribute :expected, ExpectedFile
|
|
575
|
+
attribute :timeout, Seconds, optional: true
|
|
576
|
+
|
|
577
|
+
sets :host
|
|
578
|
+
sets :expected
|
|
579
|
+
sets :timeout
|
|
580
|
+
|
|
581
|
+
emits EraCheckRequested
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
command "Recheck" do
|
|
585
|
+
role "Operator"
|
|
586
|
+
goal "Ask a host already checked which era it reports now"
|
|
587
|
+
|
|
588
|
+
reference_to Host
|
|
589
|
+
attribute :expected, ExpectedFile
|
|
590
|
+
attribute :timeout, Seconds, optional: true
|
|
591
|
+
|
|
592
|
+
sets :expected
|
|
593
|
+
sets :timeout
|
|
594
|
+
|
|
595
|
+
emits EraRecheckRequested
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
# The host reported an era the list accepts, or a list that names none.
|
|
599
|
+
command "Observe" do
|
|
600
|
+
role "System"
|
|
601
|
+
goal "Record the version and era a running host reported"
|
|
602
|
+
|
|
603
|
+
reference_to Host
|
|
604
|
+
attribute :era, EraId
|
|
605
|
+
attribute :version, VersionText
|
|
606
|
+
attribute :report, Report
|
|
607
|
+
|
|
608
|
+
sets :era
|
|
609
|
+
sets :version
|
|
610
|
+
sets :report
|
|
611
|
+
|
|
612
|
+
emits EraObserved
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
# The host reported an era that is not on the list: the finding the roll must stop on.
|
|
616
|
+
command "Drift" do
|
|
617
|
+
role "System"
|
|
618
|
+
goal "Record that a running host reports an era that should not be running"
|
|
619
|
+
|
|
620
|
+
reference_to Host
|
|
621
|
+
attribute :era, EraId
|
|
622
|
+
attribute :version, VersionText
|
|
623
|
+
attribute :report, Report
|
|
624
|
+
|
|
625
|
+
sets :era
|
|
626
|
+
sets :version
|
|
627
|
+
sets :report
|
|
628
|
+
|
|
629
|
+
emits EraDrifted
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
command "Lose" do
|
|
633
|
+
role "System"
|
|
634
|
+
goal "Record that the host could not be reached, or answered no era, and what was said"
|
|
635
|
+
|
|
636
|
+
reference_to Host
|
|
637
|
+
attribute :refusal, Report
|
|
638
|
+
|
|
639
|
+
sets :refusal
|
|
640
|
+
|
|
641
|
+
emits HostLost
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
query "Standing" do
|
|
645
|
+
description "What one check of a host found: its status, era and version, or why it failed."
|
|
646
|
+
attribute :host, Address
|
|
647
|
+
where(host: :host)
|
|
648
|
+
order_by :host
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
query "Drifted" do
|
|
652
|
+
description "Every host that reported an era that should not be running."
|
|
653
|
+
where(status: "drifted")
|
|
654
|
+
order_by :host
|
|
655
|
+
end
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
policy "FetchWhenChecked" do
|
|
659
|
+
on "Host.EraCheckRequested"
|
|
660
|
+
trigger Host::HostHttp::Fetch, with: { host: :host }
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
policy "FetchWhenRechecked" do
|
|
664
|
+
on "Host.EraRecheckRequested"
|
|
665
|
+
trigger Host::HostHttp::Fetch, with: { host: :host }
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
policy "RecordTheEra" do
|
|
669
|
+
on "Host.EraReported"
|
|
670
|
+
where { verdict.value != "mismatch" }
|
|
671
|
+
trigger Host::Observe, with: { era: :era, version: :version, report: :report }
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
policy "RecordTheDrift" do
|
|
675
|
+
on "Host.EraReported"
|
|
676
|
+
where { verdict.value == "mismatch" }
|
|
677
|
+
trigger Host::Drift, with: { era: :era, version: :version, report: :report }
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
policy "RecordTheLostHost" do
|
|
681
|
+
on "Host.HostRefused"
|
|
682
|
+
trigger Host::Lose, with: { refusal: :refusal }
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
aggregate "Era" do
|
|
686
|
+
description "One change to a domain's journal of eras, and how it ended: a store's upkeep."
|
|
687
|
+
|
|
688
|
+
attribute :run, RunKey
|
|
689
|
+
attribute :domain, DomainPath
|
|
690
|
+
attribute :operation, OperationName, optional: true
|
|
691
|
+
attribute :winners, WinnerList, optional: true
|
|
692
|
+
attribute :era, Ordinal, optional: true
|
|
693
|
+
attribute :aggregates, AggregateList, optional: true
|
|
694
|
+
attribute :confirm, Switch, optional: true
|
|
695
|
+
attribute :snapshot, Snapshot, optional: true
|
|
696
|
+
attribute :host_version, HostVersion, optional: true
|
|
697
|
+
attribute :rehearsal, Verdict, optional: true
|
|
698
|
+
attribute :rehearsed_at, Moment, optional: true
|
|
699
|
+
attribute :capable, Switch, optional: true
|
|
700
|
+
attribute :held, Count, optional: true
|
|
701
|
+
attribute :forks, Count, optional: true
|
|
702
|
+
attribute :contested, Count, optional: true
|
|
703
|
+
attribute :edges, Count, optional: true
|
|
704
|
+
attribute :bound, Count, optional: true
|
|
705
|
+
attribute :candidates, Count, optional: true
|
|
706
|
+
attribute :audited, Switch, optional: true
|
|
707
|
+
attribute :rehearsal_needed, Switch, optional: true
|
|
708
|
+
attribute :rehearsal_recorded, Switch, optional: true
|
|
709
|
+
attribute :drifted, Switch, optional: true
|
|
710
|
+
attribute :loadable, Switch, optional: true
|
|
711
|
+
attribute :shape_kept, Switch, optional: true
|
|
712
|
+
attribute :report, Report, optional: true
|
|
713
|
+
attribute :refusal, Report, optional: true
|
|
714
|
+
identified_by :run
|
|
715
|
+
|
|
716
|
+
value_object "RunKey" do
|
|
717
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
718
|
+
|
|
719
|
+
invariant("a change is named") { !value.to_s.empty? }
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
# The domain whose journal is changed: its directory.
|
|
723
|
+
value_object "DomainPath" do
|
|
724
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
value_object "OperationName" do
|
|
728
|
+
attribute :value, String,
|
|
729
|
+
pattern: '^(hold_first|merge_tail|reattest|backfill_projections|compact|compact_heki|approve_translation)$'
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
# `id:old,id:new`: which world's record wins for each id both worlds touched since the cut.
|
|
733
|
+
value_object "WinnerList" do
|
|
734
|
+
attribute :value, String, pattern: '^[^ \t\n\r,]+:(old|new)(,[^ \t\n\r,]+:(old|new))*$'
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
value_object "Ordinal" do
|
|
738
|
+
attribute :value, Integer
|
|
739
|
+
|
|
740
|
+
invariant("an era is counted from one") { value > 0 }
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
# Aggregate names, comma separated; every aggregate that keeps a journal when absent.
|
|
744
|
+
value_object "AggregateList" do
|
|
745
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
value_object "Switch" do
|
|
749
|
+
attribute :value, Boolean
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
value_object "Count" do
|
|
753
|
+
attribute :value, Integer
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
# The rehearsal a compute or rekey edge is approved on: the snapshot it ran against, the host
|
|
757
|
+
# that ran it, whether it passed, and when.
|
|
758
|
+
value_object "Snapshot" do
|
|
759
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
value_object "HostVersion" do
|
|
763
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
value_object "Verdict" do
|
|
767
|
+
attribute :value, String, pattern: '^(pass|fail)$'
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
value_object "Moment" do
|
|
771
|
+
attribute :value, String, pattern: '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[^ \t\n\r]+$'
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
value_object "Report" do
|
|
775
|
+
attribute :value, String
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
lifecycle :status, default: "requested" do
|
|
779
|
+
transition "Permit" => "admitted", from: "requested"
|
|
780
|
+
transition "Settle" => "settled", from: "admitted"
|
|
781
|
+
transition "Abandon" => "refused", from: %w[requested admitted]
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
# The seven requests. Each records what was asked and names its operation; the journal store
|
|
785
|
+
# then examines the domain and reports facts (`EraExamined`), `Permit` holds the rules that need
|
|
786
|
+
# those facts, and only an admitted change is made (`EraChanged`). A change that changes
|
|
787
|
+
# something needs an explicit `--confirm`.
|
|
788
|
+
command "HoldFirst" do
|
|
789
|
+
role "Operator"
|
|
790
|
+
goal "Hold the first era of a domain that holds none, as its first boot would"
|
|
791
|
+
|
|
792
|
+
attribute :domain, DomainPath
|
|
793
|
+
attribute :run, RunKey
|
|
794
|
+
attribute :confirm, Switch, optional: true
|
|
795
|
+
|
|
796
|
+
given("holding the first era is confirmed") { confirm.value == true }
|
|
797
|
+
|
|
798
|
+
sets :domain
|
|
799
|
+
sets :run
|
|
800
|
+
sets :confirm
|
|
801
|
+
sets :operation, to: "hold_first"
|
|
802
|
+
|
|
803
|
+
emits FirstEraRequested
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
command "MergeTail" do
|
|
807
|
+
role "Operator"
|
|
808
|
+
goal "Interleave the old world's writes since the cut into the live head, by their ordinals"
|
|
809
|
+
|
|
810
|
+
attribute :domain, DomainPath
|
|
811
|
+
attribute :run, RunKey
|
|
812
|
+
attribute :winners, WinnerList, optional: true
|
|
813
|
+
attribute :confirm, Switch, optional: true
|
|
814
|
+
|
|
815
|
+
given("the merge is confirmed") { confirm.value == true }
|
|
816
|
+
|
|
817
|
+
sets :domain
|
|
818
|
+
sets :run
|
|
819
|
+
sets :winners
|
|
820
|
+
sets :confirm
|
|
821
|
+
sets :operation, to: "merge_tail"
|
|
822
|
+
|
|
823
|
+
emits TailMergeRequested
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
command "Reattest" do
|
|
827
|
+
role "Operator"
|
|
828
|
+
goal "Freeze an era's held text as it now stands, after a person has read it"
|
|
829
|
+
|
|
830
|
+
attribute :domain, DomainPath
|
|
831
|
+
attribute :era, Ordinal
|
|
832
|
+
attribute :run, RunKey
|
|
833
|
+
attribute :confirm, Switch, optional: true
|
|
834
|
+
|
|
835
|
+
given("the text is accepted as the era's own") { confirm.value == true }
|
|
836
|
+
|
|
837
|
+
sets :domain
|
|
838
|
+
sets :era
|
|
839
|
+
sets :run
|
|
840
|
+
sets :confirm
|
|
841
|
+
sets :operation, to: "reattest"
|
|
842
|
+
|
|
843
|
+
emits ReattestRequested
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
command "BackfillProjections" do
|
|
847
|
+
role "Operator"
|
|
848
|
+
goal "Store the shape every held era froze with, for the eras that predate it"
|
|
849
|
+
|
|
850
|
+
attribute :domain, DomainPath
|
|
851
|
+
attribute :run, RunKey
|
|
852
|
+
|
|
853
|
+
sets :domain
|
|
854
|
+
sets :run
|
|
855
|
+
sets :operation, to: "backfill_projections"
|
|
856
|
+
|
|
857
|
+
emits BackfillRequested
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
command "Compact" do
|
|
861
|
+
role "Operator"
|
|
862
|
+
goal "Delete the journal entries a Postgres or Sqlite aggregate has already projected"
|
|
863
|
+
|
|
864
|
+
attribute :domain, DomainPath
|
|
865
|
+
attribute :aggregates, AggregateList, optional: true
|
|
866
|
+
attribute :run, RunKey
|
|
867
|
+
attribute :confirm, Switch, optional: true
|
|
868
|
+
|
|
869
|
+
given("the compaction is confirmed") { confirm.value == true }
|
|
870
|
+
|
|
871
|
+
sets :domain
|
|
872
|
+
sets :aggregates
|
|
873
|
+
sets :run
|
|
874
|
+
sets :confirm
|
|
875
|
+
sets :operation, to: "compact"
|
|
876
|
+
|
|
877
|
+
emits CompactionRequested
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
command "CompactHeki" do
|
|
881
|
+
role "Operator"
|
|
882
|
+
goal "Empty a Heki aggregate's journal, keeping the snapshot"
|
|
883
|
+
|
|
884
|
+
attribute :domain, DomainPath
|
|
885
|
+
attribute :aggregates, AggregateList, optional: true
|
|
886
|
+
attribute :run, RunKey
|
|
887
|
+
attribute :confirm, Switch, optional: true
|
|
888
|
+
|
|
889
|
+
given("the compaction is confirmed") { confirm.value == true }
|
|
890
|
+
|
|
891
|
+
sets :domain
|
|
892
|
+
sets :aggregates
|
|
893
|
+
sets :run
|
|
894
|
+
sets :confirm
|
|
895
|
+
sets :operation, to: "compact_heki"
|
|
896
|
+
|
|
897
|
+
emits HekiCompactionRequested
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
# Writes `translations/<edge>.approval` beside the edge, for the host to apply at its next
|
|
901
|
+
# boot. An edge with a compute or rekey rule also needs the rehearsal a person ran by hand.
|
|
902
|
+
command "ApproveTranslation" do
|
|
903
|
+
role "Operator"
|
|
904
|
+
goal "Approve the edge that leads a domain's latest era to its current shape, in a committed file"
|
|
905
|
+
|
|
906
|
+
attribute :domain, DomainPath
|
|
907
|
+
attribute :run, RunKey
|
|
908
|
+
attribute :confirm, Switch, optional: true
|
|
909
|
+
attribute :snapshot, Snapshot, optional: true
|
|
910
|
+
attribute :host_version, HostVersion, optional: true
|
|
911
|
+
attribute :rehearsal, Verdict, optional: true
|
|
912
|
+
attribute :rehearsed_at, Moment, optional: true
|
|
913
|
+
|
|
914
|
+
given("the approval is confirmed") { confirm.value == true }
|
|
915
|
+
|
|
916
|
+
sets :domain
|
|
917
|
+
sets :run
|
|
918
|
+
sets :confirm
|
|
919
|
+
sets :snapshot
|
|
920
|
+
sets :host_version
|
|
921
|
+
sets :rehearsal
|
|
922
|
+
sets :rehearsed_at
|
|
923
|
+
sets :operation, to: "approve_translation"
|
|
924
|
+
|
|
925
|
+
emits ApprovalRequested
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
# The facts the journal store reported, held against the change that was asked for.
|
|
929
|
+
command "Permit" do
|
|
930
|
+
role "System"
|
|
931
|
+
goal "Let a change through only when what was found in the journal allows it"
|
|
932
|
+
|
|
933
|
+
reference_to Era
|
|
934
|
+
attribute :capable, Switch
|
|
935
|
+
attribute :held, Count
|
|
936
|
+
attribute :forks, Count
|
|
937
|
+
attribute :contested, Count
|
|
938
|
+
attribute :edges, Count
|
|
939
|
+
attribute :bound, Count
|
|
940
|
+
attribute :candidates, Count
|
|
941
|
+
attribute :audited, Switch
|
|
942
|
+
attribute :rehearsal_needed, Switch
|
|
943
|
+
attribute :rehearsal_recorded, Switch
|
|
944
|
+
attribute :drifted, Switch
|
|
945
|
+
attribute :loadable, Switch
|
|
946
|
+
attribute :shape_kept, Switch
|
|
947
|
+
|
|
948
|
+
given("the store keeps eras") do
|
|
949
|
+
capable.value || operation.value == "compact" || operation.value == "compact_heki"
|
|
950
|
+
end
|
|
951
|
+
given("no era is held yet") { operation.value != "hold_first" || held.value == 0 }
|
|
952
|
+
given("an era beyond the first stands before a tail is merged") do
|
|
953
|
+
operation.value != "merge_tail" || held.value > 1
|
|
954
|
+
end
|
|
955
|
+
given("exactly one edge leaves each era") { operation.value != "merge_tail" || forks.value == 0 }
|
|
956
|
+
given("every record both worlds touched has a named winner") do
|
|
957
|
+
operation.value != "merge_tail" || contested.value == 0
|
|
958
|
+
end
|
|
959
|
+
given("an aggregate matches") do
|
|
960
|
+
(operation.value != "compact" && operation.value != "compact_heki") || candidates.value > 0
|
|
961
|
+
end
|
|
962
|
+
given("no projection reads the journal that would be emptied") do
|
|
963
|
+
(operation.value != "compact" && operation.value != "compact_heki") || bound.value == 0
|
|
964
|
+
end
|
|
965
|
+
given("exactly one edge leaves the latest era") do
|
|
966
|
+
operation.value != "approve_translation" || edges.value == 1
|
|
967
|
+
end
|
|
968
|
+
given("the audit passed") { operation.value != "approve_translation" || audited.value }
|
|
969
|
+
given("a rehearsal that passed is recorded for an edge with a compute or rekey rule") do
|
|
970
|
+
operation.value != "approve_translation" || !rehearsal_needed.value || rehearsal_recorded.value
|
|
971
|
+
end
|
|
972
|
+
given("the held text no longer matches its digest: there is nothing to re-attest") do
|
|
973
|
+
operation.value != "reattest" || drifted.value
|
|
974
|
+
end
|
|
975
|
+
given("the edited text loads as a bluebook: restore a loadable text") do
|
|
976
|
+
operation.value != "reattest" || loadable.value
|
|
977
|
+
end
|
|
978
|
+
given("the edit kept the era's shape, not just its text: restore a text with the original shape") do
|
|
979
|
+
operation.value != "reattest" || shape_kept.value
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
sets :capable
|
|
983
|
+
sets :held
|
|
984
|
+
sets :forks
|
|
985
|
+
sets :contested
|
|
986
|
+
sets :edges
|
|
987
|
+
sets :bound
|
|
988
|
+
sets :candidates
|
|
989
|
+
sets :audited
|
|
990
|
+
sets :rehearsal_needed
|
|
991
|
+
sets :rehearsal_recorded
|
|
992
|
+
sets :drifted
|
|
993
|
+
sets :loadable
|
|
994
|
+
sets :shape_kept
|
|
995
|
+
|
|
996
|
+
emits EraPermitted
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
command "Settle" do
|
|
1000
|
+
role "System"
|
|
1001
|
+
goal "Record that the admitted change was made, and what it did"
|
|
1002
|
+
|
|
1003
|
+
reference_to Era
|
|
1004
|
+
attribute :report, Report
|
|
1005
|
+
|
|
1006
|
+
sets :report
|
|
1007
|
+
|
|
1008
|
+
emits EraSettled
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
command "Abandon" do
|
|
1012
|
+
role "System"
|
|
1013
|
+
goal "Record that the change was refused, or could not be made, and why"
|
|
1014
|
+
|
|
1015
|
+
reference_to Era
|
|
1016
|
+
attribute :refusal, Report
|
|
1017
|
+
|
|
1018
|
+
sets :refusal
|
|
1019
|
+
|
|
1020
|
+
emits EraAbandoned
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
query "Settlement" do
|
|
1024
|
+
description "What one change did: its status, and the report or the reason it was refused."
|
|
1025
|
+
attribute :run, RunKey
|
|
1026
|
+
where(run: :run)
|
|
1027
|
+
order_by :run
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
query "Abandoned" do
|
|
1031
|
+
description "Every change that was refused or could not be made."
|
|
1032
|
+
where(status: "refused")
|
|
1033
|
+
order_by :run
|
|
1034
|
+
end
|
|
1035
|
+
|
|
1036
|
+
# An answer that is one document of text, exactly as the tool that produced it wrote it.
|
|
1037
|
+
value_object "Document" do
|
|
1038
|
+
attribute :text, String
|
|
1039
|
+
end
|
|
1040
|
+
|
|
1041
|
+
# The reads that used to write. None holds an era or names one: a domain that holds no era
|
|
1042
|
+
# answers "no era held yet", and `hold_first` is the only thing that holds the first.
|
|
1043
|
+
query "ScaffoldTranslation" do
|
|
1044
|
+
description "The edge file that would lead the latest held era to the current shape."
|
|
1045
|
+
attribute :domain, DomainPath
|
|
1046
|
+
returns Document
|
|
1047
|
+
end
|
|
1048
|
+
|
|
1049
|
+
query "AuditTranslation" do
|
|
1050
|
+
description "The audit of the edge that leads the latest held era to the current shape."
|
|
1051
|
+
attribute :domain, DomainPath
|
|
1052
|
+
returns Document
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
query "Attestation" do
|
|
1056
|
+
description "An era's held text as it now stands, and whether it still matches its digest."
|
|
1057
|
+
attribute :domain, DomainPath
|
|
1058
|
+
attribute :era, Ordinal
|
|
1059
|
+
returns Document
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
query "Compaction" do
|
|
1063
|
+
description "What compacting the domain's journals would delete, without deleting it."
|
|
1064
|
+
attribute :domain, DomainPath
|
|
1065
|
+
attribute :aggregates, AggregateList, optional: true
|
|
1066
|
+
returns Document
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
policy "ExamineWhenFirstEraRequested" do
|
|
1071
|
+
on "Era.FirstEraRequested"
|
|
1072
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1073
|
+
end
|
|
1074
|
+
|
|
1075
|
+
policy "ExamineWhenTailMergeRequested" do
|
|
1076
|
+
on "Era.TailMergeRequested"
|
|
1077
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
policy "ExamineWhenReattestRequested" do
|
|
1081
|
+
on "Era.ReattestRequested"
|
|
1082
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
policy "ExamineWhenBackfillRequested" do
|
|
1086
|
+
on "Era.BackfillRequested"
|
|
1087
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
policy "ExamineWhenCompactionRequested" do
|
|
1091
|
+
on "Era.CompactionRequested"
|
|
1092
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1093
|
+
end
|
|
1094
|
+
|
|
1095
|
+
policy "ExamineWhenHekiCompactionRequested" do
|
|
1096
|
+
on "Era.HekiCompactionRequested"
|
|
1097
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
policy "ExamineWhenApprovalRequested" do
|
|
1101
|
+
on "Era.ApprovalRequested"
|
|
1102
|
+
trigger Era::JournalStore::Examine, with: { run: :run }
|
|
1103
|
+
end
|
|
1104
|
+
|
|
1105
|
+
policy "PermitWhenExamined" do
|
|
1106
|
+
on "Era.EraExamined"
|
|
1107
|
+
trigger Era::Permit, with: {
|
|
1108
|
+
capable: :capable, held: :held, forks: :forks, contested: :contested, edges: :edges,
|
|
1109
|
+
bound: :bound, candidates: :candidates, audited: :audited,
|
|
1110
|
+
rehearsal_needed: :rehearsal_needed, rehearsal_recorded: :rehearsal_recorded,
|
|
1111
|
+
drifted: :drifted, loadable: :loadable, shape_kept: :shape_kept
|
|
1112
|
+
}
|
|
1113
|
+
end
|
|
1114
|
+
|
|
1115
|
+
# `Permit` refuses when a rule is unmet and emits nothing, so this reaction is its complement:
|
|
1116
|
+
# it holds the same rules negated, so an examined change that is not let through is abandoned
|
|
1117
|
+
# rather than left `requested`.
|
|
1118
|
+
policy "AbandonWhenNotPermitted" do
|
|
1119
|
+
on "Era.EraExamined"
|
|
1120
|
+
where do
|
|
1121
|
+
(!capable.value && operation.value != "compact" && operation.value != "compact_heki") ||
|
|
1122
|
+
(operation.value == "hold_first" && held.value != 0) ||
|
|
1123
|
+
(operation.value == "merge_tail" && (held.value <= 1 || forks.value != 0 || contested.value != 0)) ||
|
|
1124
|
+
((operation.value == "compact" || operation.value == "compact_heki") &&
|
|
1125
|
+
(candidates.value <= 0 || bound.value != 0)) ||
|
|
1126
|
+
(operation.value == "approve_translation" &&
|
|
1127
|
+
(edges.value != 1 || !audited.value || (rehearsal_needed.value && !rehearsal_recorded.value))) ||
|
|
1128
|
+
(operation.value == "reattest" && (!drifted.value || !loadable.value || !shape_kept.value))
|
|
1129
|
+
end
|
|
1130
|
+
trigger Era::Abandon, with: { refusal: "the journal's facts do not admit this change" }
|
|
1131
|
+
end
|
|
1132
|
+
|
|
1133
|
+
policy "ChangeWhenPermitted" do
|
|
1134
|
+
on "Era.EraPermitted"
|
|
1135
|
+
trigger Era::JournalStore::Apply, with: { run: :run }
|
|
1136
|
+
end
|
|
1137
|
+
|
|
1138
|
+
policy "RecordTheChange" do
|
|
1139
|
+
on "Era.EraChanged"
|
|
1140
|
+
trigger Era::Settle, with: { report: :report }
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
policy "RecordTheRefusedChange" do
|
|
1144
|
+
on "Era.EraRefused"
|
|
1145
|
+
trigger Era::Abandon, with: { refusal: :refusal }
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
aggregate "Package" do
|
|
1149
|
+
description "One package of the bluebook registry, vendored into a project and pinned."
|
|
1150
|
+
|
|
1151
|
+
attribute :package, PackageRef
|
|
1152
|
+
attribute :from, Location, optional: true
|
|
1153
|
+
attribute :root, Location, optional: true
|
|
1154
|
+
attribute :report, Report, optional: true
|
|
1155
|
+
attribute :refusal, Report, optional: true
|
|
1156
|
+
identified_by :package
|
|
1157
|
+
|
|
1158
|
+
# `name` for the newest release, `name@1.2.0` for one release, `name@9f2c1ab` for a commit.
|
|
1159
|
+
value_object "PackageRef" do
|
|
1160
|
+
attribute :value, String, pattern: '^[a-z][a-z0-9_]*(@[^ \t\n\r]+)?$'
|
|
1161
|
+
|
|
1162
|
+
invariant("a package is named") { !value.to_s.empty? }
|
|
1163
|
+
end
|
|
1164
|
+
|
|
1165
|
+
# A directory: the source repository (`from`), or the project the files land in (`root`).
|
|
1166
|
+
value_object "Location" do
|
|
1167
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1168
|
+
end
|
|
1169
|
+
|
|
1170
|
+
value_object "Report" do
|
|
1171
|
+
attribute :value, String
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
lifecycle :status, default: "requested" do
|
|
1175
|
+
transition "Revendor" => "requested", from: %w[vendored refused]
|
|
1176
|
+
transition "Complete" => "vendored", from: "requested"
|
|
1177
|
+
transition "Abandon" => "refused", from: "requested"
|
|
1178
|
+
end
|
|
1179
|
+
|
|
1180
|
+
# `hecks vendor <package[@version]> [from=path] [root=path]`. The record is named by what was
|
|
1181
|
+
# asked for, so a release is one record; vendoring the same spelling again is `hecks revendor`.
|
|
1182
|
+
# `from` defaults to $EMBRYONAUT_BLUEBOOKS_SRC and `root` to the current directory, both read by
|
|
1183
|
+
# the adapter.
|
|
1184
|
+
command "Vendor" do
|
|
1185
|
+
role "Operator"
|
|
1186
|
+
goal "Pin a package of the bluebook registry into this project, at a release or a commit"
|
|
1187
|
+
|
|
1188
|
+
attribute :package, PackageRef
|
|
1189
|
+
attribute :from, Location, optional: true
|
|
1190
|
+
attribute :root, Location, optional: true
|
|
1191
|
+
|
|
1192
|
+
sets :package
|
|
1193
|
+
sets :from
|
|
1194
|
+
sets :root
|
|
1195
|
+
|
|
1196
|
+
emits VendorRequested
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
command "Revendor" do
|
|
1200
|
+
role "Operator"
|
|
1201
|
+
goal "Pin a package that was vendored before again, for the newest release or the same one"
|
|
1202
|
+
|
|
1203
|
+
reference_to Package
|
|
1204
|
+
attribute :from, Location, optional: true
|
|
1205
|
+
attribute :root, Location, optional: true
|
|
1206
|
+
|
|
1207
|
+
sets :from
|
|
1208
|
+
sets :root
|
|
1209
|
+
|
|
1210
|
+
emits RevendorRequested
|
|
1211
|
+
end
|
|
1212
|
+
|
|
1213
|
+
command "Complete" do
|
|
1214
|
+
role "System"
|
|
1215
|
+
goal "Record that the package was pinned, and what changed"
|
|
1216
|
+
|
|
1217
|
+
reference_to Package
|
|
1218
|
+
attribute :report, Report
|
|
1219
|
+
|
|
1220
|
+
sets :report
|
|
1221
|
+
|
|
1222
|
+
emits PackageVendored
|
|
1223
|
+
end
|
|
1224
|
+
|
|
1225
|
+
command "Abandon" do
|
|
1226
|
+
role "System"
|
|
1227
|
+
goal "Record that the package could not be pinned, and why"
|
|
1228
|
+
|
|
1229
|
+
reference_to Package
|
|
1230
|
+
attribute :refusal, Report
|
|
1231
|
+
|
|
1232
|
+
sets :refusal
|
|
1233
|
+
|
|
1234
|
+
emits VendoringRefused
|
|
1235
|
+
end
|
|
1236
|
+
|
|
1237
|
+
query "Pinning" do
|
|
1238
|
+
description "What vendoring one package did: its status, and the report or the refusal."
|
|
1239
|
+
attribute :package, PackageRef
|
|
1240
|
+
where(package: :package)
|
|
1241
|
+
order_by :package
|
|
1242
|
+
end
|
|
1243
|
+
|
|
1244
|
+
query "Unpinned" do
|
|
1245
|
+
description "Every package the last vendoring of which was refused."
|
|
1246
|
+
where(status: "refused")
|
|
1247
|
+
order_by :package
|
|
1248
|
+
end
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
policy "PinWhenVendored" do
|
|
1252
|
+
on "Package.VendorRequested"
|
|
1253
|
+
trigger Package::Git::Pin, with: { package: :package }
|
|
1254
|
+
end
|
|
1255
|
+
|
|
1256
|
+
policy "PinWhenRevendored" do
|
|
1257
|
+
on "Package.RevendorRequested"
|
|
1258
|
+
trigger Package::Git::Pin, with: { package: :package }
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
policy "RecordThePinning" do
|
|
1262
|
+
on "Package.PackagePinned"
|
|
1263
|
+
trigger Package::Complete, with: { report: :report }
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
policy "RecordTheRefusedPin" do
|
|
1267
|
+
on "Package.PinRefused"
|
|
1268
|
+
trigger Package::Abandon, with: { refusal: :refusal }
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
# A run record for opening a door onto the framework, not a door: the doors live in `Hecks::Doors`.
|
|
1272
|
+
aggregate "Door" do
|
|
1273
|
+
description "A way into the framework opened for a project: its launchers, or an MCP server."
|
|
1274
|
+
|
|
1275
|
+
attribute :run, DoorKey
|
|
1276
|
+
attribute :domains, DomainList, optional: true
|
|
1277
|
+
attribute :stdio, Switch, optional: true
|
|
1278
|
+
attribute :output, Note, optional: true
|
|
1279
|
+
attribute :refusal, Note, optional: true
|
|
1280
|
+
identified_by :run
|
|
1281
|
+
|
|
1282
|
+
value_object "DoorKey" do
|
|
1283
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
1284
|
+
|
|
1285
|
+
invariant("a door is named") { !value.to_s.empty? }
|
|
1286
|
+
end
|
|
1287
|
+
|
|
1288
|
+
# Domain directories under the project, comma separated.
|
|
1289
|
+
value_object "DomainList" do
|
|
1290
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1291
|
+
end
|
|
1292
|
+
|
|
1293
|
+
value_object "Switch" do
|
|
1294
|
+
attribute :value, Boolean
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1297
|
+
value_object "Note" do
|
|
1298
|
+
attribute :value, String
|
|
1299
|
+
end
|
|
1300
|
+
|
|
1301
|
+
lifecycle :status, default: "requested" do
|
|
1302
|
+
transition "Finish" => "finished", from: "requested"
|
|
1303
|
+
transition "Stop" => "stopped", from: "requested"
|
|
1304
|
+
end
|
|
1305
|
+
|
|
1306
|
+
# Writes a launcher beside each domain. It replaces the generated launcher already there and
|
|
1307
|
+
# deletes nothing, so it runs without `confirm` (`hecks project_cli` never asked for one).
|
|
1308
|
+
command "ProjectCli" do
|
|
1309
|
+
role "Operator"
|
|
1310
|
+
goal "Write a command-line launcher beside each domain of this project"
|
|
1311
|
+
|
|
1312
|
+
attribute :run, DoorKey
|
|
1313
|
+
attribute :domains, DomainList, optional: true
|
|
1314
|
+
|
|
1315
|
+
sets :run
|
|
1316
|
+
sets :domains
|
|
1317
|
+
|
|
1318
|
+
emits LaunchersRequested
|
|
1319
|
+
end
|
|
1320
|
+
|
|
1321
|
+
# A stdio server runs until its client closes stdin, so it cannot be asked and answered
|
|
1322
|
+
# quickly like the others. The command records that the door was started; the Terminal
|
|
1323
|
+
# adapter hands the process over to the door and answers when it closes, as OpenConsole
|
|
1324
|
+
# does for a console. The launcher spells it `serve_mcp`; the `mcp` spelling exe/hecks ships
|
|
1325
|
+
# today stays with its router until the launcher is generated.
|
|
1326
|
+
command "ServeMcp" do
|
|
1327
|
+
role "Operator"
|
|
1328
|
+
goal "Serve the storehouse bus to an MCP client over stdio until it closes"
|
|
1329
|
+
|
|
1330
|
+
attribute :run, DoorKey
|
|
1331
|
+
attribute :stdio, Switch, optional: true
|
|
1332
|
+
|
|
1333
|
+
sets :run
|
|
1334
|
+
sets :stdio
|
|
1335
|
+
|
|
1336
|
+
emits McpRequested
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
command "Finish" do
|
|
1340
|
+
role "System"
|
|
1341
|
+
goal "Record that the door did its work, or was closed, and what it said"
|
|
1342
|
+
|
|
1343
|
+
reference_to Door
|
|
1344
|
+
attribute :output, Note
|
|
1345
|
+
|
|
1346
|
+
sets :output
|
|
1347
|
+
|
|
1348
|
+
emits DoorFinished
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
command "Stop" do
|
|
1352
|
+
role "System"
|
|
1353
|
+
goal "Record that the door could not be opened, and why"
|
|
1354
|
+
|
|
1355
|
+
reference_to Door
|
|
1356
|
+
attribute :refusal, Note
|
|
1357
|
+
|
|
1358
|
+
sets :refusal
|
|
1359
|
+
|
|
1360
|
+
emits DoorStopped
|
|
1361
|
+
end
|
|
1362
|
+
|
|
1363
|
+
query "Ended" do
|
|
1364
|
+
description "How one door ended: its status, and what it said or why it stopped."
|
|
1365
|
+
attribute :run, DoorKey
|
|
1366
|
+
where(run: :run)
|
|
1367
|
+
order_by :run
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1370
|
+
query "Stopped" do
|
|
1371
|
+
description "Every door that could not be opened."
|
|
1372
|
+
where(status: "stopped")
|
|
1373
|
+
order_by :run
|
|
1374
|
+
end
|
|
1375
|
+
end
|
|
1376
|
+
|
|
1377
|
+
policy "WriteWhenRequested" do
|
|
1378
|
+
on "Door.LaunchersRequested"
|
|
1379
|
+
trigger Door::Workspace::Write, with: { run: :run }
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
policy "ServeWhenRequested" do
|
|
1383
|
+
on "Door.McpRequested"
|
|
1384
|
+
trigger Door::Terminal::Serve, with: { run: :run }
|
|
1385
|
+
end
|
|
1386
|
+
|
|
1387
|
+
policy "RecordTheDoor" do
|
|
1388
|
+
on "Door.DoorAnswered"
|
|
1389
|
+
trigger Door::Finish, with: { output: :output }
|
|
1390
|
+
end
|
|
1391
|
+
|
|
1392
|
+
policy "RecordTheStoppedDoor" do
|
|
1393
|
+
on "Door.DoorRefused"
|
|
1394
|
+
trigger Door::Stop, with: { refusal: :refusal }
|
|
1395
|
+
end
|
|
1396
|
+
|
|
1397
|
+
aggregate "Build" do
|
|
1398
|
+
description "One build of a domain for the Rust host, or a check of that build against Ruby."
|
|
1399
|
+
|
|
1400
|
+
attribute :run, BuildKey
|
|
1401
|
+
attribute :domain, DomainPath, optional: true
|
|
1402
|
+
attribute :script, ScriptPath, optional: true
|
|
1403
|
+
attribute :artifact, Artifact, optional: true
|
|
1404
|
+
attribute :seeds, Count, optional: true
|
|
1405
|
+
attribute :steps, Count, optional: true
|
|
1406
|
+
attribute :output, Report, optional: true
|
|
1407
|
+
attribute :refusal, Report, optional: true
|
|
1408
|
+
identified_by :run
|
|
1409
|
+
|
|
1410
|
+
value_object "BuildKey" do
|
|
1411
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
1412
|
+
|
|
1413
|
+
invariant("a build is named") { !value.to_s.empty? }
|
|
1414
|
+
end
|
|
1415
|
+
|
|
1416
|
+
# A domain directory. Its last part is also a Rust module and a Cargo feature, so it is a
|
|
1417
|
+
# lowercase identifier; the toolchain refuses the reserved words the pattern cannot.
|
|
1418
|
+
value_object "DomainPath" do
|
|
1419
|
+
attribute :value, String, pattern: '(^|/)[a-z][a-z0-9_]*/?$'
|
|
1420
|
+
end
|
|
1421
|
+
|
|
1422
|
+
# A generated module: the directory name a domain was built as.
|
|
1423
|
+
value_object "ModuleName" do
|
|
1424
|
+
attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
# A JSON file of steps for a domain to replay.
|
|
1428
|
+
value_object "ScriptPath" do
|
|
1429
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
# What a build is replayed through: `native`, `build` (the domain's own feature), a `.wasm`
|
|
1433
|
+
# module, or a binary.
|
|
1434
|
+
value_object "Artifact" do
|
|
1435
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
1436
|
+
end
|
|
1437
|
+
|
|
1438
|
+
value_object "Count" do
|
|
1439
|
+
attribute :value, Integer
|
|
1440
|
+
|
|
1441
|
+
invariant("a count is positive") { value > 0 }
|
|
1442
|
+
end
|
|
1443
|
+
|
|
1444
|
+
value_object "CodegenName" do
|
|
1445
|
+
attribute :value, String, pattern: '^(ruby|rust)$'
|
|
1446
|
+
end
|
|
1447
|
+
|
|
1448
|
+
value_object "Report" do
|
|
1449
|
+
attribute :value, String
|
|
1450
|
+
end
|
|
1451
|
+
|
|
1452
|
+
lifecycle :status, default: "requested" do
|
|
1453
|
+
transition "Complete" => "completed", from: "requested"
|
|
1454
|
+
transition "Fault" => "faulted", from: "requested"
|
|
1455
|
+
end
|
|
1456
|
+
|
|
1457
|
+
# Writes the domain's Rust source and a Cargo feature for it into the build workspace: the
|
|
1458
|
+
# checkout's own `rust/`, or a copy of the packaged workspace under `.hecks/rust/<version>/`.
|
|
1459
|
+
# Nothing is ever written into the installed gem.
|
|
1460
|
+
command "ProjectRust" do
|
|
1461
|
+
role "Operator"
|
|
1462
|
+
goal "Generate a domain's Rust source for the Rust host"
|
|
1463
|
+
|
|
1464
|
+
attribute :domain, DomainPath
|
|
1465
|
+
attribute :run, BuildKey
|
|
1466
|
+
|
|
1467
|
+
sets :domain
|
|
1468
|
+
sets :run
|
|
1469
|
+
|
|
1470
|
+
emits RustProjectionRequested
|
|
1471
|
+
end
|
|
1472
|
+
|
|
1473
|
+
command "BuildWasm" do
|
|
1474
|
+
role "Operator"
|
|
1475
|
+
goal "Compile a domain to a WASI module a runtime such as wasmtime can run"
|
|
1476
|
+
|
|
1477
|
+
attribute :domain, DomainPath
|
|
1478
|
+
attribute :run, BuildKey
|
|
1479
|
+
|
|
1480
|
+
sets :domain
|
|
1481
|
+
sets :run
|
|
1482
|
+
|
|
1483
|
+
emits WasmBuildRequested
|
|
1484
|
+
end
|
|
1485
|
+
|
|
1486
|
+
command "BuildBrowserWasm" do
|
|
1487
|
+
role "Operator"
|
|
1488
|
+
goal "Compile a domain to an ES module a browser can import"
|
|
1489
|
+
|
|
1490
|
+
attribute :domain, DomainPath
|
|
1491
|
+
attribute :run, BuildKey
|
|
1492
|
+
|
|
1493
|
+
sets :domain
|
|
1494
|
+
sets :run
|
|
1495
|
+
|
|
1496
|
+
emits BrowserWasmBuildRequested
|
|
1497
|
+
end
|
|
1498
|
+
|
|
1499
|
+
# Without an artifact it answers Ruby's own result, which saved to a file becomes a pinned
|
|
1500
|
+
# expectation; with one it compares Ruby's result with that artifact's.
|
|
1501
|
+
command "CheckConformance" do
|
|
1502
|
+
role "Operator"
|
|
1503
|
+
goal "Replay a script through Ruby and a Rust build of the domain and compare what each did"
|
|
1504
|
+
|
|
1505
|
+
attribute :domain, DomainPath
|
|
1506
|
+
attribute :script, ScriptPath
|
|
1507
|
+
attribute :run, BuildKey
|
|
1508
|
+
attribute :artifact, Artifact, optional: true
|
|
1509
|
+
|
|
1510
|
+
sets :domain
|
|
1511
|
+
sets :script
|
|
1512
|
+
sets :run
|
|
1513
|
+
sets :artifact
|
|
1514
|
+
|
|
1515
|
+
emits ConformanceRequested
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
command "FuzzConformance" do
|
|
1519
|
+
role "Operator"
|
|
1520
|
+
goal "Replay generated sequences through Ruby and a Rust build of the domain and compare them"
|
|
1521
|
+
|
|
1522
|
+
attribute :domain, DomainPath
|
|
1523
|
+
attribute :artifact, Artifact
|
|
1524
|
+
attribute :run, BuildKey
|
|
1525
|
+
attribute :seeds, Count, optional: true
|
|
1526
|
+
attribute :steps, Count, optional: true
|
|
1527
|
+
|
|
1528
|
+
sets :domain
|
|
1529
|
+
sets :artifact
|
|
1530
|
+
sets :run
|
|
1531
|
+
sets :seeds
|
|
1532
|
+
sets :steps
|
|
1533
|
+
|
|
1534
|
+
emits ConformanceFuzzRequested
|
|
1535
|
+
end
|
|
1536
|
+
|
|
1537
|
+
command "CheckCoverageAllowlist" do
|
|
1538
|
+
role "Operator"
|
|
1539
|
+
goal "Check that every rule excusing a Rust coverage gap still excuses a real one"
|
|
1540
|
+
|
|
1541
|
+
attribute :run, BuildKey
|
|
1542
|
+
|
|
1543
|
+
sets :run
|
|
1544
|
+
|
|
1545
|
+
emits CoverageAllowlistRequested
|
|
1546
|
+
end
|
|
1547
|
+
|
|
1548
|
+
command "Complete" do
|
|
1549
|
+
role "System"
|
|
1550
|
+
goal "Record that the build or check ended well, and what it reported"
|
|
1551
|
+
|
|
1552
|
+
reference_to Build
|
|
1553
|
+
attribute :output, Report
|
|
1554
|
+
|
|
1555
|
+
sets :output
|
|
1556
|
+
|
|
1557
|
+
emits BuildCompleted
|
|
1558
|
+
end
|
|
1559
|
+
|
|
1560
|
+
command "Fault" do
|
|
1561
|
+
role "System"
|
|
1562
|
+
goal "Record that the build or check was refused or found a difference, and what it said"
|
|
1563
|
+
|
|
1564
|
+
reference_to Build
|
|
1565
|
+
attribute :refusal, Report
|
|
1566
|
+
|
|
1567
|
+
sets :refusal
|
|
1568
|
+
|
|
1569
|
+
emits BuildFaulted
|
|
1570
|
+
end
|
|
1571
|
+
|
|
1572
|
+
query "Result" do
|
|
1573
|
+
description "How one build or check ended: its status, and what it reported or why it failed."
|
|
1574
|
+
attribute :run, BuildKey
|
|
1575
|
+
where(run: :run)
|
|
1576
|
+
order_by :run
|
|
1577
|
+
end
|
|
1578
|
+
|
|
1579
|
+
query "Faulted" do
|
|
1580
|
+
description "Every build or check that was refused or found a difference."
|
|
1581
|
+
where(status: "faulted")
|
|
1582
|
+
order_by :run
|
|
1583
|
+
end
|
|
1584
|
+
|
|
1585
|
+
# An answer that is one document of text, exactly as the tool that produced it wrote it.
|
|
1586
|
+
value_object "Document" do
|
|
1587
|
+
attribute :text, String
|
|
1588
|
+
end
|
|
1589
|
+
|
|
1590
|
+
query "RustCoverage" do
|
|
1591
|
+
description "Whether each construct of a generated module has a routed Rust implementation."
|
|
1592
|
+
attribute :module_name, ModuleName
|
|
1593
|
+
attribute :codegen, CodegenName, optional: true
|
|
1594
|
+
returns Document
|
|
1595
|
+
end
|
|
1596
|
+
end
|
|
1597
|
+
|
|
1598
|
+
policy "GenerateWhenRequested" do
|
|
1599
|
+
on "Build.RustProjectionRequested"
|
|
1600
|
+
trigger Build::RustToolchain::Generate, with: { run: :run }
|
|
1601
|
+
end
|
|
1602
|
+
|
|
1603
|
+
policy "CompileWasmWhenRequested" do
|
|
1604
|
+
on "Build.WasmBuildRequested"
|
|
1605
|
+
trigger Build::RustToolchain::Wasm, with: { run: :run }
|
|
1606
|
+
end
|
|
1607
|
+
|
|
1608
|
+
policy "CompileBrowserWasmWhenRequested" do
|
|
1609
|
+
on "Build.BrowserWasmBuildRequested"
|
|
1610
|
+
trigger Build::RustToolchain::BrowserWasm, with: { run: :run }
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
policy "ConformWhenRequested" do
|
|
1614
|
+
on "Build.ConformanceRequested"
|
|
1615
|
+
trigger Build::RustToolchain::Conform, with: { run: :run }
|
|
1616
|
+
end
|
|
1617
|
+
|
|
1618
|
+
policy "ReplayWhenRequested" do
|
|
1619
|
+
on "Build.ConformanceFuzzRequested"
|
|
1620
|
+
trigger Build::RustToolchain::Replay, with: { run: :run }
|
|
1621
|
+
end
|
|
1622
|
+
|
|
1623
|
+
policy "AuditWhenRequested" do
|
|
1624
|
+
on "Build.CoverageAllowlistRequested"
|
|
1625
|
+
trigger Build::RustToolchain::Audit, with: { run: :run }
|
|
1626
|
+
end
|
|
1627
|
+
|
|
1628
|
+
policy "RecordTheBuild" do
|
|
1629
|
+
on "Build.BuildAnswered"
|
|
1630
|
+
trigger Build::Complete, with: { output: :output }
|
|
1631
|
+
end
|
|
1632
|
+
|
|
1633
|
+
policy "RecordTheFault" do
|
|
1634
|
+
on "Build.BuildRefused"
|
|
1635
|
+
trigger Build::Fault, with: { refusal: :refusal }
|
|
1636
|
+
end
|
|
1637
|
+
|
|
1638
|
+
# Named for the run, as ModelCheckRun is: `Hecks::Fuzzing` is the fuzzing toolkit's own module,
|
|
1639
|
+
# so a hecksagon could not spell an aggregate of that name.
|
|
1640
|
+
aggregate "FuzzRun" do
|
|
1641
|
+
description "One fuzz sweep or benchmark, and how it ended; and the generated sequences it replays."
|
|
1642
|
+
|
|
1643
|
+
attribute :domain, DomainPath, optional: true
|
|
1644
|
+
attribute :run, FuzzKey
|
|
1645
|
+
attribute :seeds, Count, optional: true
|
|
1646
|
+
attribute :steps, Count, optional: true
|
|
1647
|
+
attribute :workers, Count, optional: true
|
|
1648
|
+
attribute :adapter, Persistence, optional: true
|
|
1649
|
+
attribute :domains, NameList, optional: true
|
|
1650
|
+
attribute :targets, NameList, optional: true
|
|
1651
|
+
attribute :iterations, Count, optional: true
|
|
1652
|
+
attribute :warmup, Warmup, optional: true
|
|
1653
|
+
attribute :runs, Count, optional: true
|
|
1654
|
+
attribute :rust_binary, BinaryPath, optional: true
|
|
1655
|
+
attribute :format, Format, optional: true
|
|
1656
|
+
attribute :output, OutputPath, optional: true
|
|
1657
|
+
attribute :report, Report, optional: true
|
|
1658
|
+
attribute :refusal, Report, optional: true
|
|
1659
|
+
identified_by :run
|
|
1660
|
+
|
|
1661
|
+
value_object "FuzzKey" do
|
|
1662
|
+
attribute :value, String, pattern: '[^ \t\n\r]'
|
|
1663
|
+
|
|
1664
|
+
invariant("a sweep is named") { !value.to_s.empty? }
|
|
1665
|
+
end
|
|
1666
|
+
|
|
1667
|
+
# A domain directory; a sweep with none covers every domain of a hecks checkout.
|
|
1668
|
+
value_object "DomainPath" do
|
|
1669
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1670
|
+
|
|
1671
|
+
invariant("a domain is named by its path") { !value.to_s.empty? }
|
|
1672
|
+
end
|
|
1673
|
+
|
|
1674
|
+
value_object "Count" do
|
|
1675
|
+
attribute :value, Integer
|
|
1676
|
+
|
|
1677
|
+
invariant("a count is positive") { value > 0 }
|
|
1678
|
+
end
|
|
1679
|
+
|
|
1680
|
+
value_object "Warmup" do
|
|
1681
|
+
attribute :value, Integer
|
|
1682
|
+
|
|
1683
|
+
invariant("a warmup is not negative") { value >= 0 }
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1686
|
+
# Which persistence every ephemeral boot of a sweep uses.
|
|
1687
|
+
value_object "Persistence" do
|
|
1688
|
+
attribute :value, String, pattern: '^(memory|sqlite|postgres)$'
|
|
1689
|
+
end
|
|
1690
|
+
|
|
1691
|
+
# Names, comma separated: benchmark domains, or the targets to measure.
|
|
1692
|
+
value_object "NameList" do
|
|
1693
|
+
attribute :value, String, pattern: '^[^ \t\n\r,]+(,[^ \t\n\r,]+)*$'
|
|
1694
|
+
end
|
|
1695
|
+
|
|
1696
|
+
value_object "BinaryPath" do
|
|
1697
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1698
|
+
end
|
|
1699
|
+
|
|
1700
|
+
value_object "Format" do
|
|
1701
|
+
attribute :value, String, pattern: '^(markdown|json)$'
|
|
1702
|
+
end
|
|
1703
|
+
|
|
1704
|
+
value_object "OutputPath" do
|
|
1705
|
+
attribute :value, String, pattern: '[^\t\n\r]'
|
|
1706
|
+
end
|
|
1707
|
+
|
|
1708
|
+
value_object "Report" do
|
|
1709
|
+
attribute :value, String
|
|
1710
|
+
end
|
|
1711
|
+
|
|
1712
|
+
lifecycle :status, default: "requested" do
|
|
1713
|
+
transition "Conclude" => "concluded", from: "requested"
|
|
1714
|
+
transition "Halt" => "halted", from: "requested"
|
|
1715
|
+
end
|
|
1716
|
+
|
|
1717
|
+
# A sweep replays generated command and query sequences and checks properties over each.
|
|
1718
|
+
# A finding is shrunk and saved under `tmp/fuzz-failures/`, and ends the run as halted, with
|
|
1719
|
+
# what was found. Sweeping every domain of a checkout needs a hecks checkout; a client names
|
|
1720
|
+
# the domain. The sweep runs in child processes started through the ProcessPool adapter, so an
|
|
1721
|
+
# interrupt reaches the workers.
|
|
1722
|
+
command "Fuzz" do
|
|
1723
|
+
role "Operator"
|
|
1724
|
+
goal "Fuzz a domain with generated sequences and keep whether anything broke a property"
|
|
1725
|
+
|
|
1726
|
+
attribute :domain, DomainPath, optional: true
|
|
1727
|
+
attribute :run, FuzzKey
|
|
1728
|
+
attribute :seeds, Count, optional: true
|
|
1729
|
+
attribute :steps, Count, optional: true
|
|
1730
|
+
attribute :workers, Count, optional: true
|
|
1731
|
+
attribute :adapter, Persistence, optional: true
|
|
1732
|
+
|
|
1733
|
+
sets :domain
|
|
1734
|
+
sets :run
|
|
1735
|
+
sets :seeds
|
|
1736
|
+
sets :steps
|
|
1737
|
+
sets :workers
|
|
1738
|
+
sets :adapter
|
|
1739
|
+
|
|
1740
|
+
emits FuzzRequested
|
|
1741
|
+
end
|
|
1742
|
+
|
|
1743
|
+
# Measures each persistence adapter, and the Rust binary when there is one to build or use.
|
|
1744
|
+
# The report is kept in this record, which the Hecks domain binds to Memory: keeping a
|
|
1745
|
+
# domain's benchmark history beside it, in Sqlite under the project's `.hecks/`, is decided
|
|
1746
|
+
# with the persistence binding for Custodian, not here. `output` also writes the full JSON.
|
|
1747
|
+
command "Bench" do
|
|
1748
|
+
role "Operator"
|
|
1749
|
+
goal "Measure command throughput and latency for each target, and keep the report"
|
|
1750
|
+
|
|
1751
|
+
attribute :run, FuzzKey
|
|
1752
|
+
attribute :domains, NameList, optional: true
|
|
1753
|
+
attribute :targets, NameList, optional: true
|
|
1754
|
+
attribute :iterations, Count, optional: true
|
|
1755
|
+
attribute :warmup, Warmup, optional: true
|
|
1756
|
+
attribute :runs, Count, optional: true
|
|
1757
|
+
attribute :rust_binary, BinaryPath, optional: true
|
|
1758
|
+
attribute :format, Format, optional: true
|
|
1759
|
+
attribute :output, OutputPath, optional: true
|
|
1760
|
+
|
|
1761
|
+
sets :run
|
|
1762
|
+
sets :domains
|
|
1763
|
+
sets :targets
|
|
1764
|
+
sets :iterations
|
|
1765
|
+
sets :warmup
|
|
1766
|
+
sets :runs
|
|
1767
|
+
sets :rust_binary
|
|
1768
|
+
sets :format
|
|
1769
|
+
sets :output
|
|
1770
|
+
|
|
1771
|
+
emits BenchRequested
|
|
1772
|
+
end
|
|
1773
|
+
|
|
1774
|
+
command "Conclude" do
|
|
1775
|
+
role "System"
|
|
1776
|
+
goal "Record that the sweep or benchmark ended well, and what it reported"
|
|
1777
|
+
|
|
1778
|
+
reference_to FuzzRun
|
|
1779
|
+
attribute :report, Report
|
|
1780
|
+
|
|
1781
|
+
sets :report
|
|
1782
|
+
|
|
1783
|
+
emits FuzzConcluded
|
|
1784
|
+
end
|
|
1785
|
+
|
|
1786
|
+
command "Halt" do
|
|
1787
|
+
role "System"
|
|
1788
|
+
goal "Record that the sweep found something or the benchmark could not run, and what it said"
|
|
1789
|
+
|
|
1790
|
+
reference_to FuzzRun
|
|
1791
|
+
attribute :refusal, Report
|
|
1792
|
+
|
|
1793
|
+
sets :refusal
|
|
1794
|
+
|
|
1795
|
+
emits FuzzHalted
|
|
1796
|
+
end
|
|
1797
|
+
|
|
1798
|
+
query "Conclusion" do
|
|
1799
|
+
description "How one sweep or benchmark ended: its status, and what it reported or found."
|
|
1800
|
+
attribute :run, FuzzKey
|
|
1801
|
+
where(run: :run)
|
|
1802
|
+
order_by :run
|
|
1803
|
+
end
|
|
1804
|
+
|
|
1805
|
+
query "Halted" do
|
|
1806
|
+
description "Every sweep that found something and every benchmark that could not run."
|
|
1807
|
+
where(status: "halted")
|
|
1808
|
+
order_by :run
|
|
1809
|
+
end
|
|
1810
|
+
|
|
1811
|
+
# An answer that is one document of text, exactly as the tool that produced it wrote it.
|
|
1812
|
+
value_object "Document" do
|
|
1813
|
+
attribute :text, String
|
|
1814
|
+
end
|
|
1815
|
+
|
|
1816
|
+
# The generator `hecks fuzz` draws from, on its own: one valid dispatch sequence as a
|
|
1817
|
+
# replayable script. `adversarial` is the fraction of steps mutated to be refused; 0 is off.
|
|
1818
|
+
query "GenerateSequence" do
|
|
1819
|
+
description "One generated, valid dispatch sequence for a domain, as a script `hecks run` replays."
|
|
1820
|
+
attribute :domain, DomainPath
|
|
1821
|
+
attribute :seed, Integer, optional: true
|
|
1822
|
+
attribute :steps, Integer, optional: true
|
|
1823
|
+
attribute :adversarial, Float, optional: true
|
|
1824
|
+
returns Document
|
|
1825
|
+
end
|
|
1826
|
+
end
|
|
1827
|
+
|
|
1828
|
+
policy "SweepWhenRequested" do
|
|
1829
|
+
on "FuzzRun.FuzzRequested"
|
|
1830
|
+
trigger FuzzRun::ProcessPool::Sweep, with: { run: :run }
|
|
1831
|
+
end
|
|
1832
|
+
|
|
1833
|
+
policy "MeasureWhenRequested" do
|
|
1834
|
+
on "FuzzRun.BenchRequested"
|
|
1835
|
+
trigger FuzzRun::RustToolchain::Measure, with: { run: :run }
|
|
1836
|
+
end
|
|
1837
|
+
|
|
1838
|
+
policy "RecordTheSweep" do
|
|
1839
|
+
on "FuzzRun.FuzzAnswered"
|
|
1840
|
+
trigger FuzzRun::Conclude, with: { report: :report }
|
|
1841
|
+
end
|
|
1842
|
+
|
|
1843
|
+
policy "RecordTheFinding" do
|
|
1844
|
+
on "FuzzRun.FuzzRefused"
|
|
1845
|
+
trigger FuzzRun::Halt, with: { refusal: :refusal }
|
|
1846
|
+
end
|
|
1847
|
+
end
|