hecks 7.0.0 → 7.1.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/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +2 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +4 -2
- data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +16 -8
- data/lib/hecks/adapters/driven/postgres_era/lineage/transform_sql.rb +7 -3
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +2 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +2 -1
- data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +2 -1
- data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +3 -0
- data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +2 -0
- data/lib/hecks/adapters/driving/cli_runner/read_context.rb +6 -3
- data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +2 -1
- data/lib/hecks/adapters/driving/cli_runner/resolution.rb +2 -2
- data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +1 -0
- data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +6 -3
- data/lib/hecks/adapters/driving/cli_runner/search_words.rb +2 -0
- data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +1 -0
- data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +2 -1
- data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +2 -0
- data/lib/hecks/adapters/driving/cli_runner/word_help.rb +40 -0
- data/lib/hecks/adapters/driving/cli_runner.rb +2 -0
- data/lib/hecks/adapters/driving/mcp/progress_sink.rb +4 -2
- data/lib/hecks/adapters/driving/mcp.rb +2 -1
- data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +2 -1
- data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +28 -14
- data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +4 -2
- data/lib/hecks/assembly.rb +18 -4
- data/lib/hecks/behaviors/expectations/adapter_selection.rb +82 -0
- data/lib/hecks/behaviors/expectations/boot.rb +12 -5
- data/lib/hecks/bluebook/acknowledgements.rb +1 -1
- data/lib/hecks/bluebook/command.rb +3 -2
- data/lib/hecks/bluebook/declaration.rb +2 -1
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +9 -1
- data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +6 -4
- data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +6 -3
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +2 -1
- data/lib/hecks/bluebook/dsl/command_builder/folded_sets.rb +4 -2
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +2 -1
- data/lib/hecks/bluebook/hecksagon.rb +6 -3
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +9 -2
- data/lib/hecks/bluebook/meta_validator.rb +1 -1
- data/lib/hecks/bluebook/model_check/aggregate_checks.rb +2 -1
- data/lib/hecks/bluebook/model_check/classification_checks.rb +51 -0
- data/lib/hecks/bluebook/model_check/context_checks.rb +2 -0
- data/lib/hecks/bluebook/model_check/redundant_relationships.rb +2 -1
- data/lib/hecks/ci_speed/adapters/shard_partitioner.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/shard_partitioner.rb +66 -0
- data/lib/hecks/ci_speed/adapters/timings_source.adapter +7 -0
- data/lib/hecks/ci_speed/adapters/timings_source.rb +68 -0
- data/lib/hecks/ci_speed/ci_speed.bluebook +111 -0
- data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +22 -0
- data/lib/hecks/ci_workflows/ci_workflows.bluebook +50 -6
- data/lib/hecks/coder/coder.bluebook +3 -1
- data/lib/hecks/command_names/index.rb +1 -1
- data/lib/hecks/command_names/resolution.rb +15 -5
- data/lib/hecks/composer/toolbox.rb +2 -1
- data/lib/hecks/corpus.rb +4 -0
- data/lib/hecks/doc/reference/readme.rb +1 -1
- data/lib/hecks/framework_bluebooks.rb +3 -2
- data/lib/hecks/fuzzing/differential.rb +1 -1
- data/lib/hecks/fuzzing/era_boundary.rb +1 -1
- data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +1 -1
- data/lib/hecks/fuzzing/persistence_parity.rb +1 -1
- data/lib/hecks/fuzzing/target_capabilities.rb +1 -1
- data/lib/hecks/hecks/adapters/ci_runs.adapter +7 -0
- data/lib/hecks/hecks/adapters/ci_runs.rb +80 -0
- data/lib/hecks/hecks/adapters/claude_agent_list.rb +43 -0
- data/lib/hecks/hecks/adapters/claude_agents.rb +50 -19
- data/lib/hecks/hecks/adapters/claude_jobs.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +2 -1
- data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +4 -2
- data/lib/hecks/hecks/adapters/codebase/run_options.rb +2 -1
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +3 -19
- data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +5 -3
- data/lib/hecks/hecks/adapters/dispatching/launcher.rb +2 -1
- data/lib/hecks/hecks/adapters/dispatching/plan.rb +8 -4
- data/lib/hecks/hecks/adapters/dispatching/settings.rb +2 -1
- data/lib/hecks/hecks/adapters/dispatching/settler.rb +4 -2
- data/lib/hecks/hecks/adapters/dispatching.rb +6 -3
- data/lib/hecks/hecks/adapters/doctor_reading.rb +4 -2
- data/lib/hecks/hecks/adapters/git_landing/carried.rb +42 -0
- data/lib/hecks/hecks/adapters/git_landing/finisher.rb +2 -1
- data/lib/hecks/hecks/adapters/git_landing/flagged.rb +32 -0
- data/lib/hecks/hecks/adapters/git_landing/tidy.rb +27 -14
- data/lib/hecks/hecks/adapters/git_landing.rb +30 -13
- data/lib/hecks/hecks/adapters/git_leftovers.adapter +7 -0
- data/lib/hecks/hecks/adapters/git_leftovers.rb +49 -0
- data/lib/hecks/hecks/adapters/git_main_pull.rb +2 -2
- data/lib/hecks/hecks/adapters/git_train.rb +9 -5
- data/lib/hecks/hecks/adapters/git_worktree_add.rb +8 -4
- data/lib/hecks/hecks/adapters/github_pull_requests.rb +2 -1
- data/lib/hecks/hecks/adapters/in_process_operations.rb +2 -1
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +1 -1
- data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +2 -1
- data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +4 -2
- data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +4 -2
- data/lib/hecks/hecks/adapters/landed_branches.rb +38 -0
- data/lib/hecks/hecks/adapters/main_boarding.adapter +7 -0
- data/lib/hecks/hecks/adapters/main_boarding.rb +85 -0
- data/lib/hecks/hecks/adapters/main_integration/checks.rb +63 -0
- data/lib/hecks/hecks/adapters/main_integration/command_runner.rb +32 -0
- data/lib/hecks/hecks/adapters/main_integration/range_guard.rb +49 -0
- data/lib/hecks/hecks/adapters/main_integration/repository.rb +83 -0
- data/lib/hecks/hecks/adapters/main_integration/runs.rb +51 -0
- data/lib/hecks/hecks/adapters/main_integration/train.rb +74 -0
- data/lib/hecks/hecks/adapters/main_integration.adapter +7 -0
- data/lib/hecks/hecks/adapters/main_integration.rb +77 -0
- data/lib/hecks/hecks/adapters/main_verification.adapter +7 -0
- data/lib/hecks/hecks/adapters/main_verification.rb +89 -0
- data/lib/hecks/hecks/adapters/push_recorder.adapter +7 -0
- data/lib/hecks/hecks/adapters/push_recorder.rb +78 -0
- data/lib/hecks/hecks/adapters/red_flag_guard.rb +62 -0
- data/lib/hecks/hecks/adapters/red_flag_marker.rb +101 -0
- data/lib/hecks/hecks/adapters/red_flag_report.rb +59 -0
- data/lib/hecks/hecks/adapters/red_flag_survey.rb +65 -0
- data/lib/hecks/hecks/adapters/red_flagging.adapter +7 -0
- data/lib/hecks/hecks/adapters/red_flagging.rb +98 -0
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +6 -1
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +6 -3
- data/lib/hecks/hecks/adapters/settings_reading/event_tap_row.rb +33 -0
- data/lib/hecks/hecks/adapters/settings_reading.rb +3 -1
- data/lib/hecks/hecks/codebase.behaviors +0 -6
- data/lib/hecks/hecks/custodian.behaviors +22 -1
- data/lib/hecks/hecks/delegate/delegate.bluebook +128 -15
- data/lib/hecks/hecks/deliver/deliver.bluebook +450 -2
- data/lib/hecks/hecks/environments/memory.world +5 -0
- data/lib/hecks/hecks/hecks.contextmap +8 -0
- data/lib/hecks/hecks/hecks.hecksagon +106 -6
- data/lib/hecks/hecks/hecks.world +9 -1
- data/lib/hecks/hecks/migrate/migrate.bluebook +6 -1
- data/lib/hecks/hecks/redflag/redflag.bluebook +249 -0
- data/lib/hecks/hecks/test/test.bluebook +0 -19
- data/lib/hecks/language/adapter.bluebook +13 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +8 -9
- data/lib/hecks/language/sentence/sentence.bluebook +2 -0
- data/lib/hecks/pipeline/pipeline.bluebook +251 -0
- data/lib/hecks/pipeline/pipeline.hecksagon +17 -0
- data/lib/hecks/pipeline_board/adapters/cache.rb +43 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_fill.rb +56 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_git.rb +82 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_github/runs.rb +66 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_github.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_github.rb +70 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_jobs.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_jobs.rb +87 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_journal/chain.rb +40 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_journal/tap.rb +75 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_journal.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_journal.rb +83 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/ci_tiles.rb +85 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/fanout.rb +73 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/gather.rb +57 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/metrics.rb +36 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/strip.rb +102 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/tile_kit.rb +57 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages/work_tiles.rb +59 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_stages.rb +84 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_tickets.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_tickets.rb +77 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/page.html +292 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/sequence.html +190 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/server.rb +105 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/snapshot.rb +57 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/stream.rb +59 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web/wiring.html +536 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_web.rb +80 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_wiring/details.rb +85 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_wiring/graph.rb +120 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_wiring.adapter +7 -0
- data/lib/hecks/pipeline_board/adapters/pipeline_wiring.rb +36 -0
- data/lib/hecks/pipeline_board/adapters/probe.rb +48 -0
- data/lib/hecks/pipeline_board/pipeline_board.bluebook +144 -0
- data/lib/hecks/pipeline_board/pipeline_board.hecksagon +12 -0
- data/lib/hecks/pipeline_board/pipeline_board.ports.hecksagon +47 -0
- data/lib/hecks/ports/persistence/binding_policy.rb +2 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +4 -3
- data/lib/hecks/ports/persistence/repository_factory.rb +2 -1
- data/lib/hecks/projections/ci_pipeline/table.rb +2 -1
- data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +2 -2
- data/lib/hecks/projections/undo.rb +2 -1
- data/lib/hecks/projector/cli_projector/command_help.rb +5 -4
- data/lib/hecks/projector/cli_projector/renames.rb +4 -2
- data/lib/hecks/projector/cli_projector/usage.rb +4 -3
- data/lib/hecks/projector/exporter/adapters.rb +3 -2
- data/lib/hecks/projector/narrate_projector/use_cases.rb +74 -0
- data/lib/hecks/projector/narrate_projector.rb +10 -3
- data/lib/hecks/quality_control/adapters/main_maintenance.rb +9 -5
- data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +21 -2
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +2 -1
- data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +8 -4
- data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +10 -8
- data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +6 -3
- data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +8 -4
- data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +4 -2
- data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +8 -4
- data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +3 -2
- data/lib/hecks/quality_control/cli/qa_main_gate.rb +10 -5
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_tick.rb +6 -3
- data/lib/hecks/quality_control/quality_control.bluebook +11 -11
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +6 -3
- data/lib/hecks/query_ir/touchpoints.rb +2 -1
- data/lib/hecks/refused.rb +2 -1
- data/lib/hecks/release/approval.rb +4 -2
- data/lib/hecks/runtime/event_log.rb +27 -0
- data/lib/hecks/runtime/event_tap.rb +106 -0
- data/lib/hecks/runtime/loader/boot_steps.rb +1 -1
- data/lib/hecks/runtime/loader.rb +35 -19
- data/lib/hecks/runtime/registry/durability_warnings.rb +12 -5
- data/lib/hecks/runtime/registry/runtime_state.rb +4 -1
- data/lib/hecks/runtime/registry/saga_anchor.rb +54 -0
- data/lib/hecks/runtime/registry/saga_durability_rule.rb +66 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +58 -12
- data/lib/hecks/runtime/registry/verification.rb +7 -3
- data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +2 -1
- data/lib/hecks/runtime/saga_interpreter.rb +1 -1
- data/lib/hecks/rust_format.rb +2 -1
- data/lib/hecks/shape_ledger/edge_hygiene.rb +10 -5
- data/lib/hecks/shape_ledger.rb +1 -1
- data/lib/hecks/storehouse/audit.rb +2 -1
- data/lib/hecks/storehouse/identity.rb +6 -3
- data/lib/hecks/storehouse.rb +2 -1
- data/lib/hecks/tickets/bluebook/tickets.bluebook +5 -4
- data/lib/hecks/tools/ci_workflows.rb +2 -1
- data/lib/hecks/tools/document.rb +12 -1
- data/lib/hecks/tools/downstream_model_check.rb +4 -2
- data/lib/hecks/tools/fuzz_sweep/shards.rb +9 -30
- data/lib/hecks/tools/model_check/examination.rb +25 -2
- data/lib/hecks/tools/move_disables.rb +4 -2
- data/lib/hecks/tools/regeneration_run/scratch.rb +2 -1
- data/lib/hecks/tools/rspec_shard_files.rb +12 -15
- data/lib/hecks/tools/sequence_script.rb +1 -1
- data/lib/hecks/tools/shard_planner.rb +65 -0
- data/lib/hecks/tools/stage_progress.rb +2 -1
- data/lib/hecks/tools/stress_concurrency_specs.rb +2 -1
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +8 -9
- data/lib/hecks.rb +5 -2
- data/prebuilt/{13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal → 4b81646f769ae5b1e7457f9b11c48d8bc1093e96a1dd6fb61864065121ca6f01.marshal} +0 -0
- data/prebuilt/{e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal → 681890632e3f4a99646623dcae44af36b1bad66c515f5abf67a2460372b9c6fd.marshal} +0 -0
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/parser/src/emit.rs +5 -1
- data/rust/parser/src/ir.rs +2 -0
- data/rust/parser/src/keywords.rs +12 -0
- data/rust/parser/src/main.rs +1 -0
- data/rust/parser/src/parse/adapter.rs +1 -0
- data/rust/parser/src/phrases.rs +16 -0
- data/rust/parser/src/sentence/examples.rs +93 -0
- data/rust/parser/src/sentence/mod.rs +1 -0
- metadata +89 -5
- data/lib/hecks/tools/refresh_rspec_runtime_baseline.rb +0 -166
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "git"
|
|
4
|
+
require_relative "console_capture"
|
|
5
|
+
require_relative "red_flag_marker"
|
|
6
|
+
require_relative "red_flag_report"
|
|
7
|
+
require_relative "red_flag_survey"
|
|
8
|
+
|
|
9
|
+
module Hecks
|
|
10
|
+
module Adapters
|
|
11
|
+
# The `Flagging` port's adapter for `RedFlag`: raises, notes, checks in to and lowers the red
|
|
12
|
+
# flag of a repository, reads its status, and surveys the latest CI run of main to raise or
|
|
13
|
+
# lower it. The flag is `RedFlagMarker`'s file; nothing else is touched.
|
|
14
|
+
class RedFlagging
|
|
15
|
+
# The CI run id in a report such as `abc: CI run 12 failure; failed jobs: a, b`.
|
|
16
|
+
RUN_ID = /run (\d+)/
|
|
17
|
+
# The failed jobs in that report.
|
|
18
|
+
JOBS = /failed jobs: (.*)\z/
|
|
19
|
+
|
|
20
|
+
# @param aggregate [Object, nil] unused
|
|
21
|
+
# @param settings [Hash] unused
|
|
22
|
+
# @param root [String, nil] unused
|
|
23
|
+
# @param tune [Hash] `checkout:` the repository, `clock:` and `runner:` (for a spec)
|
|
24
|
+
def initialize(aggregate: nil, settings: {}, root: nil, **tune)
|
|
25
|
+
@tune = tune
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @param held [Hash] the `RedFlag` record: `commit`, `detail`, `rows`, `checkout`
|
|
29
|
+
# @return [Hash{Symbol => Hash}] `outcome:` (`raised` or `noted`) and the flag's facts
|
|
30
|
+
def hoist(**held)
|
|
31
|
+
detail = pick(held, :detail, :report).to_s
|
|
32
|
+
facts = { ci_run: detail[RUN_ID, 1], jobs: detail[JOBS, 1], rows: plain(held[:rows]) }
|
|
33
|
+
state, flag = marker(held).raise!(commit: pick(held, :commit, :landed).to_s, run: facts)
|
|
34
|
+
answer(state.to_s, flag, facts)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param held [Hash] the `RedFlag` record: `session`, `taking`, `checkout`
|
|
38
|
+
# @return [Hash{Symbol => Hash}] `outcome:` (`checked_in`) and the flag's facts
|
|
39
|
+
# @raise [ConsoleCapture::Failure] when no flag stands
|
|
40
|
+
def sign_in(**held)
|
|
41
|
+
flag = marker(held).check_in!(session: plain(held[:session]).to_s, taking: plain(held[:taking]).to_s)
|
|
42
|
+
raise ConsoleCapture::Failure, "no red flag stands: nothing to check in to" unless flag
|
|
43
|
+
|
|
44
|
+
answer("checked_in", flag, session: plain(held[:session]), taking: plain(held[:taking]))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @param held [Hash] the `RedFlag` record: `checkout`
|
|
48
|
+
# @return [Hash{Symbol => Hash}] `outcome:` (`cleared`, or `idle` when none stood)
|
|
49
|
+
def lower(**held)
|
|
50
|
+
flag = marker(held).clear!
|
|
51
|
+
flag ? answer("cleared", flag, {}) : { outcome: { value: "idle" }, output: { value: "no red flag was standing" } }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Reads the latest completed CI run of main and raises or lowers the flag to match it.
|
|
55
|
+
#
|
|
56
|
+
# @param held [Hash] the `RedFlag` record: `checkout`
|
|
57
|
+
# @return [Hash{Symbol => Hash}] `outcome:` as {#hoist} and {#lower}, or `idle` while a run is
|
|
58
|
+
# still going
|
|
59
|
+
def survey(**held)
|
|
60
|
+
seen = RedFlagSurvey.new(runner: @tune[:runner], checkout: checkout(held)).latest
|
|
61
|
+
return hoist(commit: seen[:commit], detail: seen[:detail]) if seen[:verdict] == :red
|
|
62
|
+
return lower(**held) if seen[:verdict] == :green
|
|
63
|
+
|
|
64
|
+
{ outcome: { value: "idle" }, output: { value: seen[:detail] } }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @param held [Hash] `checkout`
|
|
68
|
+
# @return [Hash{Symbol => String}] `text:` the flag in words, or that none stands
|
|
69
|
+
def status(**held)
|
|
70
|
+
flag = marker(held).read
|
|
71
|
+
{ text: flag ? "#{RedFlagReport.new(flag).text}\n" : "main is not flagged\n" }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def answer(outcome, flag, facts)
|
|
77
|
+
{ outcome: { value: outcome }, flag: { value: flag["id"] }, commit: { value: flag["commit"].to_s },
|
|
78
|
+
ci_run: { value: facts[:ci_run].to_s }, jobs: { value: facts[:jobs].to_s }, rows: { value: facts[:rows].to_s },
|
|
79
|
+
session: { value: facts[:session].to_s }, taking: { value: facts[:taking].to_s } }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def marker(held) = RedFlagMarker.new(git_dir(held), **@tune.slice(:clock))
|
|
83
|
+
|
|
84
|
+
def git_dir(held)
|
|
85
|
+
ok = Git.new.capture("rev-parse", "--path-format=absolute", "--git-common-dir", chdir: checkout(held))
|
|
86
|
+
raise ConsoleCapture::Failure, "#{checkout(held)} is not a repository" unless ok.ok?
|
|
87
|
+
|
|
88
|
+
ok.out.strip
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def checkout(held) = plain(held[:checkout]) || @tune[:checkout] || Dir.pwd
|
|
92
|
+
|
|
93
|
+
def pick(held, *keys) = plain(held[keys.find { |key| held.key?(key) }])
|
|
94
|
+
|
|
95
|
+
def plain(argument) = argument.is_a?(Hash) ? argument[:value] : argument
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -82,7 +82,12 @@ module Hecks
|
|
|
82
82
|
def answer(edge, report, refused, unchecked)
|
|
83
83
|
rows, total = Rows.from(refused)
|
|
84
84
|
edge_facts(edge).merge(refused_rows: rows, refusal_total: plain(total), parity: report.parity,
|
|
85
|
-
unchecked: unchecked).merge(report.facts)
|
|
85
|
+
unchecked: unchecked).merge(report.facts).merge(record_facts)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# The domain and the ledger watermark the copy held: what a mint's record of this rehearsal names.
|
|
89
|
+
def record_facts
|
|
90
|
+
{ rehearsed_domain: @subject.bluebook_name, watermark: @store.watermark(@subject) }
|
|
86
91
|
end
|
|
87
92
|
|
|
88
93
|
def flag(value) = plain(value)
|
|
@@ -84,7 +84,8 @@ module Hecks
|
|
|
84
84
|
|
|
85
85
|
private
|
|
86
86
|
|
|
87
|
-
# A split target's "before": its source's held records, fanned out one per key the split
|
|
87
|
+
# A split target's "before": its source's held records, fanned out one per key the split
|
|
88
|
+
# names,
|
|
88
89
|
# carrying the split's fields (ADR 0166). Nil when the aggregate is not a split target.
|
|
89
90
|
def split_before(edge, aggregate)
|
|
90
91
|
source, split = split_source_for(edge, aggregate)
|
|
@@ -100,7 +101,8 @@ module Hecks
|
|
|
100
101
|
[]
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
# One target record per source record that carries the split's key, holding the split's
|
|
104
|
+
# One target record per source record that carries the split's key, holding the split's
|
|
105
|
+
# fields.
|
|
104
106
|
def fanned_out(held, split)
|
|
105
107
|
fields = split.fields.map(&:to_s)
|
|
106
108
|
held.filter_map do |_id, state|
|
|
@@ -120,7 +122,8 @@ module Hecks
|
|
|
120
122
|
held.filter_map { |_id, state| fanned_row(state, split.keyed_by.to_s, fields) }.to_h
|
|
121
123
|
end
|
|
122
124
|
|
|
123
|
-
# One target row keyed by the held record's key, a value object's `value` member when it has
|
|
125
|
+
# One target row keyed by the held record's key, a value object's `value` member when it has
|
|
126
|
+
# one.
|
|
124
127
|
def fanned_row(state, key, fields)
|
|
125
128
|
value = state[key]
|
|
126
129
|
value = value["value"] if value.is_a?(Hash)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class SettingsReading
|
|
6
|
+
# The `event tap` row of `hecks config`: where the runtime's event tap writes, and whether
|
|
7
|
+
# the `HECKS_EVENT_TAP` variable, the world or neither says.
|
|
8
|
+
module EventTapRow
|
|
9
|
+
# @param directory [String] the domain directory
|
|
10
|
+
# @return [Array(String, String, String)] the row's name, value and source
|
|
11
|
+
def event_tap(directory)
|
|
12
|
+
declared = declared_event_log(directory)
|
|
13
|
+
return ["event tap", "none declared", "default"] if declared.empty?
|
|
14
|
+
return ["event tap", "off", "world"] if declared[:path].to_s.empty?
|
|
15
|
+
|
|
16
|
+
override = Assembly.event_tap_override
|
|
17
|
+
source = override ? "variable #{Assembly::EVENT_TAP_VARIABLE}" : "world"
|
|
18
|
+
["event tap", Runtime::EventTap.path_for(declared, override) || "off", source]
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
["event tap", "could not be read", first_line(e.message)]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
# The Hecks world's `event_log` settings, empty when it declares none.
|
|
26
|
+
def declared_event_log(directory)
|
|
27
|
+
world = Hecks.describe(directory).registry.world("Hecks")
|
|
28
|
+
world&.for_verb(Runtime::EventTap::VERB).to_h
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -7,6 +7,7 @@ require_relative "settings_reading/stores"
|
|
|
7
7
|
require_relative "settings_reading/disposable_ledger"
|
|
8
8
|
require_relative "settings_reading/push_nudge"
|
|
9
9
|
require_relative "settings_reading/test_scope"
|
|
10
|
+
require_relative "settings_reading/event_tap_row"
|
|
10
11
|
require_relative "work_limits"
|
|
11
12
|
|
|
12
13
|
module Hecks
|
|
@@ -30,6 +31,7 @@ module Hecks
|
|
|
30
31
|
include DisposableLedger
|
|
31
32
|
include PushNudge
|
|
32
33
|
include TestScope
|
|
34
|
+
include EventTapRow
|
|
33
35
|
|
|
34
36
|
# The first line of a message.
|
|
35
37
|
FIRST_LINE = /\A[^\n]*/
|
|
@@ -62,7 +64,7 @@ module Hecks
|
|
|
62
64
|
schema, project_environment,
|
|
63
65
|
variable_or_default("cache directory", "HECKS_CACHE_DIR", usage_cache_directory),
|
|
64
66
|
variable_or_default("rust workspace", "HECKS_RUST_DIR", RustBuild.rust_dir),
|
|
65
|
-
registry_source(directory), *stores(directory)]
|
|
67
|
+
event_tap(directory), registry_source(directory), *stores(directory)]
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
def line_of(name, value, source) = "#{name}: #{value} (#{source})"
|
|
@@ -207,12 +207,6 @@ Hecks.behaviors "Codebase" do
|
|
|
207
207
|
expect emits: %w[ClearCachesRequested TestSuiteExamined TestSuiteAccepted TestSuiteAnswered TestSuiteCompleted]
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
-
test "RefreshRuntimeBaseline refuses a run that is not a number" do
|
|
211
|
-
tests "RefreshRuntimeBaseline", on: "TestSuiteRun"
|
|
212
|
-
input from_run: { value: "latest" }, run: { value: "baseline" }
|
|
213
|
-
expect refused: "must match"
|
|
214
|
-
end
|
|
215
|
-
|
|
216
210
|
test "RegenerateLegacyFixtures reports what it would rewrite, and rewrites nothing, without confirm" do
|
|
217
211
|
tests "RegenerateLegacyFixtures", on: "TestSuiteRun"
|
|
218
212
|
input run: { value: "fixtures" }
|
|
@@ -66,7 +66,7 @@ Hecks.behaviors "Custodian" do
|
|
|
66
66
|
test "Board keeps a checkout that is not there as a faulted push" do
|
|
67
67
|
tests "Board", on: "SendTrain"
|
|
68
68
|
input run: { value: "evening" }, checkout: { value: "/tmp/hecks-behaviors-absent/checkout" }, confirm: { value: true }
|
|
69
|
-
expect emits: %w[BoardingRequested TrainRefused PushFaulted]
|
|
69
|
+
expect emits: %w[BoardingRequested TrainRefused PushFaulted OutcomeUnrecorded]
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
test "Land keeps a checkout that is not there as a refused landing" do
|
|
@@ -101,6 +101,27 @@ Hecks.behaviors "Custodian" do
|
|
|
101
101
|
expect emits: %w[RetirementRequested RemovalRefused RetirementDeclined]
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
test "Discard keeps a checkout that is not there as a spared worktree" do
|
|
105
|
+
tests "Discard", on: "Landing"
|
|
106
|
+
input run: { value: "evening" }, checkout: { value: "/tmp/hecks-behaviors-absent/checkout" },
|
|
107
|
+
reason: { value: "superseded" }, confirm: { value: true }
|
|
108
|
+
expect emits: %w[DiscardRequested DiscardRefused DiscardDeclined]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
test "Discard needs confirm" do
|
|
112
|
+
tests "Discard", on: "Landing"
|
|
113
|
+
input run: { value: "evening" }, checkout: { value: "/tmp/hecks-behaviors-absent/checkout" },
|
|
114
|
+
reason: { value: "superseded" }
|
|
115
|
+
expect refused: "discards the branch's commits that main lacks needs --confirm; without it this only reports"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
test "Discard needs a reason" do
|
|
119
|
+
tests "Discard", on: "Landing"
|
|
120
|
+
input run: { value: "evening" }, checkout: { value: "/tmp/hecks-behaviors-absent/checkout" },
|
|
121
|
+
reason: { value: "" }, confirm: { value: true }
|
|
122
|
+
expect refused: "a discard says why"
|
|
123
|
+
end
|
|
124
|
+
|
|
104
125
|
test "Dispatch keeps a directory that is not there as a declined run" do
|
|
105
126
|
tests "Dispatch", on: "AgentRun"
|
|
106
127
|
input run: { value: "evening" }, repo: { value: "/tmp/hecks-behaviors-absent/repo" }, brief: { value: "say ok" }
|
|
@@ -7,9 +7,10 @@ Hecks.bluebook "Hecks" do
|
|
|
7
7
|
# the givens and reactions below.
|
|
8
8
|
#
|
|
9
9
|
# The bluebook decides everything: a brief must say something, an agent name cannot be mistaken
|
|
10
|
-
# for a flag, the directory must be one the `Agents` port finds
|
|
11
|
-
# `done` or `
|
|
12
|
-
# starts: it finds
|
|
10
|
+
# for a flag, the directory must be one the `Agents` port finds and the agent one it lists, and a
|
|
11
|
+
# job that reports `done`, `stopped` or `failed` has ended while `working` and `blocked` have
|
|
12
|
+
# not. The port only looks and starts: it finds the directory and the agents, starts the
|
|
13
|
+
# session, and reports the state its job is in.
|
|
13
14
|
|
|
14
15
|
aggregate "AgentRun" do
|
|
15
16
|
description "One brief handed to a background Claude session: started and tracked, or refused with the reason."
|
|
@@ -22,6 +23,7 @@ Hecks.bluebook "Hecks" do
|
|
|
22
23
|
attribute :condition, Condition, optional: true
|
|
23
24
|
attribute :refusal, Report, optional: true
|
|
24
25
|
attribute :tidied_at, Moment, optional: true
|
|
26
|
+
attribute :detail, Report, optional: true
|
|
25
27
|
identified_by :run
|
|
26
28
|
|
|
27
29
|
value_object "RunKey" do
|
|
@@ -61,11 +63,18 @@ Hecks.bluebook "Hecks" do
|
|
|
61
63
|
attribute :value, String
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
# The directory a session works in, written with its trailing slash, so a watch that filters
|
|
67
|
+
# on a checkout's directory matches the checkout and every worktree under it.
|
|
68
|
+
value_object "Checkout" do
|
|
69
|
+
attribute :value, String
|
|
70
|
+
end
|
|
71
|
+
|
|
64
72
|
lifecycle :status, default: "requested" do
|
|
65
73
|
mark :failure, "refused"
|
|
66
74
|
transition "Begin" => "started", from: "requested"
|
|
67
75
|
transition "Decline" => "refused", from: "requested"
|
|
68
76
|
transition "Finish" => "finished", from: "started"
|
|
77
|
+
transition "Fail" => "finished", from: "started"
|
|
69
78
|
transition "Tidied" => "tidied", from: "finished"
|
|
70
79
|
mark :terminal, "tidied", "refused"
|
|
71
80
|
end
|
|
@@ -107,24 +116,63 @@ Hecks.bluebook "Hecks" do
|
|
|
107
116
|
emits AgentRunDeclined
|
|
108
117
|
end
|
|
109
118
|
|
|
119
|
+
# A check reads the job's own state and records a change as one of the four session events
|
|
120
|
+
# below; a state that did not change records nothing.
|
|
110
121
|
command "Check", from: "started" do
|
|
111
122
|
role "Operator"
|
|
112
|
-
goal "
|
|
123
|
+
goal "Read the state a started session's job is in, and record it when it changed"
|
|
113
124
|
|
|
114
125
|
reference_to AgentRun
|
|
115
126
|
|
|
116
127
|
emits AgentCheckRequested
|
|
117
128
|
end
|
|
118
129
|
|
|
130
|
+
command "Work", from: "started" do
|
|
131
|
+
role "System"
|
|
132
|
+
goal "Record that the session is working"
|
|
133
|
+
|
|
134
|
+
reference_to AgentRun
|
|
135
|
+
attribute :condition, Condition, sets: true
|
|
136
|
+
attribute :checkout, Checkout
|
|
137
|
+
|
|
138
|
+
emits SessionWorking
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
command "Block", from: "started" do
|
|
142
|
+
role "System"
|
|
143
|
+
goal "Record that the session waits on a person, and the question it waits on"
|
|
144
|
+
|
|
145
|
+
reference_to AgentRun
|
|
146
|
+
attribute :condition, Condition, sets: true
|
|
147
|
+
attribute :detail, Report, sets: true
|
|
148
|
+
attribute :checkout, Checkout
|
|
149
|
+
|
|
150
|
+
emits SessionBlocked
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# `done` and `stopped` are a session's two ways of ending well; `failed` is `Fail`.
|
|
119
154
|
command "Finish" do
|
|
120
155
|
role "System"
|
|
121
156
|
goal "Record that the session has ended, and how it ended"
|
|
122
157
|
|
|
123
158
|
reference_to AgentRun
|
|
124
159
|
attribute :condition, Condition, sets: true
|
|
160
|
+
attribute :detail, Report, sets: true
|
|
161
|
+
attribute :checkout, Checkout
|
|
125
162
|
|
|
163
|
+
emits SessionFinished
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
command "Fail" do
|
|
167
|
+
role "System"
|
|
168
|
+
goal "Record that the session failed, and what it said"
|
|
126
169
|
|
|
127
|
-
|
|
170
|
+
reference_to AgentRun
|
|
171
|
+
attribute :condition, Condition, sets: true
|
|
172
|
+
attribute :detail, Report, sets: true
|
|
173
|
+
attribute :checkout, Checkout
|
|
174
|
+
|
|
175
|
+
emits SessionFailed
|
|
128
176
|
end
|
|
129
177
|
|
|
130
178
|
# A finished run's session is removed only when it ended `done`; a session still `working`,
|
|
@@ -181,6 +229,28 @@ Hecks.bluebook "Hecks" do
|
|
|
181
229
|
end
|
|
182
230
|
end
|
|
183
231
|
|
|
232
|
+
# One check of every run still started, for a driver that watches sessions. The launcher also
|
|
233
|
+
# answers it as `agent_run.check_all!`.
|
|
234
|
+
aggregate "SessionSweep" do
|
|
235
|
+
description "One check of every started run's session: each change of state is recorded on its run."
|
|
236
|
+
|
|
237
|
+
attribute :run, SweepKey
|
|
238
|
+
identified_by :run
|
|
239
|
+
|
|
240
|
+
value_object "SweepKey" do
|
|
241
|
+
attribute :value, String, matches: :present
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
command "CheckAll" do
|
|
245
|
+
role "Operator"
|
|
246
|
+
goal "Check every run whose session was started and is not known to have ended"
|
|
247
|
+
|
|
248
|
+
attribute :run, SweepKey, sets: true
|
|
249
|
+
|
|
250
|
+
emits SweepRequested
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
184
254
|
# Filling the Work queue is one run too: the Work rows that may start a session now are chosen
|
|
185
255
|
# from the queue, the machine's load and the freeze, and without `confirm` that is all it does.
|
|
186
256
|
# The choosing and the starting are the port's; whether a start is allowed stays with `Work`.
|
|
@@ -292,16 +362,33 @@ Hecks.bluebook "Hecks" do
|
|
|
292
362
|
ask :locate, with: { run: :run }
|
|
293
363
|
end
|
|
294
364
|
|
|
295
|
-
|
|
365
|
+
# Locating the directory also says whether its `claude` lists the named agent, so a name it
|
|
366
|
+
# does not know is refused before a session is started; with no agent named, the session runs
|
|
367
|
+
# `claude`'s default. One look, not two: the reactions after a start stay within the depth limit.
|
|
368
|
+
policy "StartWhenTheAgentIsListed" do
|
|
296
369
|
on "AgentRun.RepoLocated"
|
|
370
|
+
where { listed != false }
|
|
297
371
|
ask :start, with: { run: :run }
|
|
298
372
|
end
|
|
299
373
|
|
|
374
|
+
policy "RecordTheUnlistedAgent" do
|
|
375
|
+
on "AgentRun.RepoLocated"
|
|
376
|
+
where { listed == false }
|
|
377
|
+
trigger AgentRun::Decline, with: { refusal: :note }
|
|
378
|
+
end
|
|
379
|
+
|
|
300
380
|
policy "RecordTheSession" do
|
|
301
381
|
on "AgentRun.AgentStarted"
|
|
302
382
|
trigger AgentRun::Begin, with: { session: :session }
|
|
303
383
|
end
|
|
304
384
|
|
|
385
|
+
# A session can die within seconds of its start (an agent that fails to load). Its job is read
|
|
386
|
+
# once the port has let it settle, so a dead session is recorded failed, never left started.
|
|
387
|
+
policy "ReadTheNewSession" do
|
|
388
|
+
on "AgentRun.AgentRunStarted"
|
|
389
|
+
ask :await_job, with: { run: :run }
|
|
390
|
+
end
|
|
391
|
+
|
|
305
392
|
policy "RecordTheMissingRepo" do
|
|
306
393
|
on "AgentRun.RepoMissing"
|
|
307
394
|
trigger AgentRun::Decline, with: { refusal: :refusal }
|
|
@@ -312,9 +399,42 @@ Hecks.bluebook "Hecks" do
|
|
|
312
399
|
trigger AgentRun::Decline, with: { refusal: :refusal }
|
|
313
400
|
end
|
|
314
401
|
|
|
315
|
-
policy "
|
|
402
|
+
policy "ReadTheJob" do
|
|
316
403
|
on "AgentRun.AgentCheckRequested"
|
|
317
|
-
ask :
|
|
404
|
+
ask :read_job, with: { run: :run }
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
# Each check is addressed by the row's key alone: the sweep's own `run` is not passed on.
|
|
408
|
+
policy "CheckEveryStartedRun" do
|
|
409
|
+
on "SessionSweep.SweepRequested"
|
|
410
|
+
for_each "AgentRun.Running"
|
|
411
|
+
trigger AgentRun::Check, with: { agent_run: :agent_run }
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# A job's state becomes an event only when it differs from the state the run last recorded
|
|
415
|
+
# (`previous`), so a check that finds nothing new records nothing.
|
|
416
|
+
policy "RecordTheWorkingSession" do
|
|
417
|
+
on "AgentRun.JobRead"
|
|
418
|
+
where { state == "working" && previous != state }
|
|
419
|
+
trigger AgentRun::Work, with: { condition: :state, checkout: :checkout }
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
policy "RecordTheBlockedSession" do
|
|
423
|
+
on "AgentRun.JobRead"
|
|
424
|
+
where { state == "blocked" && previous != state }
|
|
425
|
+
trigger AgentRun::Block, with: { condition: :state, detail: :detail, checkout: :checkout }
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
policy "RecordTheEndedSession" do
|
|
429
|
+
on "AgentRun.JobRead"
|
|
430
|
+
where { (state == "done" || state == "stopped") && previous != state }
|
|
431
|
+
trigger AgentRun::Finish, with: { condition: :state, detail: :detail, checkout: :checkout }
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
policy "RecordTheFailedSession" do
|
|
435
|
+
on "AgentRun.JobRead"
|
|
436
|
+
where { state == "failed" && previous != state }
|
|
437
|
+
trigger AgentRun::Fail, with: { condition: :state, detail: :detail, checkout: :checkout }
|
|
318
438
|
end
|
|
319
439
|
|
|
320
440
|
# The session is looked at before it is removed; the port says whether a person took it over.
|
|
@@ -344,12 +464,5 @@ Hecks.bluebook "Hecks" do
|
|
|
344
464
|
on "AgentRun.RemoveRefused"
|
|
345
465
|
trigger AgentRun::Retain, with: { refusal: :refusal }
|
|
346
466
|
end
|
|
347
|
-
|
|
348
|
-
# `done` and `stopped` are a session's two ways of ending; `busy` and `idle` are not.
|
|
349
|
-
policy "FinishWhenTheSessionEnded" do
|
|
350
|
-
on "AgentRun.SessionChecked"
|
|
351
|
-
where { condition == "done" || condition == "stopped" }
|
|
352
|
-
trigger AgentRun::Finish, with: { condition: :condition }
|
|
353
|
-
end
|
|
354
467
|
end
|
|
355
468
|
end
|