hecks 6.0.0 → 7.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 +19 -12
- data/lib/hecks/adapters/driven/claude_code.rb +2 -2
- data/lib/hecks/adapters/driven/folder.rb +10 -1
- data/lib/hecks/adapters/driven/folder_overlay.rb +15 -0
- data/lib/hecks/adapters/driven/heki.rb +1 -1
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +1 -1
- data/lib/hecks/adapters/driven/memory/outbox_rows.rb +2 -2
- data/lib/hecks/adapters/driven/postgres/name_guard.rb +25 -0
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -3
- data/lib/hecks/adapters/driven/postgres/repository.rb +1 -1
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +1 -1
- data/lib/hecks/adapters/driven/postgres.rb +3 -0
- data/lib/hecks/adapters/driven/postgres_era/boot.rb +28 -16
- data/lib/hecks/adapters/driven/postgres_era/class_methods.rb +27 -7
- data/lib/hecks/adapters/driven/postgres_era/dialect.rb +10 -5
- data/lib/hecks/adapters/driven/postgres_era/field_cache_provisioner.rb +39 -0
- data/lib/hecks/adapters/driven/postgres_era/journal.rb +52 -13
- data/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +29 -49
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_sql.rb +73 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.json +10 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/direct_verified.rb +65 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename.rb +77 -25
- data/lib/hecks/adapters/driven/postgres_era/lineage/domain_rename_state.rb +108 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_integrity.rb +11 -6
- data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +63 -5
- data/lib/hecks/adapters/driven/postgres_era/lineage/layered_sql.rb +64 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/ledger_reset.rb +150 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_provisioning.rb +85 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +11 -7
- data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +11 -5
- data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +76 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage/sql_templates.rb +9 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage.rb +10 -2
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/context.rb +23 -3
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +3 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/disposable_ledger.rb +119 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolution.rb +219 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +68 -71
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/held_era.rb +68 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/ledger_change.rb +63 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +1 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_decision.rb +163 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +24 -0
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +59 -21
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +24 -11
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +40 -6
- data/lib/hecks/adapters/driven/postgres_era/shared_tables.rb +32 -0
- data/lib/hecks/adapters/driven/postgres_era.adapter +12 -0
- data/lib/hecks/adapters/driven/postgres_era.rb +25 -10
- data/lib/hecks/adapters/driven/prism.rb +0 -1
- data/lib/hecks/adapters/driven/sql_query_builder.rb +1 -0
- data/lib/hecks/adapters/driven/sqlite/dispatch_claims.rb +1 -1
- data/lib/hecks/adapters/driven/sqlite/name_guard.rb +25 -0
- data/lib/hecks/adapters/driven/sqlite/outbox.rb +2 -2
- data/lib/hecks/adapters/driven/sqlite/repository.rb +1 -1
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +20 -0
- data/lib/hecks/adapters/driven/sqlite.rb +9 -1
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +1 -1
- data/lib/hecks/adapters/driven/worktree_overlay.rb +117 -0
- data/lib/hecks/adapters/driving/cli/shorthand.rb +5 -1
- data/lib/hecks/adapters/driving/cli.rb +1 -1
- data/lib/hecks/adapters/driving/cli_runner/answers.rb +77 -22
- data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +35 -0
- data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +36 -0
- data/lib/hecks/adapters/driving/cli_runner/json_words.rb +55 -0
- data/lib/hecks/adapters/driving/cli_runner/name_index.rb +63 -0
- data/lib/hecks/adapters/driving/cli_runner/read_context.rb +32 -0
- data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +49 -0
- data/lib/hecks/adapters/driving/cli_runner/resolution.rb +43 -17
- data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +63 -0
- data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +66 -0
- data/lib/hecks/adapters/driving/cli_runner/run_replay.rb +118 -0
- data/lib/hecks/adapters/driving/cli_runner/search_words.rb +35 -0
- data/lib/hecks/adapters/driving/cli_runner/settling.rb +6 -5
- data/lib/hecks/adapters/driving/cli_runner/streaming.rb +11 -10
- data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +1 -1
- data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +77 -0
- data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +36 -4
- data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +75 -0
- data/lib/hecks/adapters/driving/cli_runner.rb +106 -7
- data/lib/hecks/adapters/driving/context_line.rb +85 -0
- data/lib/hecks/adapters/driving/exit_status.rb +31 -0
- data/lib/hecks/adapters/driving/launcher_options.rb +7 -5
- data/lib/hecks/adapters/driving/mcp/progress_sink.rb +45 -0
- data/lib/hecks/adapters/driving/mcp/tool_calls.rb +7 -5
- data/lib/hecks/adapters/driving/mcp.rb +25 -5
- data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +40 -7
- data/lib/hecks/adapters/driving/mcp_scope.rb +8 -7
- data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +154 -0
- data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +64 -93
- data/lib/hecks/adapters/driving/usage_log.rb +146 -0
- data/lib/hecks/adapters/driving/write_guard.rb +55 -0
- data/lib/hecks/adapters/driving.rb +0 -1
- data/lib/hecks/behaviors/dsl.rb +5 -1
- data/lib/hecks/behaviors/expectations/boot.rb +0 -1
- data/lib/hecks/bluebook/acknowledgements.rb +1 -1
- data/lib/hecks/bluebook/aggregate.rb +21 -18
- data/lib/hecks/bluebook/assembly/contracts/sagas.rb +2 -0
- data/lib/hecks/bluebook/assembly/contracts/structure.rb +18 -13
- data/lib/hecks/bluebook/behaviour/aggregate.rb +27 -3
- data/lib/hecks/bluebook/command.rb +16 -5
- data/lib/hecks/bluebook/declaration.rb +32 -4
- data/lib/hecks/bluebook/domain_port.rb +7 -3
- data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +0 -2
- data/lib/hecks/bluebook/dsl/aggregate_builder/renaming.rb +25 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +3 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +0 -1
- data/lib/hecks/bluebook/dsl/audience_word.rb +40 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +56 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +80 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +51 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +1 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +17 -34
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +8 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +13 -3
- data/lib/hecks/bluebook/dsl/entity_builder.rb +0 -2
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +6 -4
- data/lib/hecks/bluebook/dsl/kinds.rb +53 -0
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +9 -2
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +25 -15
- data/lib/hecks/bluebook/dsl/translation_builder.rb +16 -1
- data/lib/hecks/bluebook/dsl/word_gate.rb +1 -1
- data/lib/hecks/bluebook/dsl.rb +1 -0
- data/lib/hecks/bluebook/meta_validator/judge/identity.rb +9 -4
- data/lib/hecks/bluebook/meta_validator/plan/category.rb +10 -2
- data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +9 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +2 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +3 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +7 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +7 -2
- data/lib/hecks/bluebook/meta_validator/shapes.rb +3 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +1 -1
- data/lib/hecks/bluebook/model_check/aggregate_checks.rb +27 -0
- data/lib/hecks/bluebook/model_check/ask_checks.rb +25 -0
- data/lib/hecks/bluebook/model_check/reaction_chains.rb +114 -0
- data/lib/hecks/bluebook/model_check/reaction_cycles.rb +53 -0
- data/lib/hecks/bluebook/model_check/reaction_depth_checks.rb +58 -0
- data/lib/hecks/bluebook/model_check/reaction_walk.rb +62 -0
- data/lib/hecks/bluebook/model_check.rb +5 -27
- data/lib/hecks/bluebook/process_manager.rb +20 -3
- data/lib/hecks/bluebook/translation.rb +5 -3
- data/lib/hecks/bluebook/translation_plan.rb +9 -2
- data/lib/hecks/ci_pipeline/adapters/ci_cache.adapter +7 -0
- data/lib/hecks/ci_pipeline/adapters/ci_cache.rb +39 -0
- data/lib/hecks/ci_pipeline/adapters/ci_runner.adapter +7 -0
- data/lib/hecks/ci_pipeline/adapters/ci_runner.rb +55 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.behaviors +322 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.bluebook +938 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.hecksagon +12 -0
- data/lib/hecks/ci_pipeline/ci_pipeline.ports.hecksagon +16 -0
- data/lib/hecks/ci_speed/adapters/ci_reader.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/ci_reader.rb +141 -0
- data/lib/hecks/ci_speed/adapters/local_runner/answer.rb +41 -0
- data/lib/hecks/ci_speed/adapters/local_runner/catalog.rb +89 -0
- data/lib/hecks/ci_speed/adapters/local_runner/checkouts.rb +89 -0
- data/lib/hecks/ci_speed/adapters/local_runner/launcher.rb +69 -0
- data/lib/hecks/ci_speed/adapters/local_runner/load_average.rb +38 -0
- data/lib/hecks/ci_speed/adapters/local_runner/refs.rb +39 -0
- data/lib/hecks/ci_speed/adapters/local_runner/refused.rb +11 -0
- data/lib/hecks/ci_speed/adapters/local_runner/verdict.rb +71 -0
- data/lib/hecks/ci_speed/adapters/local_runner.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/local_runner.rb +168 -0
- data/lib/hecks/ci_speed/adapters/replayed_runner.rb +39 -0
- data/lib/hecks/ci_speed/ci_speed.behaviors +341 -0
- data/lib/hecks/ci_speed/ci_speed.bluebook +1073 -0
- data/lib/hecks/ci_speed/ci_speed.hecksagon +11 -0
- data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +21 -0
- data/lib/hecks/ci_workflows/ci_workflows.behaviors +13 -0
- data/lib/hecks/ci_workflows/ci_workflows.bluebook +173 -0
- data/lib/hecks/ci_workflows/ci_workflows.hecksagon +15 -0
- data/lib/hecks/coder/coder.bluebook +385 -0
- data/lib/hecks/coder/coder.hecksagon +12 -0
- data/lib/hecks/command_names/check.rb +39 -0
- data/lib/hecks/command_names/extractor.rb +67 -0
- data/lib/hecks/command_names/index.rb +40 -0
- data/lib/hecks/command_names/resolution.rb +81 -0
- data/lib/hecks/command_names/scan.rb +54 -0
- data/lib/hecks/command_names/sources.rb +73 -0
- data/lib/hecks/command_names.rb +26 -0
- data/lib/hecks/composer/jobs.rb +1 -1
- data/lib/hecks/composer/toolbox.rb +8 -1
- data/lib/hecks/corpus/generated_key.rb +205 -0
- data/lib/hecks/corpus/listing.rb +34 -0
- data/lib/hecks/corpus/rust.rb +27 -11
- data/lib/hecks/corpus/sources.rb +2 -1
- data/lib/hecks/corpus.rb +37 -42
- data/lib/hecks/deprecation.rb +23 -0
- data/lib/hecks/doc/reference/readme.rb +1 -1
- data/lib/hecks/doc/reference/rendering.rb +2 -2
- data/lib/hecks/doc/reference.rb +1 -1
- data/lib/hecks/embryonaut_bluebook/manifest.rb +1 -1
- data/lib/hecks/fixer/fixer.bluebook +240 -0
- data/lib/hecks/fixer/fixer.hecksagon +17 -0
- data/lib/hecks/framework_bluebooks.rb +32 -7
- data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +1 -0
- data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +11 -12
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +23 -5
- data/lib/hecks/fuzzing/isolated_boot.rb +1 -1
- data/lib/hecks/fuzzing/mutation/checks.rb +3 -3
- data/lib/hecks/grammar/translation.bluebook +1 -1
- data/lib/hecks/grammar/translation_rules.json +64 -0
- data/lib/hecks/hecks/adapter_words.json +7 -0
- data/lib/hecks/hecks/adapters/area_overlap.rb +156 -0
- data/lib/hecks/hecks/adapters/claude_agents.rb +8 -3
- data/lib/hecks/hecks/adapters/codebase/batch_runs.rb +60 -0
- data/lib/hecks/hecks/adapters/codebase/changed_specs.rb +52 -0
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +3 -2
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +14 -1
- data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +53 -0
- data/lib/hecks/hecks/adapters/codebase/generated_keys.rb +31 -0
- data/lib/hecks/hecks/adapters/codebase/impacted_specs.rb +110 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +2 -2
- data/lib/hecks/hecks/adapters/codebase/launcher_text.rb +39 -0
- data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +52 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +51 -8
- data/lib/hecks/hecks/adapters/codebase/run_options.rb +35 -0
- data/lib/hecks/hecks/adapters/codebase/scripting.rb +39 -0
- data/lib/hecks/hecks/adapters/codebase/search.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +79 -51
- data/lib/hecks/hecks/adapters/codebase/spec_files/report.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/spec_files/shared_run.rb +73 -0
- data/lib/hecks/hecks/adapters/codebase/spec_files.rb +95 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +53 -4
- data/lib/hecks/hecks/adapters/codebase/test_scope.rb +105 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +48 -34
- data/lib/hecks/hecks/adapters/console_capture.rb +1 -1
- data/lib/hecks/hecks/adapters/cost_explorer.rb +9 -1
- data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +51 -0
- data/lib/hecks/hecks/adapters/dispatching/launcher.rb +97 -0
- data/lib/hecks/hecks/adapters/dispatching/plan.rb +82 -0
- data/lib/hecks/hecks/adapters/dispatching/rows.rb +66 -0
- data/lib/hecks/hecks/adapters/dispatching/settings.rb +81 -0
- data/lib/hecks/hecks/adapters/dispatching/settler.rb +40 -0
- data/lib/hecks/hecks/adapters/dispatching.adapter +7 -0
- data/lib/hecks/hecks/adapters/dispatching.rb +93 -0
- data/lib/hecks/hecks/adapters/doctor_reading/report.rb +27 -0
- data/lib/hecks/hecks/adapters/doctor_reading.adapter +7 -0
- data/lib/hecks/hecks/adapters/doctor_reading.rb +161 -0
- data/lib/hecks/hecks/adapters/git_checkout.rb +1 -1
- data/lib/hecks/hecks/adapters/git_commit.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_commit.rb +61 -0
- data/lib/hecks/hecks/adapters/git_landing/finisher.rb +82 -0
- data/lib/hecks/hecks/adapters/git_landing/foreign_hold.rb +111 -0
- data/lib/hecks/hecks/adapters/git_landing/line.rb +171 -0
- data/lib/hecks/hecks/adapters/git_landing/lineup.rb +98 -0
- data/lib/hecks/hecks/adapters/git_landing/merger.rb +1 -1
- data/lib/hecks/hecks/adapters/git_landing/numbering.rb +54 -0
- data/lib/hecks/hecks/adapters/git_landing/rivals.rb +59 -0
- data/lib/hecks/hecks/adapters/git_landing/ticket.rb +156 -0
- data/lib/hecks/hecks/adapters/git_landing/tidy.rb +147 -0
- data/lib/hecks/hecks/adapters/git_landing/train.rb +104 -0
- data/lib/hecks/hecks/adapters/git_landing/verdict.rb +64 -0
- data/lib/hecks/hecks/adapters/git_landing/waiting.rb +120 -0
- data/lib/hecks/hecks/adapters/git_landing.rb +106 -20
- data/lib/hecks/hecks/adapters/git_main_pull.rb +99 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/bench.rb +82 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/due.rb +84 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted/skips.rb +47 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted/spec_run.rb +75 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/impacted.rb +181 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/line.rb +76 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/reading.rb +24 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/record.rb +146 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/corpus.rb +25 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map/needles.rb +61 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/spec_map.rb +105 -0
- data/lib/hecks/hecks/adapters/git_rehearsal/stages.rb +118 -0
- data/lib/hecks/hecks/adapters/git_rehearsal.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_rehearsal.rb +141 -0
- data/lib/hecks/hecks/adapters/git_train/bench.rb +15 -15
- data/lib/hecks/hecks/adapters/git_train/branch_guard.rb +62 -0
- data/lib/hecks/hecks/adapters/git_train/carriage.rb +27 -28
- data/lib/hecks/hecks/adapters/git_train/launcher_shape.rb +75 -0
- data/lib/hecks/hecks/adapters/git_train/mint_step.rb +47 -0
- data/lib/hecks/hecks/adapters/git_train/settlement.rb +167 -0
- data/lib/hecks/hecks/adapters/git_train.rb +73 -15
- data/lib/hecks/hecks/adapters/git_worktree_add.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_worktree_add.rb +68 -0
- data/lib/hecks/hecks/adapters/github_pull_requests.adapter +7 -0
- data/lib/hecks/hecks/adapters/github_pull_requests.rb +109 -0
- data/lib/hecks/hecks/adapters/host_http.rb +6 -6
- data/lib/hecks/hecks/adapters/in_process_boot.rb +10 -8
- data/lib/hecks/hecks/adapters/in_process_operations.rb +11 -17
- data/lib/hecks/hecks/adapters/in_process_undo.rb +17 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +13 -4
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +28 -15
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +17 -1
- data/lib/hecks/hecks/adapters/journal_store/held_domain/renaming.rb +45 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +31 -5
- data/lib/hecks/hecks/adapters/journal_store/held_mint.rb +128 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +1 -1
- data/lib/hecks/hecks/adapters/journal_store/readings/boot_status.rb +58 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/outcomes.rb +76 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/postgres_reader.rb +44 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/reader.rb +64 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/report.rb +102 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/sqlite_reader.rb +43 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/stores.rb +80 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/subscribers.rb +72 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace/summary.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/event_trace.rb +39 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/command_line.rb +57 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/edge_guards.rb +107 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/inspection.rb +94 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/plan.rb +66 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/report.rb +72 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/store.rb +34 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/watermark_guards.rb +86 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan/world.rb +66 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/mint_plan.rb +36 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/projection_audit.rb +64 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +3 -3
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/database_reading.rb +113 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status/read_only.rb +33 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/sqlite_status.rb +32 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +13 -1
- data/lib/hecks/hecks/adapters/journal_store/reconcile_report.rb +60 -0
- data/lib/hecks/hecks/adapters/journal_store/reconciliation.rb +121 -0
- data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +59 -0
- data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +123 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +16 -0
- data/lib/hecks/hecks/adapters/landed_work.adapter +7 -0
- data/lib/hecks/hecks/adapters/landed_work.rb +52 -0
- data/lib/hecks/hecks/adapters/local_files.rb +6 -6
- data/lib/hecks/hecks/adapters/process_pool.rb +3 -2
- data/lib/hecks/hecks/adapters/push_size.rb +57 -0
- data/lib/hecks/hecks/adapters/qa_quiescing.adapter +7 -0
- data/lib/hecks/hecks/adapters/qa_quiescing.rb +57 -0
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +30 -3
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +63 -3
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +29 -6
- data/lib/hecks/hecks/adapters/rehearsal/subject.rb +11 -5
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +10 -1
- data/lib/hecks/hecks/adapters/rust_workspace.rb +1 -1
- data/lib/hecks/hecks/adapters/settings_reading/disposable_ledger.rb +32 -0
- data/lib/hecks/hecks/adapters/settings_reading/push_nudge.rb +26 -0
- data/lib/hecks/hecks/adapters/settings_reading/stores.rb +76 -0
- data/lib/hecks/hecks/adapters/settings_reading/test_scope.rb +28 -0
- data/lib/hecks/hecks/adapters/settings_reading.rb +28 -2
- data/lib/hecks/hecks/adapters/started_work.rb +42 -0
- data/lib/hecks/hecks/adapters/terminal.rb +12 -10
- data/lib/hecks/hecks/adapters/where_reading.adapter +7 -0
- data/lib/hecks/hecks/adapters/where_reading.rb +64 -0
- data/lib/hecks/hecks/adapters/work_areas.rb +57 -0
- data/lib/hecks/hecks/adapters/work_limits.rb +57 -0
- data/lib/hecks/hecks/build/build.bluebook +576 -0
- data/lib/hecks/hecks/check/check.bluebook +966 -0
- data/lib/hecks/hecks/codebase.behaviors +61 -5
- data/lib/hecks/hecks/composer.behaviors +1 -1
- data/lib/hecks/hecks/context_map.hecksagon +1 -1
- data/lib/hecks/hecks/custodian.behaviors +33 -7
- data/lib/hecks/hecks/delegate/delegate.bluebook +355 -0
- data/lib/hecks/hecks/deliver/deliver.bluebook +945 -0
- data/lib/hecks/hecks/deploy.behaviors +1 -1
- data/lib/hecks/hecks/evolve/evolve.bluebook +788 -0
- data/lib/hecks/hecks/find/find.bluebook +81 -0
- data/lib/hecks/hecks/hecks.behaviors +1 -1
- data/lib/hecks/hecks/hecks.bluebook +0 -133
- data/lib/hecks/hecks/hecks.contextmap +2 -0
- data/lib/hecks/hecks/hecks.hecksagon +185 -29
- data/lib/hecks/hecks/hecks.world +35 -9
- data/lib/hecks/hecks/implicit_moves.json +24 -0
- data/lib/hecks/hecks/migrate/migrate.bluebook +1066 -0
- data/lib/hecks/hecks/operate/operate.bluebook +695 -0
- data/lib/hecks/hecks/quiesce/quiesce.bluebook +117 -0
- data/lib/hecks/hecks/rehearse/rehearse.bluebook +133 -0
- data/lib/hecks/hecks/release/release.bluebook +916 -0
- data/lib/hecks/hecks/serve/serve.bluebook +134 -0
- data/lib/hecks/hecks/shapes.json +1 -15
- data/lib/hecks/hecks/site.behaviors +1 -1
- data/lib/hecks/hecks/start/start.bluebook +194 -0
- data/lib/hecks/hecks/test/test.bluebook +638 -0
- data/lib/hecks/hecks/tickets.world +14 -0
- data/lib/hecks/language/bluebook/aggregate.bluebook +22 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +34 -0
- data/lib/hecks/language/bluebook/command.bluebook +35 -0
- data/lib/hecks/language/bluebook/process_manager.bluebook +14 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +174 -54
- data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -0
- data/lib/hecks/language/hecksagon/port_operation.bluebook +14 -0
- data/lib/hecks/language/kinds/run.kind +120 -0
- data/lib/hecks/language/oidc.json +10 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +24 -0
- data/lib/hecks/module_folders.rb +31 -0
- data/lib/hecks/ports/key_vault.rb +1 -1
- data/lib/hecks/ports/persistence/append_only.rb +26 -8
- data/lib/hecks/ports/persistence/binding_policy.rb +3 -1
- data/lib/hecks/ports/persistence/codec_boundary.rb +1 -1
- data/lib/hecks/ports/persistence/mint_door.rb +74 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +6 -5
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +5 -1
- data/lib/hecks/ports/persistence/plugins/era/era_status.rb +48 -0
- data/lib/hecks/ports/persistence/plugins/era/projected_bluebook.rb +127 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/additive_shape.rb +107 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +155 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/compose_render.rb +79 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/edge_files.rb +49 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/edge_route.rb +61 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/implicit_edge.rb +67 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/reconcile.rb +130 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/reconcile_files.rb +35 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +13 -5
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +5 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +1 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +11 -3
- data/lib/hecks/ports/persistence/stored_name_guard.rb +36 -0
- data/lib/hecks/ports/persistence.rb +2 -0
- data/lib/hecks/projections/ci_pipeline/table/checks.rb +137 -0
- data/lib/hecks/projections/ci_pipeline/table/lookup.rb +59 -0
- data/lib/hecks/projections/ci_pipeline/table/refusals.rb +58 -0
- data/lib/hecks/projections/ci_pipeline/table/rows.rb +119 -0
- data/lib/hecks/projections/ci_pipeline/table/tree.rb +30 -0
- data/lib/hecks/projections/ci_pipeline/table/typing.rb +92 -0
- data/lib/hecks/projections/ci_pipeline/table.rb +112 -0
- data/lib/hecks/projections/ci_pipeline/workflows.rb +162 -0
- data/lib/hecks/projections/ci_pipeline/yaml_text.rb +104 -0
- data/lib/hecks/projections/deploy/box/hosting.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_scripts.rb +1 -1
- data/lib/hecks/projections/deploy/box.rb +1 -1
- data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +1 -1
- data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +3 -3
- data/lib/hecks/projections/undo.rb +46 -0
- data/lib/hecks/projections.rb +2 -0
- data/lib/hecks/projector/cli_projector/claims.rb +11 -0
- data/lib/hecks/projector/cli_projector/command_help.rb +6 -1
- data/lib/hecks/projector/cli_projector/command_specs.rb +11 -1
- data/lib/hecks/projector/cli_projector/completion.rb +87 -0
- data/lib/hecks/projector/cli_projector/everyday.rb +40 -0
- data/lib/hecks/projector/cli_projector/json_listing.rb +77 -0
- data/lib/hecks/projector/cli_projector/listing.rb +1 -1
- data/lib/hecks/projector/cli_projector/modules.rb +39 -0
- data/lib/hecks/projector/cli_projector/query_specs.rb +1 -0
- data/lib/hecks/projector/cli_projector/renames.rb +58 -0
- data/lib/hecks/projector/cli_projector/search.rb +74 -0
- data/lib/hecks/projector/cli_projector/usage.rb +23 -6
- data/lib/hecks/projector/cli_projector.rb +24 -1
- data/lib/hecks/quality_control/adapters/ci_head.adapter +8 -0
- data/lib/hecks/quality_control/adapters/image_roll.adapter +9 -0
- data/lib/hecks/quality_control/adapters/image_roll.rb +158 -0
- data/lib/hecks/quality_control/adapters/main_maintenance.adapter +8 -0
- data/lib/hecks/quality_control/adapters/main_maintenance.rb +275 -0
- data/lib/hecks/quality_control/adapters/pump_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/pump_tools.rb +18 -0
- data/lib/hecks/quality_control/adapters/push_due_reader.adapter +8 -0
- data/lib/hecks/quality_control/adapters/push_due_reader.rb +99 -0
- data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +183 -0
- data/lib/hecks/quality_control/adapters/qa_era_mint.rb +94 -0
- data/lib/hecks/quality_control/adapters/qa_quiesce_marker.rb +126 -0
- data/lib/hecks/quality_control/adapters/run_keys.rb +36 -0
- data/lib/hecks/quality_control/adapters/run_reader.adapter +7 -0
- data/lib/hecks/quality_control/adapters/run_reader.rb +188 -0
- data/lib/hecks/quality_control/cli/child.rb +1 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_event_pump/attached.rb +67 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/consumer.rb +103 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/cursors.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/reactions.rb +46 -0
- data/lib/hecks/quality_control/cli/qa_event_pump/reader.rb +30 -0
- data/lib/hecks/quality_control/cli/qa_event_pump.rb +76 -0
- data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +79 -0
- data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +167 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +3 -3
- data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +52 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +47 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +59 -0
- data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +62 -0
- data/lib/hecks/quality_control/cli/qa_main_gate.rb +135 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +2 -3
- data/lib/hecks/quality_control/cli/qa_push_nudge.rb +48 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_tick/event_pump_step.rb +34 -0
- data/lib/hecks/quality_control/cli/qa_tick/output.rb +16 -1
- data/lib/hecks/quality_control/cli/qa_tick/push_nudge_step.rb +28 -0
- data/lib/hecks/quality_control/cli/qa_tick/quiesce_guard.rb +51 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +36 -8
- data/lib/hecks/quality_control/quality_control.behaviors +65 -0
- data/lib/hecks/quality_control/quality_control.bluebook +1131 -11
- data/lib/hecks/quality_control/quality_control.hecksagon +11 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +138 -0
- data/lib/hecks/query_ir/touchpoints.rb +5 -7
- data/lib/hecks/refused.rb +21 -0
- data/lib/hecks/release/approval.rb +6 -3
- data/lib/hecks/release/conditions.rb +46 -0
- data/lib/hecks/release/runner/gem_publisher.rb +4 -4
- data/lib/hecks/release/version_commit.rb +48 -0
- data/lib/hecks/runtime/command_interpreter/hydration.rb +5 -4
- data/lib/hecks/runtime/command_interpreter/persisting.rb +11 -3
- data/lib/hecks/runtime/command_interpreter.rb +2 -2
- data/lib/hecks/runtime/command_rules/admissibility.rb +0 -2
- data/lib/hecks/runtime/command_rules/emission.rb +0 -1
- data/lib/hecks/runtime/dependency_planning/expression_reads.rb +0 -1
- data/lib/hecks/runtime/dispatcher/planning.rb +24 -0
- data/lib/hecks/runtime/dispatcher/routing.rb +6 -0
- data/lib/hecks/runtime/dispatcher/value_routing.rb +54 -0
- data/lib/hecks/runtime/dispatcher.rb +7 -1
- data/lib/hecks/runtime/dry_run_plan.rb +60 -0
- data/lib/hecks/runtime/entity_element/location.rb +0 -1
- data/lib/hecks/runtime/entity_element/mutations.rb +0 -1
- data/lib/hecks/runtime/entity_interpreter/locating.rb +5 -0
- data/lib/hecks/runtime/entity_interpreter.rb +0 -1
- data/lib/hecks/runtime/errors.rb +26 -0
- data/lib/hecks/runtime/instance.rb +0 -1
- data/lib/hecks/runtime/invocation_builder.rb +0 -1
- data/lib/hecks/runtime/outbox/consumer_runner.rb +9 -1
- data/lib/hecks/runtime/outbox/relay.rb +25 -4
- data/lib/hecks/runtime/outbox/runnable.rb +3 -1
- data/lib/hecks/runtime/outbox.rb +6 -2
- data/lib/hecks/runtime/policy_interpreter/fan_out.rb +18 -2
- data/lib/hecks/runtime/policy_interpreter.rb +17 -9
- data/lib/hecks/runtime/port_operation_interpreter.rb +21 -7
- data/lib/hecks/runtime/query_interpreter/arguments.rb +6 -5
- data/lib/hecks/runtime/reaction_invocation.rb +0 -1
- data/lib/hecks/runtime/refusal_wording.rb +12 -1
- data/lib/hecks/runtime/registry/context_maps.rb +1 -5
- data/lib/hecks/runtime/registry/declarations.rb +34 -4
- data/lib/hecks/runtime/registry/hecksagon_rules.rb +15 -1
- data/lib/hecks/runtime/registry/runtime_state.rb +10 -0
- data/lib/hecks/runtime/registry/world_defaults.rb +24 -2
- data/lib/hecks/runtime/registry/world_names.rb +99 -0
- data/lib/hecks/runtime/registry.rb +33 -27
- data/lib/hecks/runtime/saga_interpreter/compensation.rb +10 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +29 -3
- data/lib/hecks/runtime/saga_interpreter/delivery.rb +0 -1
- data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +1 -1
- data/lib/hecks/runtime/saga_interpreter.rb +46 -2
- data/lib/hecks/runtime/value/coercion.rb +36 -8
- data/lib/hecks/rust_build/conformance.rb +16 -5
- data/lib/hecks/rust_build/parser.rb +25 -0
- data/lib/hecks/rust_build/project_rust/codegen_run.rb +45 -12
- data/lib/hecks/rust_build/project_rust/declared.rb +80 -0
- data/lib/hecks/rust_build/project_rust/features_header.rb +22 -0
- data/lib/hecks/rust_build/project_rust/manifest.rb +96 -0
- data/lib/hecks/rust_build/project_rust/meta.rb +36 -0
- data/lib/hecks/rust_build/project_rust.rb +28 -90
- data/lib/hecks/rust_build/write_if_changed.rb +19 -4
- data/lib/hecks/rust_build.rb +2 -1
- data/lib/hecks/rust_format.rb +32 -2
- data/lib/hecks/secrets.rb +111 -0
- data/lib/hecks/shape_ledger/edge_hygiene.rb +170 -0
- data/lib/hecks/shape_ledger/scope.rb +51 -0
- data/lib/hecks/shape_ledger/status.rb +89 -0
- data/lib/hecks/shape_ledger.rb +78 -33
- data/lib/hecks/site/bluebook/site.bluebook +1 -0
- data/lib/hecks/storehouse/audit.rb +34 -4
- data/lib/hecks/storehouse/callers.rb +8 -0
- data/lib/hecks/storehouse/dispatching.rb +14 -3
- data/lib/hecks/storehouse/identity.rb +41 -0
- data/lib/hecks/storehouse/querying.rb +7 -7
- data/lib/hecks/storehouse.rb +28 -10
- data/lib/hecks/tickets/bluebook/adapters/work_areas.adapter +7 -0
- data/lib/hecks/tickets/bluebook/adapters/work_limits.adapter +7 -0
- data/lib/hecks/tickets/bluebook/tickets.behaviors +70 -0
- data/lib/hecks/tickets/bluebook/tickets.bluebook +323 -28
- data/lib/hecks/tickets/bluebook/tickets.hecksagon +7 -0
- data/lib/hecks/tickets/bluebook/tickets.ports.hecksagon +17 -0
- data/lib/hecks/{cli → tools}/behaviors.rb +1 -1
- data/lib/hecks/{cli → tools}/canonicalise.rb +1 -1
- data/lib/hecks/{cli → tools}/check_engine_agreement.rb +1 -1
- data/lib/hecks/{cli → tools}/check_era.rb +6 -6
- data/lib/hecks/tools/ci_gates.rb +8 -2
- data/lib/hecks/tools/ci_workflows.rb +98 -0
- data/lib/hecks/{cli → tools}/console.rb +1 -1
- data/lib/hecks/{cli → tools}/deploy_template_diff.rb +1 -1
- data/lib/hecks/{cli → tools}/doc_coverage.rb +2 -2
- data/lib/hecks/{cli → tools}/document.rb +1 -1
- data/lib/hecks/{cli → tools}/domain_stub.rb +1 -1
- data/lib/hecks/{cli → tools}/domain_writer.rb +1 -1
- data/lib/hecks/tools/downstream_model_check.rb +122 -0
- data/lib/hecks/tools/evolve_run.rb +2 -2
- data/lib/hecks/{cli → tools}/expected_era.rb +1 -1
- data/lib/hecks/{cli → tools}/expression_projection.rb +1 -1
- data/lib/hecks/{cli → tools}/follow.rb +1 -1
- data/lib/hecks/tools/fuzz_sweep/options.rb +40 -5
- data/lib/hecks/tools/fuzz_sweep/pool.rb +12 -1
- data/lib/hecks/tools/fuzz_sweep/shards.rb +155 -0
- data/lib/hecks/tools/fuzz_sweep.rb +11 -5
- data/lib/hecks/tools/gate.rb +38 -29
- data/lib/hecks/tools/gate_memo/local_files.rb +33 -0
- data/lib/hecks/tools/gate_memo/rehearsal.rb +54 -0
- data/lib/hecks/tools/gate_memo/ruby_files.rb +152 -0
- data/lib/hecks/tools/gate_memo/session.rb +114 -0
- data/lib/hecks/tools/gate_memo/standalone.rb +67 -0
- data/lib/hecks/tools/gate_memo.rb +196 -0
- data/lib/hecks/tools/gate_report.rb +56 -0
- data/lib/hecks/{cli → tools}/history.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_agent.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_aggregate.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_draft.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_record.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_run.rb +2 -2
- data/lib/hecks/{cli → tools}/interview_session/agent_state.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/catalog.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/manual_findings.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session/proposals.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_session.rb +2 -2
- data/lib/hecks/{cli → tools}/interview_shape/lifecycle.rb +1 -1
- data/lib/hecks/{cli → tools}/interview_shape.rb +1 -1
- data/lib/hecks/{cli → tools}/ir.rb +1 -1
- data/lib/hecks/tools/lanes/files.rb +1 -1
- data/lib/hecks/tools/lanes/watch_workflow.rb +6 -8
- data/lib/hecks/tools/lanes/workflow.rb +1 -1
- data/lib/hecks/tools/lanes.rb +1 -1
- data/lib/hecks/{cli → tools}/mcp.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check/examination.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check/sources.rb +1 -1
- data/lib/hecks/{cli → tools}/model_check.rb +1 -1
- data/lib/hecks/tools/move_disables/reasons.rb +35 -0
- data/lib/hecks/tools/move_disables.rb +211 -0
- data/lib/hecks/tools/move_former_name.rb +105 -0
- data/lib/hecks/{cli → tools}/pattern_cases.rb +1 -1
- data/lib/hecks/{cli → tools}/persistence_notice.rb +1 -1
- data/lib/hecks/{cli → tools}/present.rb +1 -1
- data/lib/hecks/{cli → tools}/project_cli/launcher_source.rb +32 -22
- data/lib/hecks/{cli → tools}/project_cli/templates.rb +22 -15
- data/lib/hecks/{cli → tools}/project_cli.rb +11 -7
- data/lib/hecks/{cli → tools}/project_diagrams.rb +3 -3
- data/lib/hecks/{cli → tools}/project_glossary.rb +2 -2
- data/lib/hecks/{cli → tools}/reference.rb +2 -2
- data/lib/hecks/{cli → tools}/refresh_projections.rb +1 -1
- data/lib/hecks/{cli → tools}/refresh_rspec_runtime_baseline.rb +1 -1
- data/lib/hecks/tools/regeneration_run/pool.rb +148 -0
- data/lib/hecks/tools/regeneration_run/scratch.rb +76 -0
- data/lib/hecks/tools/regeneration_run.rb +125 -103
- data/lib/hecks/{cli → tools}/release.rb +1 -1
- data/lib/hecks/{cli → tools}/release_gem.rb +1 -1
- data/lib/hecks/{cli → tools}/rspec_io_parallel_files.rb +1 -1
- data/lib/hecks/{cli → tools}/rspec_shard_files.rb +1 -1
- data/lib/hecks/{cli → tools}/run.rb +9 -2
- data/lib/hecks/{cli → tools}/run_expectations.rb +1 -1
- data/lib/hecks/{cli → tools}/seed_semantics_corpus.rb +4 -4
- data/lib/hecks/{cli → tools}/serve_query_ir_mcp.rb +1 -1
- data/lib/hecks/{cli → tools}/shape.rb +3 -2
- data/lib/hecks/{cli → tools}/smoke_http/checks.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http/settings.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http/transport.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_http.rb +1 -1
- data/lib/hecks/{cli → tools}/smoke_test.rb +1 -1
- data/lib/hecks/{cli → tools}/spec_example.rb +1 -1
- data/lib/hecks/tools/stage_progress.rb +54 -0
- data/lib/hecks/{cli → tools}/statements.rb +1 -1
- data/lib/hecks/{cli → tools}/stores.rb +1 -1
- data/lib/hecks/{cli → tools}/stress_concurrency_specs/reporting.rb +1 -1
- data/lib/hecks/{cli → tools}/stress_concurrency_specs/usage.rb +4 -4
- data/lib/hecks/{cli → tools}/stress_concurrency_specs.rb +3 -3
- data/lib/hecks/tools/tenant_provisioning.rb +23 -0
- data/lib/hecks/tools/tools_doc.rb +10 -8
- data/lib/hecks/tools/translation_audit/edges.rb +21 -16
- data/lib/hecks/tools/translation_audit/verdicts.rb +1 -1
- data/lib/hecks/tools/translation_audit.rb +1 -1
- data/lib/hecks/tools/translation_scaffold.rb +1 -1
- data/lib/hecks/tools.rb +4 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +61 -31
- data/lib/hecks/workflow_pagination/judge.rb +48 -0
- data/lib/hecks/workflow_pagination/statement.rb +50 -0
- data/lib/hecks/workflow_pagination.rb +58 -0
- data/lib/hecks.rb +2 -0
- data/lib/rubocop/cop/hecks/bare_event_and_query_names.rb +58 -0
- data/lib/rubocop/cop/hecks/correlates_by_aggregate.rb +39 -0
- data/lib/rubocop/cop/hecks/creating_command_sets.rb +75 -0
- data/lib/rubocop/cop/hecks/invariant_expression_language.rb +47 -0
- data/lib/rubocop/cop/hecks/lifecycle_needs_attribute.rb +58 -0
- data/lib/rubocop/cop/hecks/no_id_string_attribute.rb +49 -0
- data/lib/rubocop/cop/hecks/one_terminal_mark_per_lifecycle.rb +47 -0
- data/lib/rubocop/cop/hecks/value_object_shorthand.rb +56 -0
- data/prebuilt/13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal +0 -0
- data/prebuilt/e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal +0 -0
- data/qa/settings.yml +23 -0
- data/rust/.gitignore +0 -6
- data/rust/Cargo.toml +2 -1
- data/rust/build/Cargo.toml +1 -1
- data/rust/build/src/binding_pass.rs +57 -4
- data/rust/build/src/pipeline.rs +6 -4
- data/rust/build/src/resolve.rs +1 -0
- data/rust/codegen/Cargo.toml +1 -1
- data/rust/codegen/src/domain_generator.rs +3 -0
- data/rust/codegen/src/json_codec.rs +182 -23
- data/rust/codegen/src/one_of_references.rs +1 -0
- data/rust/codegen/src/queries.rs +20 -2
- data/rust/codegen/src/registry.rs +21 -5
- data/rust/expr/Cargo.toml +1 -1
- data/rust/host/Cargo.toml +1 -1
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/core/Cargo.toml +1 -1
- data/rust/host/src/bin/mint_harness.rs +1 -0
- data/rust/host/src/boot.rs +1 -0
- data/rust/host/src/store/mint.rs +40 -6
- data/rust/lsp/Cargo.toml +1 -1
- data/rust/parser/Cargo.toml +1 -1
- data/rust/parser/src/build/correlation_keys.rs +125 -0
- data/rust/parser/src/build/mod.rs +1 -0
- data/rust/parser/src/emit.rs +55 -3
- data/rust/parser/src/ir.rs +33 -1
- data/rust/parser/src/keywords.rs +289 -1
- data/rust/parser/src/main.rs +2 -0
- data/rust/parser/src/parse/aggregate.rs +10 -1
- data/rust/parser/src/parse/audience.rs +65 -0
- data/rust/parser/src/parse/command.rs +14 -0
- data/rust/parser/src/parse/declaration.rs +97 -0
- data/rust/parser/src/parse/domain_port.rs +6 -0
- data/rust/parser/src/parse/mod.rs +1 -0
- data/rust/parser/src/parse/process_manager.rs +17 -10
- data/rust/parser/src/parse/world.rs +12 -8
- data/rust/parser/src/render_ruby.rs +9 -0
- data/rust/parser/src/sentence/format.rs +3 -0
- data/rust/parser/src/sentence/process.rs +6 -2
- data/rust/src/exemplar/json.rs +17 -0
- data/rust/src/kernel/cli.rs +27 -3
- data/rust/src/kernel/dispatch.rs +4 -2
- data/rust/src/kernel/json.rs +62 -0
- data/rust/src/kernel/orchestrate.rs +28 -3
- data/rust/src/kernel/orchestrate_guard_tests.rs +12 -12
- data/rust/web/Cargo.toml +1 -1
- metadata +389 -96
- data/lib/hecks/cli/command_table.rb +0 -72
- data/lib/hecks/cli/launcher_words.rb +0 -168
- data/lib/hecks/cli.rb +0 -133
- data/lib/hecks/hecks/agents.bluebook +0 -246
- data/lib/hecks/hecks/codebase.bluebook +0 -3209
- data/lib/hecks/hecks/custodian.bluebook +0 -1300
- data/lib/hecks/hecks/ledger.bluebook +0 -190
- data/lib/hecks/hecks/rehearsal.bluebook +0 -437
- data/lib/hecks/hecks/tooling.bluebook +0 -1234
- data/lib/hecks/hecks/translations/2-148748.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-15a2e4.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-1b447c.bluebook +0 -5
- data/lib/hecks/hecks/translations/2-240474.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-44446d.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-46ca26.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-473eab.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-75cc28.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-781c07.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-84c18b.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-aa5fff.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-bfdb48.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-cd96d8.bluebook +0 -10
- data/lib/hecks/hecks/translations/2-d43f71.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-eea577.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-f53248.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-fbb677.bluebook +0 -2
- data/lib/hecks/hecks/translations/2-ffdf12.bluebook +0 -6
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +0 -36
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +0 -56
- data/prebuilt/31cf81e12f16236ad26249be590cfea3799c9db67432e6a4ef54b801c355b6ae.marshal +0 -0
- data/prebuilt/68ecb2bd3abb1a221007db4f2b0375834c13aaccac8f2b99778e8517f11aa113.marshal +0 -0
- data/prebuilt/verdicts-0328c2403383837d780ad5ed81d1da351c56436b894cf9015b5d56b8f1f1bf10.json +0 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require "hecks/adapters/driving/cli_runner"
|
|
2
|
+
require_relative "index"
|
|
3
|
+
require_relative "scan"
|
|
4
|
+
require_relative "sources"
|
|
5
|
+
|
|
6
|
+
module Hecks
|
|
7
|
+
module CommandNames
|
|
8
|
+
# The check that every launcher name a file invokes is one the launcher accepts.
|
|
9
|
+
#
|
|
10
|
+
# A renamed command leaves its old name in gate rows, workflows, specs and docs, and a gate that
|
|
11
|
+
# runs a name the launcher refuses runs nothing. This reads those places for `exe/hecks <name>`
|
|
12
|
+
# and `hecks <name>` and looks each up in the launcher's own name table, once.
|
|
13
|
+
module Check
|
|
14
|
+
# One invocation the launcher would refuse.
|
|
15
|
+
Finding = Struct.new(:path, :line, :text, :problem) do
|
|
16
|
+
# @return [String] `file:line`, the string, the fault and the nearest valid name
|
|
17
|
+
def to_s
|
|
18
|
+
near = problem.nearest ? "; nearest valid name: #{problem.nearest}" : ""
|
|
19
|
+
"#{path}:#{line}: #{text[0, 120]} -- #{problem.text}#{near}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module_function
|
|
24
|
+
|
|
25
|
+
# @param root [String] the checkout
|
|
26
|
+
# @param scopes [Hash] `CliRunner.name_index`
|
|
27
|
+
# @return [Array<Finding>] every invocation the launcher would refuse, by file then line
|
|
28
|
+
def findings(root:, scopes:)
|
|
29
|
+
index = Index.new(scopes)
|
|
30
|
+
Sources.files(root).flat_map do |path|
|
|
31
|
+
Scan.new(path, File.read(File.join(root, path), encoding: "UTF-8")).calls.filter_map do |call|
|
|
32
|
+
problem = index.problem(call.words)
|
|
33
|
+
Finding.new(path, call.line, call.text, problem) if problem && !Sources.allowed?(call.text)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module CommandNames
|
|
3
|
+
# The launcher invocations in a file's text: where each is, and the words typed after it.
|
|
4
|
+
class Extractor
|
|
5
|
+
# One invocation found.
|
|
6
|
+
Call = Struct.new(:line, :text, :words)
|
|
7
|
+
|
|
8
|
+
# `exe/hecks` names the launcher wherever it appears.
|
|
9
|
+
STRONG = %r{exe/hecks(?=\s)\s+(?<rest>[^`"'|;&)>\\]*)}
|
|
10
|
+
# `exe/hecks` as the head of an argument list.
|
|
11
|
+
LISTED = %r{exe/hecks["']\s*,\s*["'](?<rest>[^"']*)}
|
|
12
|
+
# A bare `hecks` counts when a backtick opens it, or a prompt precedes it.
|
|
13
|
+
QUOTED = /(?<=`)hecks\s+(?<rest>[^`"'|;&)>\\]*)/
|
|
14
|
+
PROMPT = /(?:\A|\s)\$\s+hecks\s+(?<rest>[^`"'|;&)>\\]*)/
|
|
15
|
+
# A bare `hecks` that opens a line of shell, in a fence or a shell file.
|
|
16
|
+
SHELL = /\A\s*(?:bundle exec\s+)?hecks\s+(?<rest>[^`"'|;&)>\\]*)/
|
|
17
|
+
|
|
18
|
+
# A word that can be a launcher name, with the punctuation prose puts after it cut off.
|
|
19
|
+
NAME = /\A[A-Za-z_][\w:]*(?:\.\w+)*!?\z/
|
|
20
|
+
|
|
21
|
+
# The punctuation prose puts after a name.
|
|
22
|
+
TRAILING = /[,.;:)\]]+\z/
|
|
23
|
+
|
|
24
|
+
# A name with a regex-escaped dot (`gate_run\.gate!`): a pattern, not a launcher call.
|
|
25
|
+
ESCAPED = /[\w:!]+(?:\\\.[\w!]*)+/
|
|
26
|
+
|
|
27
|
+
# The line marker that excuses an illustrative invocation, on its own line or the one before.
|
|
28
|
+
MARKER = "dead-name-check: skip".freeze
|
|
29
|
+
|
|
30
|
+
# @param shell [Boolean] whether a line may open with a bare `hecks` (a fence, a shell file)
|
|
31
|
+
# @param strong_only [Boolean] whether only `exe/hecks` counts, as in a code comment's prose
|
|
32
|
+
def initialize(shell: false, strong_only: false)
|
|
33
|
+
@shell = shell
|
|
34
|
+
@strong_only = strong_only
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param line [String] one line of text
|
|
38
|
+
# @param number [Integer] its line number
|
|
39
|
+
# @return [Array<Call>] the invocations on it
|
|
40
|
+
def calls(line, number)
|
|
41
|
+
return [] unless line.include?("hecks")
|
|
42
|
+
|
|
43
|
+
text = line.gsub(ESCAPED, "")
|
|
44
|
+
patterns.flat_map { |pattern| text.scan(pattern).flatten }.filter_map { |rest| call(rest, number, line) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def patterns
|
|
50
|
+
return [STRONG, LISTED] if @strong_only
|
|
51
|
+
|
|
52
|
+
[STRONG, LISTED, QUOTED, PROMPT, (SHELL if @shell)].compact
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def call(rest, number, line)
|
|
56
|
+
words = words(rest)
|
|
57
|
+
Call.new(number, line.strip, words) unless words.empty?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The leading words of a line that spell a launcher name, after the flags before it.
|
|
61
|
+
def words(rest)
|
|
62
|
+
tokens = rest.split.drop_while { |token| token.start_with?("-") }
|
|
63
|
+
tokens.map { |token| token.sub(TRAILING, "") }.take_while { |token| token.match?(NAME) }.first(3)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "hecks/adapters/driving/cli_runner"
|
|
2
|
+
require_relative "resolution"
|
|
3
|
+
|
|
4
|
+
module Hecks
|
|
5
|
+
module CommandNames
|
|
6
|
+
# The launcher's accepted names, by scope, and what becomes of a typed line.
|
|
7
|
+
class Index
|
|
8
|
+
# Words the launcher answers before it looks a name up.
|
|
9
|
+
PROGRAM_WORDS = %w[help usage search tour completion resume].freeze
|
|
10
|
+
|
|
11
|
+
# @param scopes [Hash{String => Hash}] `CliRunner.name_index`
|
|
12
|
+
def initialize(scopes)
|
|
13
|
+
@scopes = scopes
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param words [Array<String>] the words after the launcher's name
|
|
17
|
+
# @return [Problem, nil] what is wrong with the line, or nil when the launcher accepts it
|
|
18
|
+
def problem(words)
|
|
19
|
+
scope, rest = scope_of(words)
|
|
20
|
+
asking = Adapters::Driving::CliRunner::QUERY_WORDS.include?(rest.first)
|
|
21
|
+
typed = rest.drop(asking ? 1 : 0).first
|
|
22
|
+
return if typed.nil? || free?(scope, typed)
|
|
23
|
+
|
|
24
|
+
Resolution.new(scope, typed, asking).problem
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# An attached bluebook's word hands the rest of the line to that bluebook.
|
|
30
|
+
def scope_of(words)
|
|
31
|
+
scope = words.first && !words.first.empty? && @scopes[words.first]
|
|
32
|
+
scope ? [scope, words.drop(1)] : [@scopes.fetch(""), words]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def free?(scope, typed)
|
|
36
|
+
PROGRAM_WORDS.include?(typed) || scope["modules"].include?(typed)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require "hecks/adapters/driving/cli_runner"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module CommandNames
|
|
5
|
+
# What is wrong with a typed line.
|
|
6
|
+
Problem = Struct.new(:text, :nearest)
|
|
7
|
+
|
|
8
|
+
# One typed word looked up the way the launcher looks it up: every spelling through
|
|
9
|
+
# `canonical_name`, the bang rule of `BangRule`, the neighbours of `Suggestions`.
|
|
10
|
+
class Resolution
|
|
11
|
+
RUNNER = Adapters::Driving::CliRunner
|
|
12
|
+
|
|
13
|
+
# The marks a name carries that a plain English word does not.
|
|
14
|
+
NAME_MARKS = /[_.]/
|
|
15
|
+
|
|
16
|
+
# @param scope [Hash] one scope of `CliRunner.name_index`
|
|
17
|
+
# @param typed [String] the word, with its `!` if it has one
|
|
18
|
+
# @param asking [Boolean] whether `query` came before it
|
|
19
|
+
def initialize(scope, typed, asking)
|
|
20
|
+
@scope = scope
|
|
21
|
+
@cli = { names: { command: scope["command"], question: scope["question"] } }
|
|
22
|
+
@typed = typed.chomp("!")
|
|
23
|
+
@bang = typed.end_with?("!")
|
|
24
|
+
@asking = asking
|
|
25
|
+
@name = RUNNER.canonical_name(@cli, @typed)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @return [Problem, nil] nil when the launcher would run the line
|
|
29
|
+
def problem
|
|
30
|
+
return unknown unless command || question
|
|
31
|
+
|
|
32
|
+
bare_command || banged_query || query_of_command
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def command = @scope["command"][@name]
|
|
38
|
+
|
|
39
|
+
def question = @scope["question"][@name]
|
|
40
|
+
|
|
41
|
+
def bare_command
|
|
42
|
+
return unless command && !@asking && !@bang
|
|
43
|
+
|
|
44
|
+
Problem.new("#{@typed} is a command and writes; write it as #{@typed}!", "#{command}!")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def banged_query
|
|
48
|
+
return unless @bang && !@asking && !command && question
|
|
49
|
+
|
|
50
|
+
Problem.new("#{@typed}! is a query and reads; write it without the !", "query #{question}")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def query_of_command
|
|
54
|
+
return unless @asking && !question
|
|
55
|
+
|
|
56
|
+
Problem.new("#{@typed} is a command, not a query", "#{command}!")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def unknown
|
|
60
|
+
return if plain? && !homed?
|
|
61
|
+
|
|
62
|
+
near = RUNNER.near_names(@cli, RUNNER.snake_form(@name), @asking).first
|
|
63
|
+
Problem.new("#{@typed} is not a command or query", near && listed(near))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# A lone word with no underscore, dot or bang is as likely English as a name.
|
|
67
|
+
def plain? = !@bang && !@typed.match?(NAME_MARKS)
|
|
68
|
+
|
|
69
|
+
# Whether the word is the last part of some name, so a launcher once accepted it bare.
|
|
70
|
+
def homed?
|
|
71
|
+
(@cli[:names][:command].keys + @cli[:names][:question].keys).any? { |key| key.split(".").last == @name }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def listed(near)
|
|
75
|
+
return "#{@scope["command"][near]}!" if @scope["command"][near]
|
|
76
|
+
|
|
77
|
+
"query #{@scope["question"][near]}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require_relative "extractor"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module CommandNames
|
|
5
|
+
# One file read for launcher invocations, leaving out the ones marked as illustrative.
|
|
6
|
+
class Scan
|
|
7
|
+
# A fence whose opening line says its content is shown and not meant to run.
|
|
8
|
+
EXCUSED_FENCE = /\b(?:skip|historical|illustrative)\b/
|
|
9
|
+
|
|
10
|
+
# @param path [String] the file's path, relative to the checkout
|
|
11
|
+
# @param text [String] its text
|
|
12
|
+
def initialize(path, text)
|
|
13
|
+
@path = path
|
|
14
|
+
@lines = text.scrub.lines
|
|
15
|
+
@markdown = path.end_with?(".md")
|
|
16
|
+
@ruby = path.end_with?(".rb")
|
|
17
|
+
@shell = !path.end_with?(".rb", ".md", ".bluebook")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [Array<Extractor::Call>] the invocations, each as `calls` of the extractor
|
|
21
|
+
def calls
|
|
22
|
+
fence = nil
|
|
23
|
+
@lines.each_with_index.flat_map do |line, index|
|
|
24
|
+
fence = fence_after(fence, line)
|
|
25
|
+
next [] if skipped?(line, index, fence)
|
|
26
|
+
|
|
27
|
+
extractor(fence, line).calls(line, index + 1)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# The open fence after a line: nil outside one, else its opening line.
|
|
34
|
+
def fence_after(fence, line)
|
|
35
|
+
return fence unless @markdown && line.lstrip.start_with?("```")
|
|
36
|
+
|
|
37
|
+
fence ? nil : line
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def skipped?(line, index, fence)
|
|
41
|
+
return true if line.lstrip.start_with?("```") || excused?(fence)
|
|
42
|
+
|
|
43
|
+
[line, (@lines[index - 1] if index.positive?)].compact.any? { |text| text.include?(Extractor::MARKER) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def excused?(fence) = fence&.match?(EXCUSED_FENCE)
|
|
47
|
+
|
|
48
|
+
# A Ruby comment is prose, so only the launcher's path names a call in it.
|
|
49
|
+
def extractor(fence, line)
|
|
50
|
+
Extractor.new(shell: @shell || !fence.nil?, strong_only: @ruby && line.lstrip.start_with?("#"))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module CommandNames
|
|
3
|
+
# The files whose text shells out to the launcher, and the ones left out.
|
|
4
|
+
module Sources
|
|
5
|
+
# Globs, relative to the checkout, of the files a line may invoke the launcher in.
|
|
6
|
+
INCLUDED = %w[
|
|
7
|
+
.github/workflows/*.yml .github/workflows/*.yaml .github/actions/**/* .githooks/*
|
|
8
|
+
lib/hecks/language/bluebook/vocabulary.bluebook Makefile scripts/**/* spec/**/*.rb
|
|
9
|
+
docs/implemented/**/*.md CLAUDE.md
|
|
10
|
+
lib/**/*.rb qa/**/*.rb qa/**/*.md qa/**/*.sh qa/**/*.yml
|
|
11
|
+
.claude/hooks/* .claude/settings.json .claude/skills/**/*.md .claude/agents/**/*.md
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
# Exact lines left unflagged. Each is a dead name kept on purpose until a person picks the
|
|
15
|
+
# command that replaces it; remove the entry when that command exists.
|
|
16
|
+
#
|
|
17
|
+
# The headers below are written into committed generated files (diagrams, the Rust syntax and
|
|
18
|
+
# phrase tables, the site routes, the kernel templates) and specs assert them, so renaming
|
|
19
|
+
# one is a regeneration of those files and its own change.
|
|
20
|
+
ALLOWED_LINES = [
|
|
21
|
+
# The mint plan's ledger line has no successor command yet.
|
|
22
|
+
"exe/hecks Maintenance.mint_era! run.value=<run-id>",
|
|
23
|
+
"hecks project_diagrams", "hecks project_parser_table", "hecks project_phrase_table",
|
|
24
|
+
"hecks measure_kernel_coverage",
|
|
25
|
+
# The installed gem's own `hecks vendor`, which a client runs outside this launcher.
|
|
26
|
+
"(the name `hecks vendor` accepts)", "`hecks site site_projection.project_site"
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
# Paths that record what was once true, so a retired name in them is history, not a fault.
|
|
30
|
+
HISTORICAL = %r{\A(?:docs/decisions/|docs/implemented/decisions/|docs/archive/|CHANGELOG\.md\z)}
|
|
31
|
+
|
|
32
|
+
# A banner in a document's first lines that says it records a moment.
|
|
33
|
+
SNAPSHOT = /\A(?:>\s*)?\*\*Historical snapshot\b/
|
|
34
|
+
|
|
35
|
+
# A line in a document's first lines that excuses the whole file, such as a page that lists
|
|
36
|
+
# the names a rename leaves behind.
|
|
37
|
+
SKIP_FILE = "dead-name-check: skip-file".freeze
|
|
38
|
+
|
|
39
|
+
# How many lines from the top count as "the first lines".
|
|
40
|
+
BANNER_WINDOW = 12
|
|
41
|
+
|
|
42
|
+
module_function
|
|
43
|
+
|
|
44
|
+
# @param root [String] the checkout
|
|
45
|
+
# @return [Array<String>] the paths to scan, relative to `root`, sorted
|
|
46
|
+
def files(root)
|
|
47
|
+
scanned(root).reject { |path| historical?(root, path) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Array<String>] every file the globs reach, relative to `root`, sorted
|
|
51
|
+
def scanned(root)
|
|
52
|
+
paths = INCLUDED.flat_map { |glob| Dir.glob(File.join(root, glob), File::FNM_DOTMATCH) }
|
|
53
|
+
relative(root, paths.select { |path| File.file?(path) })
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [Array<String>] the paths below `root`, once each, sorted
|
|
57
|
+
def relative(root, paths) = paths.map { |path| path.delete_prefix("#{root}/") }.uniq.sort
|
|
58
|
+
|
|
59
|
+
# @return [Boolean] whether a path is history: a decision record, the changelog, an archive, a
|
|
60
|
+
# document whose first lines call it a historical snapshot, or one that excuses itself
|
|
61
|
+
def historical?(root, path)
|
|
62
|
+
return true if path.match?(HISTORICAL)
|
|
63
|
+
|
|
64
|
+
File.foreach(File.join(root, path), encoding: "UTF-8").first(BANNER_WINDOW).any? { |line| excused?(line) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @return [Boolean] whether a line carries one of the allowed strings
|
|
68
|
+
def allowed?(text) = ALLOWED_LINES.any? { |allowed| text.include?(allowed) }
|
|
69
|
+
|
|
70
|
+
def excused?(line) = line.match?(SNAPSHOT) || line.include?(SKIP_FILE)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative "command_names/check"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
# Reads the places that shell out to the launcher for names the launcher does not accept.
|
|
5
|
+
module CommandNames
|
|
6
|
+
# The clean verdict.
|
|
7
|
+
CLEAN = "every launcher name invoked in workflows, hooks, gate rows, specs and docs is one the launcher accepts".freeze
|
|
8
|
+
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
# @param root [String] the checkout
|
|
12
|
+
# @param runtime [#registry] what `Hecks.describe` answers
|
|
13
|
+
# @return [String] the clean verdict
|
|
14
|
+
# @raise [Failure] with a line for each name the launcher would refuse
|
|
15
|
+
def check(root:, runtime:)
|
|
16
|
+
scopes = Adapters::Driving::CliRunner.name_index(runtime: runtime)
|
|
17
|
+
found = Check.findings(root: root, scopes: scopes)
|
|
18
|
+
raise Failure, found.join("\n") unless found.empty?
|
|
19
|
+
|
|
20
|
+
CLEAN
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised with every finding.
|
|
24
|
+
class Failure < StandardError; end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/hecks/composer/jobs.rb
CHANGED
|
@@ -35,7 +35,7 @@ module Hecks
|
|
|
35
35
|
# @param confirm [String, nil] the confirmation the runner requires, if any
|
|
36
36
|
# @return [true]
|
|
37
37
|
# @raise [Busy] when a job is running
|
|
38
|
-
def start(kind:, verb:, args: {}, confirm: nil)
|
|
38
|
+
def start(kind:, verb:, args: {}, confirm: nil)
|
|
39
39
|
@mutex.synchronize do
|
|
40
40
|
raise Busy, "a job is already running" if running?
|
|
41
41
|
|
|
@@ -157,11 +157,18 @@ module Hecks
|
|
|
157
157
|
Hecks.boot(File.join(Parse::ROOT, "lib/hecks/hecks"), install_driving: false, environment: "memory")
|
|
158
158
|
end
|
|
159
159
|
|
|
160
|
+
# A safe-listed command writes through the runner only with its bang; the list names bare commands.
|
|
161
|
+
def writing(argv)
|
|
162
|
+
return argv unless argv.first && SAFE_COMMANDS.include?(argv.first)
|
|
163
|
+
|
|
164
|
+
["#{argv.first}!", *argv.drop(1)]
|
|
165
|
+
end
|
|
166
|
+
|
|
160
167
|
# @api private
|
|
161
168
|
def invoke(argv)
|
|
162
169
|
rt = runtime
|
|
163
170
|
@lock.synchronize do
|
|
164
|
-
Hecks::Adapters::Driving::CliRunner.call(runtime: rt, program: "hecks", argv: argv)
|
|
171
|
+
Hecks::Adapters::Driving::CliRunner.call(runtime: rt, program: "hecks", argv: writing(argv))
|
|
165
172
|
end
|
|
166
173
|
end
|
|
167
174
|
end
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Corpus
|
|
7
|
+
# A content hash of everything that decides what `hecks regenerate_corpus` writes for some of
|
|
8
|
+
# the corpus's domains: the generator, and each named domain's own sources. A job that reads a
|
|
9
|
+
# few domains of the generated tree keys its cache on those, so a change to any other domain
|
|
10
|
+
# leaves its cache where it was.
|
|
11
|
+
#
|
|
12
|
+
# The hash reads file contents only, never a time, and only tracked files: a bare checkout and
|
|
13
|
+
# one that has already regenerated hash the same. It errs wide, never narrow: a file that might
|
|
14
|
+
# be read is hashed, so a key can move for a change that did not matter, and never stay put for
|
|
15
|
+
# one that did.
|
|
16
|
+
#
|
|
17
|
+
# Hecks::Corpus::GeneratedKey.key(%w[lease_clock nested_pieces]) # => "9c1e..."
|
|
18
|
+
module GeneratedKey
|
|
19
|
+
# Bumped when what the key hashes changes shape, so every saved entry stops matching.
|
|
20
|
+
VERSION = "1"
|
|
21
|
+
|
|
22
|
+
# What the generator is made of, relative to the checkout: the Rust crates it runs, and the
|
|
23
|
+
# Ruby that builds the IR it reads. Every domain's output depends on all of it.
|
|
24
|
+
GENERATOR_INPUTS = %w[
|
|
25
|
+
rust/codegen/**/* rust/build/**/* rust/parser/**/* rust/Cargo.toml rust/src/generated/mod.rs
|
|
26
|
+
lib/hecks/rust_build/**/* lib/hecks/projector/**/* lib/hecks/corpus/**/* lib/hecks/corpus.rb
|
|
27
|
+
lib/hecks/tools/regeneration_run.rb lib/hecks/tools/regeneration_run/**/*
|
|
28
|
+
lib/hecks/bluebook/**/* lib/hecks/language/**/*
|
|
29
|
+
lib/hecks/runtime/**/* lib/hecks/ports/**/* lib/hecks/rust_format.rb rust-toolchain.toml Gemfile.lock
|
|
30
|
+
lib/hecks/*.rb lib/hecks/grammar/**/* lib/hecks/literal/**/*
|
|
31
|
+
lib/hecks/adapters/driven/*.adapter lib/hecks/adapters/driven/folder*
|
|
32
|
+
].freeze
|
|
33
|
+
|
|
34
|
+
# The generated modules hashed into every key, whichever domains are named: pizzas, whose
|
|
35
|
+
# translations carry SQL only the Ruby toolchain compiles, so it is not a function of its
|
|
36
|
+
# own bluebook alone.
|
|
37
|
+
COMMITTED_OUTPUT = %w[pizzas].freeze
|
|
38
|
+
|
|
39
|
+
# Every bluebook, hecksagon, world and adapter file of the gem: what a domain that attaches a
|
|
40
|
+
# bluebook this key cannot name exactly is hashed against.
|
|
41
|
+
ALL_BLUEBOOK_FILES = %w[lib/hecks/**/*.bluebook lib/hecks/**/*.hecksagon lib/hecks/**/*.world
|
|
42
|
+
lib/hecks/**/adapters/*.adapter].freeze
|
|
43
|
+
|
|
44
|
+
# The one way a hecksagon attaches a gem bluebook or a vendored package, which this key can
|
|
45
|
+
# follow exactly.
|
|
46
|
+
ATTACHES_LINE = /\A\s*attaches\s+"(?<name>\w+)"(?<vendored>,\s*from:\s*:vendor)?\s*(?:#.*)?\z/
|
|
47
|
+
|
|
48
|
+
# Any other line that names an attachment, which this key cannot follow: it hashes wide.
|
|
49
|
+
ATTACHMENT_WORD = /\battaches\b|FrameworkBluebooks\.|\battach!|Framework\.load!/
|
|
50
|
+
|
|
51
|
+
# The files a hecksagon's own text can name an attachment in.
|
|
52
|
+
ATTACHING_FILES = /\.(hecksagon|world|adapter)\z/
|
|
53
|
+
|
|
54
|
+
# The directory of the gem's Ruby, which a bluebook's absolute path is read relative to.
|
|
55
|
+
GEM_LIB = File.expand_path("..", __dir__).freeze
|
|
56
|
+
|
|
57
|
+
# Raised inside this module when an attachment cannot be followed to the files it reads.
|
|
58
|
+
class Unresolved < StandardError; end
|
|
59
|
+
|
|
60
|
+
module_function
|
|
61
|
+
|
|
62
|
+
# The key of the generated output of the named domains.
|
|
63
|
+
#
|
|
64
|
+
# @param names [Array<String>, nil] feature names; nil names every domain
|
|
65
|
+
# @param root [String] the checkout
|
|
66
|
+
# @return [String] the hex digest
|
|
67
|
+
# @raise [UnknownDomain] when a name is not a domain, listing the valid ones
|
|
68
|
+
def key(names = nil, root: ROOT)
|
|
69
|
+
digest(listing(names, root: root))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @param lines [Array<String>] the rows of `listing`
|
|
73
|
+
# @return [String] the hex digest the rows add up to
|
|
74
|
+
def digest(lines) = Digest::SHA256.hexdigest("generated-key-#{VERSION}\n#{lines.join("\n")}")
|
|
75
|
+
|
|
76
|
+
# What `hecks corpus_run.generated_key` answers: the key, with each file hashed above it when
|
|
77
|
+
# they are asked for.
|
|
78
|
+
#
|
|
79
|
+
# @param names [Array<String>, nil] feature names; nil names every domain
|
|
80
|
+
# @param files [Boolean] whether to list each file hashed, with its own digest
|
|
81
|
+
# @param root [String] the checkout
|
|
82
|
+
# @return [String] the lines
|
|
83
|
+
# @raise [UnknownDomain] when a name is not a domain, listing the valid ones
|
|
84
|
+
def report(names = nil, files: false, root: ROOT)
|
|
85
|
+
rows = listing(names, root: root)
|
|
86
|
+
[*(rows if files), digest(rows)].join("\n")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Each file the key hashes, with its own digest, so a reviewer can see why a key moved.
|
|
90
|
+
#
|
|
91
|
+
# @param names [Array<String>, nil] feature names; nil names every domain
|
|
92
|
+
# @param root [String] the checkout
|
|
93
|
+
# @return [Array<String>] `"<sha256> <path>"` rows, sorted by path
|
|
94
|
+
# @raise [UnknownDomain] when a name is not a domain, listing the valid ones
|
|
95
|
+
def listing(names = nil, root: ROOT)
|
|
96
|
+
files(names, root: root).map { |path| "#{Digest::SHA256.file(File.join(root, path)).hexdigest} #{path}" }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @param names [Array<String>, nil] feature names; nil names every domain
|
|
100
|
+
# @param root [String] the checkout
|
|
101
|
+
# @return [Array<String>] the paths the key hashes, relative to the checkout, sorted
|
|
102
|
+
# @raise [UnknownDomain] when a name is not a domain, listing the valid ones
|
|
103
|
+
def files(names = nil, root: ROOT)
|
|
104
|
+
domains = Corpus.rust_domains_named(names, root: root)
|
|
105
|
+
(generator_files(root) + domains.flat_map { |domain| domain_files(domain, root) }).uniq.sort
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @return [Array<String>] the generator's files that exist, and the committed generated output
|
|
109
|
+
def generator_files(root)
|
|
110
|
+
globs = GENERATOR_INPUTS + COMMITTED_OUTPUT.map { |feature| "rust/src/generated/#{feature}/**/*" }
|
|
111
|
+
globs.flat_map { |glob| expand(glob, root) }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# One domain's own directory and every bluebook it attaches.
|
|
115
|
+
#
|
|
116
|
+
# @param domain [RustDomain] the domain
|
|
117
|
+
# @param root [String] the checkout
|
|
118
|
+
# @return [Array<String>] the paths, relative to the checkout
|
|
119
|
+
def domain_files(domain, root)
|
|
120
|
+
own = expand("#{domain.dir.delete_prefix("#{root}/")}/**/*", root)
|
|
121
|
+
own + attached_files(own, root)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# The files of every bluebook the domain's own hecksagons attach, followed through the ports
|
|
125
|
+
# and adapters a bluebook ships. A bluebook this cannot follow exactly widens to all of them.
|
|
126
|
+
#
|
|
127
|
+
# @param own [Array<String>] the domain's own files, relative to the checkout
|
|
128
|
+
# @param root [String] the checkout
|
|
129
|
+
# @return [Array<String>] the bluebook files, relative to the checkout
|
|
130
|
+
def attached_files(own, root)
|
|
131
|
+
follow(names_in(own, root).uniq, root)
|
|
132
|
+
rescue Unresolved
|
|
133
|
+
ALL_BLUEBOOK_FILES.flat_map { |glob| expand(glob, root) }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @param path [String] a hecksagon, world or adapter file, relative to the checkout
|
|
137
|
+
# @param root [String] the checkout
|
|
138
|
+
# @return [Array<String>] the gem bluebooks it attaches, by name
|
|
139
|
+
# @raise [Unresolved] when it names an attachment in a way this does not follow
|
|
140
|
+
def attached_names(path, root)
|
|
141
|
+
File.readlines(File.join(root, path), chomp: true, encoding: "UTF-8").filter_map do |line|
|
|
142
|
+
next if line.strip.start_with?("#") || !line.match?(ATTACHMENT_WORD)
|
|
143
|
+
|
|
144
|
+
match = ATTACHES_LINE.match(line) or raise Unresolved, "#{path}: #{line.strip}"
|
|
145
|
+
match[:name] unless match[:vendored]
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Every file of the named bluebooks and of the bluebooks their own hecksagons attach.
|
|
150
|
+
#
|
|
151
|
+
# @param pending [Array<String>] bluebook names still to read
|
|
152
|
+
# @param root [String] the checkout
|
|
153
|
+
# @return [Array<String>] the files, relative to the checkout
|
|
154
|
+
# @raise [Unresolved] when a bluebook is not one the gem carries
|
|
155
|
+
def follow(pending, root)
|
|
156
|
+
files = []
|
|
157
|
+
seen = []
|
|
158
|
+
while (name = pending.shift)
|
|
159
|
+
next if seen.include?(name)
|
|
160
|
+
|
|
161
|
+
seen << name
|
|
162
|
+
files.concat(bluebook = bluebook_paths(name, root))
|
|
163
|
+
pending.concat(names_in(bluebook, root))
|
|
164
|
+
end
|
|
165
|
+
files
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# @param paths [Array<String>] files relative to the checkout
|
|
169
|
+
# @param root [String] the checkout
|
|
170
|
+
# @return [Array<String>] the bluebooks the hecksagons, worlds and adapters among them attach
|
|
171
|
+
# @raise [Unresolved] when one names an attachment in a way this does not follow
|
|
172
|
+
def names_in(paths, root)
|
|
173
|
+
paths.grep(ATTACHING_FILES).flat_map { |path| attached_names(path, root) }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# @param name [String] a bluebook's name
|
|
177
|
+
# @param root [String] the checkout
|
|
178
|
+
# @return [Array<String>] the files attaching it reads, relative to the checkout
|
|
179
|
+
# @raise [Unresolved] when the gem carries no bluebook of that name
|
|
180
|
+
def bluebook_paths(name, root)
|
|
181
|
+
require_relative "../framework_bluebooks"
|
|
182
|
+
FrameworkBluebooks.files_of(name).map do |path|
|
|
183
|
+
raise Unresolved, "#{name}: #{path} is outside the gem" unless path.start_with?("#{GEM_LIB}/")
|
|
184
|
+
|
|
185
|
+
relative = File.join("lib/hecks", path.delete_prefix("#{GEM_LIB}/"))
|
|
186
|
+
File.file?(File.join(root, relative)) ? relative : nil
|
|
187
|
+
end.compact
|
|
188
|
+
rescue Runtime::WiringError => e
|
|
189
|
+
raise Unresolved, e.message
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# The files a glob finds, relative to the checkout: no directory, and nothing under a Cargo
|
|
193
|
+
# `target`, which a build fills and a bare checkout does not have.
|
|
194
|
+
#
|
|
195
|
+
# @param glob [String] a glob, relative to the checkout
|
|
196
|
+
# @param root [String] the checkout
|
|
197
|
+
# @return [Array<String>] the paths
|
|
198
|
+
def expand(glob, root)
|
|
199
|
+
Dir.glob(glob, File::FNM_DOTMATCH, base: root).select do |path|
|
|
200
|
+
File.file?(File.join(root, path)) && !path.split("/").include?("target") && File.basename(path) != ".DS_Store"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Hecks
|
|
2
|
+
module Corpus
|
|
3
|
+
# How a kind's glob becomes its members: a directory each, or a file each.
|
|
4
|
+
# Extended onto `Corpus`.
|
|
5
|
+
module Listing
|
|
6
|
+
# @return [Array<Member>] the members of one kind: a directory each, or a file each
|
|
7
|
+
# @raise [ArgumentError] if `kind` is not in `KINDS`
|
|
8
|
+
def kind_members(kind, root)
|
|
9
|
+
if (glob = DIRECTORY_KINDS[kind])
|
|
10
|
+
directory_members(kind, root, glob)
|
|
11
|
+
elsif (glob = FILE_KINDS[kind])
|
|
12
|
+
file_members(kind, root, glob)
|
|
13
|
+
else
|
|
14
|
+
raise ArgumentError, "unknown corpus kind #{kind.inspect} — known: #{KINDS.join(", ")}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def directory_members(kind, root, glob)
|
|
19
|
+
directories(root, glob).map { |dir| Member.new(File.basename(dir), kind, dir) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def directories(root, glob) = Dir.glob(File.join(root, glob)).select { |path| File.directory?(path) }.sort
|
|
23
|
+
|
|
24
|
+
# The part of a glob before its first wildcard.
|
|
25
|
+
GLOB_FIXED_PREFIX = /\A[^*]*/
|
|
26
|
+
|
|
27
|
+
def file_members(kind, root, glob)
|
|
28
|
+
prefix = File.join(root, glob[GLOB_FIXED_PREFIX].chomp("/"))
|
|
29
|
+
Dir.glob(File.join(root, glob))
|
|
30
|
+
.map { |file| Member.new(file.delete_prefix("#{prefix}/").delete_suffix(".bluebook"), kind, file) }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|