hecks 3.2.0 → 3.3.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/bluebook/assembly/contracts.rb +2 -1
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +2 -39
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -3
- data/lib/hecks/bluebook/dsl/need_word.rb +50 -0
- data/lib/hecks/bluebook/dsl/query_builder.rb +6 -1
- data/lib/hecks/bluebook/query.rb +8 -5
- data/lib/hecks/cli/check_era.rb +3 -39
- data/lib/hecks/cli/interview_draft.rb +86 -31
- data/lib/hecks/cli/interview_session.rb +77 -26
- data/lib/hecks/cli/interview_shape.rb +179 -0
- data/lib/hecks/doors/cli_runner.rb +14 -1
- data/lib/hecks/doors/launcher_options.rb +13 -3
- data/lib/hecks/doors/mcp_door.rb +16 -2
- data/lib/hecks/doors/mcp_door_scope.rb +45 -5
- data/lib/hecks/doors/mcp_guide_cache.rb +75 -0
- data/lib/hecks/doors.rb +1 -1
- data/lib/hecks/embryonaut_bluebook/manifest.rb +117 -0
- data/lib/hecks/embryonaut_bluebook/registry.rb +209 -0
- data/lib/hecks/embryonaut_bluebook/vendor.rb +1 -1
- data/lib/hecks/embryonaut_bluebook.rb +2 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +17 -1
- data/lib/hecks/fuzzing/qa_settings.rb +15 -34
- data/lib/hecks/gate/stages.yml +113 -8
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +10 -1
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +10 -2
- data/lib/hecks/hecks/adapters/first_admin.rb +108 -0
- data/lib/hecks/hecks/adapters/git.rb +59 -0
- data/lib/hecks/hecks/adapters/in_process_access.rb +25 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +2 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +18 -3
- data/lib/hecks/hecks/adapters/rust_workspace.rb +1 -1
- data/lib/hecks/hecks/adapters/site_toolchain.rb +88 -11
- data/lib/hecks/hecks/codebase.behaviors +6 -0
- data/lib/hecks/hecks/codebase.bluebook +21 -0
- data/lib/hecks/hecks/custodian.behaviors +6 -0
- data/lib/hecks/hecks/custodian.bluebook +217 -0
- data/lib/hecks/hecks/hecks.hecksagon +24 -0
- data/lib/hecks/hecks/hecks.world +8 -3
- data/lib/hecks/hecks/site.world +5 -2
- data/lib/hecks/language/bluebook/query.bluebook +25 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +220 -7
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +1 -1
- data/lib/hecks/language/oidc.json +5 -0
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -3
- data/lib/hecks/projections/deploy/box/hosting.rb +170 -0
- data/lib/hecks/projections/deploy/box/hosting_settings.rb +123 -0
- data/lib/hecks/projections/deploy/box/settings.rb +40 -6
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +2 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +33 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +79 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +77 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef.part +12 -0
- data/lib/hecks/projections/deploy/box/templates/hosting.mk.tmpl +24 -0
- data/lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl +17 -0
- data/lib/hecks/projections/deploy/box/templates/smoke-after-deploy.sh.tmpl +271 -0
- data/lib/hecks/projections/deploy/box.rb +28 -4
- data/lib/hecks/projections/deploy/fargate.rb +3 -3
- data/lib/hecks/projections/deploy/lambda.rb +8 -8
- data/lib/hecks/projections/model/deviations.rb +1 -1
- data/lib/hecks/projections/site/edge/behaviours.rb +5 -3
- data/lib/hecks/projections/site/edge/checks.rb +31 -5
- data/lib/hecks/projections/site/edge.rb +25 -11
- data/lib/hecks/projections/site/live_edge.rb +162 -0
- data/lib/hecks/projections/site/routes_ts.rb +50 -27
- data/lib/hecks/projections/site/site_cdn.rb +7 -4
- data/lib/hecks/projections/site/table/checks.rb +53 -7
- data/lib/hecks/projections/site/table/link_builder.rb +64 -0
- data/lib/hecks/projections/site/table/row_builder.rb +21 -6
- data/lib/hecks/projections/site/table.rb +16 -5
- data/lib/hecks/quality_control/adapters/git_pr.rb +0 -14
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +32 -16
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +1 -2
- data/lib/hecks/quality_control/quality_control.bluebook +76 -124
- data/lib/hecks/runtime/interpreting.rb +3 -22
- data/lib/hecks/runtime/needs.rb +48 -0
- data/lib/hecks/runtime/query_interpreter.rb +3 -0
- data/lib/hecks/runtime/registry/verification.rb +3 -3
- data/lib/hecks/rust_build/host.rb +147 -0
- data/lib/hecks/rust_build/kernel_input.rb +51 -17
- data/lib/hecks/rust_build/project_rust/codegen_run.rb +0 -18
- data/lib/hecks/rust_build/project_rust.rb +7 -140
- data/lib/hecks/rust_build.rb +1 -0
- data/lib/hecks/site/bluebook/site.bluebook +80 -14
- data/lib/hecks/site/bluebook/site.ports.hecksagon +6 -0
- data/lib/hecks/sme/bluebook/sme.bluebook +128 -1
- data/lib/hecks/storehouse.rb +35 -1
- data/lib/hecks/tools/comment_style.rb +4 -2
- data/lib/hecks/tools/gate.rb +1 -1
- data/lib/hecks/tools/rust_comment_style.rb +2 -4
- data/lib/hecks/tools/site_routes.rb +69 -28
- data/lib/hecks/tools/tools_doc.rb +204 -0
- data/lib/hecks/tools.rb +1 -0
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +152 -1
- data/lib/hecks.rb +1 -0
- data/qa/settings.yml +1 -2
- data/rust/build/src/lineage_pass.rs +31 -16
- data/rust/build/src/main.rs +4 -2
- data/rust/build/src/pipeline.rs +9 -20
- data/rust/codegen/src/attr.rs +1 -1
- data/rust/codegen/src/bridging.rs +8 -8
- data/rust/codegen/src/commands.rs +1 -1
- data/rust/codegen/src/constraints.rs +1 -1
- data/rust/codegen/src/dependency_planning.rs +1 -1
- data/rust/codegen/src/domain_generator.rs +2 -2
- data/rust/codegen/src/exemplar.rs +1 -1
- data/rust/codegen/src/expr_emitter.rs +1 -1
- data/rust/codegen/src/fielded.rs +1 -1
- data/rust/codegen/src/json.rs +214 -23
- data/rust/codegen/src/json_codec.rs +1 -1
- data/rust/codegen/src/literal.rs +6 -3
- data/rust/codegen/src/main.rs +23 -13
- data/rust/codegen/src/mutations.rs +1 -1
- data/rust/codegen/src/naming.rs +5 -3
- data/rust/codegen/src/optional_pass.rs +226 -0
- data/rust/codegen/src/ports.rs +1 -1
- data/rust/codegen/src/queries.rs +3 -3
- data/rust/codegen/src/reactions.rs +1 -1
- data/rust/codegen/src/read_models.rs +2 -2
- data/rust/codegen/src/reference_specs.rs +1 -1
- data/rust/codegen/src/registry.rs +4 -4
- data/rust/codegen/src/shared.rs +1 -1
- data/rust/{build → codegen}/src/sidecars.rs +9 -5
- data/rust/codegen/src/skip_reason.rs +1 -1
- data/rust/codegen/src/types.rs +4 -4
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/api.rs +1 -1
- data/rust/host/src/dispatch.rs +5 -0
- data/rust/host/src/needs.rs +193 -29
- data/rust/host/src/resend.rs +4 -4
- data/rust/host/src/ui_schema.rs +1 -1
- data/rust/parser/src/emit.rs +12 -0
- data/rust/parser/src/ir.rs +2 -0
- data/rust/parser/src/keywords.rs +2 -0
- data/rust/parser/src/main.rs +1 -0
- data/rust/parser/src/parse/command.rs +2 -44
- data/rust/parser/src/parse/mod.rs +1 -0
- data/rust/parser/src/parse/needs.rs +60 -0
- data/rust/parser/src/parse/query.rs +3 -0
- data/rust/src/exemplar/commands.rs +1 -1
- data/rust/src/exemplar/constraints.rs +1 -1
- data/rust/src/exemplar/fielded.rs +1 -1
- data/rust/src/exemplar/json.rs +1 -1
- data/rust/src/exemplar/mod.rs +1 -1
- data/rust/src/exemplar/mutations.rs +1 -1
- data/rust/src/exemplar/queries.rs +1 -1
- data/rust/src/exemplar/reactions.rs +1 -1
- data/rust/src/exemplar/read_models.rs +1 -1
- data/rust/src/exemplar/registry.rs +1 -1
- data/rust/src/exemplar/types.rs +1 -1
- data/rust/src/kernel/cli.rs +18 -8
- data/rust/src/kernel/needs.rs +104 -9
- data/rust/src/kernel/read_model.rs +1 -1
- data/rust/src/lib.rs +1 -1
- metadata +24 -30
- data/lib/hecks/rust_build/append_optionals.rb +0 -79
- data/lib/hecks/rust_build/rust_literal.rb +0 -33
- data/lib/hecks/three_zero/forms.yml +0 -127
- data/lib/hecks/three_zero.rb +0 -12
- data/rust/build/src/json.rs +0 -421
- data/rust/build/src/optional_pass.rs +0 -150
- data/rust/project/bridging.rb +0 -257
- data/rust/project/commands.rb +0 -877
- data/rust/project/constraints.rb +0 -86
- data/rust/project/dependency_planning.rb +0 -178
- data/rust/project/domain_generator.rb +0 -983
- data/rust/project/exemplar.rb +0 -148
- data/rust/project/expr_emitter.rb +0 -72
- data/rust/project/fielded.rb +0 -141
- data/rust/project/json_codec.rb +0 -641
- data/rust/project/mutations.rb +0 -695
- data/rust/project/naming.rb +0 -223
- data/rust/project/ports.rb +0 -65
- data/rust/project/queries.rb +0 -493
- data/rust/project/reactions.rb +0 -317
- data/rust/project/read_models.rb +0 -690
- data/rust/project/reference_specs.rb +0 -27
- data/rust/project/registry.rb +0 -396
- data/rust/project/skip_reason.rb +0 -29
- data/rust/project/types.rb +0 -225
- data/rust/project/write_if_changed.rb +0 -7
- data/rust/project.rb +0 -30
- data/rust/project_rust_pipeline.rb +0 -391
|
@@ -30,7 +30,7 @@ module Hecks
|
|
|
30
30
|
DOC_LINE = %r{\A\s*(?:///(?!/)|//!)}
|
|
31
31
|
|
|
32
32
|
# `// TMPL:name BEGIN`/`END` sentinels are parsed verbatim by
|
|
33
|
-
# `rust/
|
|
33
|
+
# `rust/codegen/src/exemplar.rs`; every prose rule skips them outright.
|
|
34
34
|
TMPL_MARKER = /\bTMPL:\S+\s+(?:BEGIN|END)\b/i
|
|
35
35
|
MOD_DOC_LINE = %r{\A\s*//!}
|
|
36
36
|
ATTR_LINE = /\A\s*#\[/
|
|
@@ -45,9 +45,7 @@ module Hecks
|
|
|
45
45
|
# Rust-specific acronyms beyond the Ruby linter's list.
|
|
46
46
|
RUST_ACRONYMS = %w[EOF RAII RHS SQS DLQ JIT LSP NFA DFA CR].to_set.freeze
|
|
47
47
|
|
|
48
|
-
RUST_PROPER_NOUNS = {
|
|
49
|
-
"EMBRYONAUT" => "Embryonaut"
|
|
50
|
-
}.freeze
|
|
48
|
+
RUST_PROPER_NOUNS = {}.freeze
|
|
51
49
|
|
|
52
50
|
RUST_EXTRA_WORDS = %w[
|
|
53
51
|
cardinality routability prepend safer diff diffed stats earliest unbracketed
|
|
@@ -14,41 +14,47 @@ module Hecks
|
|
|
14
14
|
# it declares an edge, into the behaviours and listener rules of its template
|
|
15
15
|
# (`Projections::Site::SiteCdn`).
|
|
16
16
|
#
|
|
17
|
-
# hecks site site_projection.project_site [<project>] [--out=<dir>] [--
|
|
17
|
+
# hecks site site_projection.project_site [<project>] [--out=<dir>] [--template=<file>]
|
|
18
|
+
# [--extension=ts|mts] [--check]
|
|
18
19
|
#
|
|
19
|
-
# `<project>`
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
# names each file that differs from the table.
|
|
20
|
+
# `<project>` (default: the working directory) holds `bluebook/` and the `vendor/` it attaches
|
|
21
|
+
# from. `routes.ts` goes to `<project>/generated` or to `--out`, anywhere. The template is the
|
|
22
|
+
# `Edge` row's, relative to the project, or `--template`, anywhere; it is rewritten in place
|
|
23
|
+
# between its `BEGIN`/`END GENERATED site_cdn` markers. With `--out` alone, `--out` receives a
|
|
24
|
+
# copy of it instead. `--extension=mts` names the module `routes.mts`; `--check` writes nothing.
|
|
25
25
|
module SiteRoutes
|
|
26
26
|
# Where the files go, relative to the project, when `--out` names no directory.
|
|
27
27
|
DEFAULT_OUT = "generated"
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# The extensions the module may take; the first is the default.
|
|
30
|
+
EXTENSIONS = %w[ts mts].freeze
|
|
31
|
+
|
|
32
|
+
USAGE = "usage: hecks site site_projection.project_site [<project>] [--out=<dir>] " \
|
|
33
|
+
"[--template=<file>] [--extension=#{EXTENSIONS.join('|')}] [--check]".freeze
|
|
30
34
|
|
|
31
35
|
module_function
|
|
32
36
|
|
|
33
37
|
# Projects the route table, writes what differs and prints a line for each file written.
|
|
34
38
|
#
|
|
35
39
|
# @param argv [Array<String>] the project directory, then the flags
|
|
36
|
-
# @param root [String] the
|
|
40
|
+
# @param root [String] the project used when `argv` names none; the working directory
|
|
37
41
|
# @return [Integer] 0, or 1 when `--check` finds a file out of date
|
|
38
|
-
# @raise [SystemExit] with the reason on stderr when the project declares no route table
|
|
39
|
-
#
|
|
40
|
-
def main(argv, root:
|
|
42
|
+
# @raise [SystemExit] with the reason on stderr when the project declares no route table, the
|
|
43
|
+
# table is refused, or a flag is refused
|
|
44
|
+
def main(argv, root: Dir.pwd)
|
|
41
45
|
argv = argv.dup
|
|
42
|
-
out = nil
|
|
46
|
+
out = template = extension = nil
|
|
43
47
|
check = false
|
|
44
48
|
OptionParser.new do |parser|
|
|
45
49
|
parser.on("--out=DIR") { |value| out = value }
|
|
50
|
+
parser.on("--template=FILE") { |value| template = value }
|
|
51
|
+
parser.on("--extension=EXT") { |value| extension = value }
|
|
46
52
|
parser.on("--check") { check = true }
|
|
47
53
|
end.parse!(argv)
|
|
48
54
|
project = argv.empty? ? root : File.expand_path(argv.shift)
|
|
49
55
|
abort USAGE unless argv.empty?
|
|
50
56
|
|
|
51
|
-
files = projection(project, out: out)
|
|
57
|
+
files = projection(project, out: out, template: template, extension: extension)
|
|
52
58
|
stale = files.reject { |path, text| File.file?(path) && File.read(path) == text }.keys
|
|
53
59
|
return report(stale, project, check) if check
|
|
54
60
|
|
|
@@ -63,16 +69,26 @@ module Hecks
|
|
|
63
69
|
|
|
64
70
|
# @param root [String] the project directory
|
|
65
71
|
# @param out [String, nil] the directory to write to; `generated/` of the project when nil
|
|
72
|
+
# @param template [String, nil] the template to rewrite in place, wherever it lies; the
|
|
73
|
+
# `Edge` row's template, relative to the project, when nil
|
|
74
|
+
# @param extension [String, nil] `ts` (the default) or `mts`, the module's file extension
|
|
66
75
|
# @return [Hash{String => String}] each file's absolute path to the text it should hold
|
|
67
|
-
# @raise [SystemExit] when the project declares no route table
|
|
68
|
-
|
|
76
|
+
# @raise [SystemExit] when the project declares no route table, the table is refused, or a
|
|
77
|
+
# path or the extension is refused
|
|
78
|
+
def projection(root, out: nil, template: nil, extension: nil)
|
|
79
|
+
extension ||= EXTENSIONS.first
|
|
80
|
+
unless EXTENSIONS.include?(extension)
|
|
81
|
+
abort "project_site: --extension is one of #{EXTENSIONS.join(', ')}, not #{extension.inspect}"
|
|
82
|
+
end
|
|
83
|
+
dir = out ? File.expand_path(out) : File.join(root, DEFAULT_OUT)
|
|
84
|
+
abort "project_site: --out #{dir} is a file; it names the directory routes.#{extension} goes in" if File.file?(dir)
|
|
85
|
+
|
|
69
86
|
registry = registry_for(root)
|
|
70
87
|
chapter = Projections::Site::Table.chapter(registry)
|
|
71
88
|
table = Projections::Site::Table.read(chapter, registry: registry)
|
|
72
89
|
files = Projector.call(:site_routes_ts, bluebook: chapter, options: { table: table })
|
|
73
|
-
|
|
74
|
-
written
|
|
75
|
-
written.merge(template_files(root, out, chapter, table, registry))
|
|
90
|
+
written = files.to_h { |name, text| [File.join(dir, name.sub(/\.ts\z/, ".#{extension}")), text] }
|
|
91
|
+
written.merge(template_files(root, out, chapter, table, registry, template: template))
|
|
76
92
|
rescue Projections::Site::Table::Invalid => e
|
|
77
93
|
abort "project_site: #{e.message}"
|
|
78
94
|
end
|
|
@@ -84,25 +100,50 @@ module Hecks
|
|
|
84
100
|
# @param chapter [Bluebook::Chapter] the chapter that declares the route table
|
|
85
101
|
# @param table [Projections::Site::Table] the checked table
|
|
86
102
|
# @param registry [Hecks::Runtime::Registry] the registry the project booted into
|
|
103
|
+
# @param template [String, nil] a template named on the command line, rewritten in place
|
|
87
104
|
# @return [Hash{String => String}] the template's path to its text; empty with no edge
|
|
88
|
-
# @raise [SystemExit] when
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
105
|
+
# @raise [SystemExit] when a template is named and the project declares no edge, the
|
|
106
|
+
# template is missing or lacks a region it needs, or holds a region an edge without a load
|
|
107
|
+
# balancer does not use
|
|
108
|
+
def template_files(root, out, chapter, table, registry, template: nil)
|
|
109
|
+
edge = Projections::Site::Edge.read(chapter, table: table, template: template,
|
|
110
|
+
vocabulary: Projections::Site::Table.vocabulary(registry))
|
|
111
|
+
unless edge
|
|
112
|
+
abort "project_site: --template names #{template}, but the project declares no Edge rows" if template
|
|
113
|
+
return {}
|
|
114
|
+
end
|
|
92
115
|
|
|
93
116
|
regions = Projector.call(:site_cdn, bluebook: chapter, options: { table: table, edge: edge })
|
|
94
|
-
relative = edge.setting.template
|
|
95
|
-
source = File.join(root, relative)
|
|
96
|
-
|
|
117
|
+
relative = template || edge.setting.template
|
|
118
|
+
source = template ? File.expand_path(template) : File.join(root, relative)
|
|
119
|
+
unless File.file?(source)
|
|
120
|
+
abort "project_site: the template #{relative} does not exist#{" in #{root}" unless template}"
|
|
121
|
+
end
|
|
97
122
|
|
|
98
|
-
text =
|
|
123
|
+
text = rewritten(File.read(source), regions, relative, edge)
|
|
124
|
+
in_place = template || out.nil?
|
|
125
|
+
{ (in_place ? source : File.join(File.expand_path(out), relative)) => text }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @param text [String] the template
|
|
129
|
+
# @param regions [Hash{String => String}] each region's name to the block that goes in it
|
|
130
|
+
# @param relative [String] the template's name, for a message
|
|
131
|
+
# @param edge [Projections::Site::Edge] the checked edge
|
|
132
|
+
# @return [String] the template with each region rewritten
|
|
133
|
+
# @raise [SystemExit] when a region is missing, or a listener_rules region is left behind
|
|
134
|
+
# by an edge with no load balancer
|
|
135
|
+
def rewritten(text, regions, relative, edge)
|
|
136
|
+
if !edge.alb? && Projections::Site::Regions.region?(text, "listener_rules")
|
|
137
|
+
abort "project_site: #{relative} has a BEGIN/END GENERATED site_cdn listener_rules region, " \
|
|
138
|
+
"and the Edge row says alb: false; remove the region"
|
|
139
|
+
end
|
|
140
|
+
regions.reduce(text) do |current, (name, block)|
|
|
99
141
|
unless Projections::Site::Regions.region?(current, name)
|
|
100
142
|
abort "project_site: #{relative} has no BEGIN/END GENERATED site_cdn #{name} region"
|
|
101
143
|
end
|
|
102
144
|
|
|
103
145
|
Projections::Site::Regions.replace(current, name, block)
|
|
104
146
|
end
|
|
105
|
-
{ (out ? File.join(File.expand_path(out), relative) : source) => text }
|
|
106
147
|
end
|
|
107
148
|
|
|
108
149
|
# Loads the project's chapters the way a deploy does: the bluebooks, then the hecksagons that
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hecks"
|
|
4
|
+
require "hecks/vocabulary"
|
|
5
|
+
require_relative "../tools"
|
|
6
|
+
|
|
7
|
+
module Hecks
|
|
8
|
+
module Tools
|
|
9
|
+
# Writes the launcher forms of `docs/tools.md` from the `RetiredScript` rows of the Vocabulary
|
|
10
|
+
# chapter. Each row names a command (or, in QualityControl, a query); its form is rendered from
|
|
11
|
+
# that command's own arguments, the same projection the launcher parses against, so a form can
|
|
12
|
+
# neither keep an argument the command dropped nor miss one it gained.
|
|
13
|
+
#
|
|
14
|
+
# Only the tables between the `generated:begin tools` and `generated:end tools` comments are
|
|
15
|
+
# written; the prose around them is hand-written and left alone. With `--check` nothing is
|
|
16
|
+
# written: the tool answers 1 and names the sections that differ from the rows.
|
|
17
|
+
module ToolsDoc
|
|
18
|
+
# The document, relative to the checkout.
|
|
19
|
+
DOCUMENT = "docs/tools.md"
|
|
20
|
+
|
|
21
|
+
# The sections of the document, in the order it lists them.
|
|
22
|
+
SECTIONS = %w[Custodian Deploy Site Codebase QualityControl].freeze
|
|
23
|
+
|
|
24
|
+
# The first line of a table, and the line that closes it.
|
|
25
|
+
HEADER = "| launcher | replaces |\n|---|---|"
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# @param argv [Array<String>] `--check` to compare without writing
|
|
30
|
+
# @param root [String] the checkout
|
|
31
|
+
# @return [Integer] 0, or 1 when `--check` finds a section out of date
|
|
32
|
+
# @raise [SystemExit] when a section has no marked table
|
|
33
|
+
def main(argv, root: Tools::ROOT)
|
|
34
|
+
path = File.join(root, DOCUMENT)
|
|
35
|
+
text = File.read(path, encoding: "UTF-8")
|
|
36
|
+
fresh = projection(text, root)
|
|
37
|
+
return report(text, fresh) if argv.include?("--check")
|
|
38
|
+
|
|
39
|
+
File.write(path, fresh, encoding: "UTF-8") unless fresh == text
|
|
40
|
+
puts(fresh == text ? "tools_doc: #{rows.size} rows, every table current" : "wrote #{DOCUMENT}")
|
|
41
|
+
0
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Array<Hash{String => String}>] the `RetiredScript` rows, in table order
|
|
45
|
+
def rows = Hecks::Vocabulary.rows("RetiredScript")
|
|
46
|
+
|
|
47
|
+
# The launcher form each retired script became, as the table lists it.
|
|
48
|
+
#
|
|
49
|
+
# @param root [String] the checkout
|
|
50
|
+
# @return [Hash{String => String}] script name to its forms, joined with `; `; a command no
|
|
51
|
+
# script preceded (`(new)`) has none
|
|
52
|
+
def forms(root: Tools::ROOT)
|
|
53
|
+
@forms ||= {}
|
|
54
|
+
@forms[root] ||= begin
|
|
55
|
+
context = Context.new(root)
|
|
56
|
+
rows.reject { |row| row["script"] == "(new)" }.group_by { |row| row["script"] }
|
|
57
|
+
.transform_values { |group| group.map { |row| form(row, context) }.join("; ") }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @param text [String] the document as it stands
|
|
62
|
+
# @param root [String] the checkout
|
|
63
|
+
# @return [String] the document with each section's table rewritten from the rows
|
|
64
|
+
# @raise [SystemExit] when a section has no marked table
|
|
65
|
+
def projection(text, root)
|
|
66
|
+
context = Context.new(root)
|
|
67
|
+
SECTIONS.reduce(text) do |held, section|
|
|
68
|
+
region = /(<!-- generated:begin tools section=#{section} -->\n).*?(<!-- generated:end tools -->)/m
|
|
69
|
+
abort "tools_doc: #{DOCUMENT} has no marked table for #{section}" unless held.match?(region)
|
|
70
|
+
|
|
71
|
+
held.sub(region) { "#{Regexp.last_match(1)}#{table(section, context)}\n#{Regexp.last_match(2)}" }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @param section [String] one of `SECTIONS`
|
|
76
|
+
# @param context [Context] the booted chapters
|
|
77
|
+
# @return [String] the section's table, header included
|
|
78
|
+
def table(section, context)
|
|
79
|
+
lines = rows.select { |row| row["section"] == section }.group_by { |row| row["script"] }.map do |script, group|
|
|
80
|
+
cell = group.map { |row| cell(row, context) }.join("; ")
|
|
81
|
+
"| #{cell} | #{script == '(new)' ? '(new: no `bin/` script)' : "`bin/#{script}`"} |"
|
|
82
|
+
end
|
|
83
|
+
[HEADER, *lines].join("\n")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# One form as the table shows it: in backticks, with a `|` escaped.
|
|
87
|
+
def cell(row, context) = "`#{form(row, context).gsub('|', '\|')}`"
|
|
88
|
+
|
|
89
|
+
# @param row [Hash{String => String}] a `RetiredScript` row
|
|
90
|
+
# @param context [Context] the booted chapters
|
|
91
|
+
# @return [String] the launcher form of the row's command or query
|
|
92
|
+
def form(row, context)
|
|
93
|
+
return row["form"] unless row["form"].to_s.empty?
|
|
94
|
+
|
|
95
|
+
spec, words = context.spec_for(row)
|
|
96
|
+
passes = row["passes"].to_s
|
|
97
|
+
text = [*words, *argument_words(spec, skip: passes.empty? ? [] : %w[arguments])].join(" ")
|
|
98
|
+
text += %( [arguments="#{passes}"]) unless passes.empty?
|
|
99
|
+
text += " (#{row['note']})" unless row["note"].to_s.empty?
|
|
100
|
+
"hecks #{text}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The words after the verb: the first argument bare, the rest `name=`, flags last.
|
|
104
|
+
#
|
|
105
|
+
# @param spec [Hash] a projected command or query
|
|
106
|
+
# @param skip [Array<String>] arguments not to spell, because the row documents them itself
|
|
107
|
+
# @return [Array<String>] each argument as the launcher spells it
|
|
108
|
+
def argument_words(spec, skip: [])
|
|
109
|
+
named = by_attribute(spec[:arguments].reject do |argument|
|
|
110
|
+
argument[:minted] || skip.include?(argument[:path].split(".").first)
|
|
111
|
+
end)
|
|
112
|
+
# The launcher reads a bare word as the first argument, when that is not a flag.
|
|
113
|
+
bare = named.first unless named.empty? || named.first[:type] == "Boolean"
|
|
114
|
+
flags, plain = (named - [bare].compact).partition { |argument| argument[:type] == "Boolean" }
|
|
115
|
+
[*(bracket(bare, "<#{bare[:path]}>") if bare),
|
|
116
|
+
*plain.map { |argument| bracket(argument, "#{argument[:path]}=") },
|
|
117
|
+
*flags.map { |argument| flag_word(argument) }]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# A one-field value object's `x.value` leaf is spelled as the attribute, `x`; a value object
|
|
121
|
+
# with more fields keeps one leaf each.
|
|
122
|
+
#
|
|
123
|
+
# @param leaves [Array<Hash>] projected leaf arguments
|
|
124
|
+
# @return [Array<Hash>] the arguments the launcher takes, one per attribute for a scalar
|
|
125
|
+
def by_attribute(leaves)
|
|
126
|
+
leaves.group_by { |argument| argument[:path].split(".").first }.flat_map do |head, group|
|
|
127
|
+
group.size == 1 && group.first[:path].end_with?(".value") ? [group.first.merge(path: head)] : group
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @param argument [Hash] a projected argument
|
|
132
|
+
# @param word [String] how it is spelled
|
|
133
|
+
# @return [String] `word`, in brackets when the argument is optional
|
|
134
|
+
def bracket(argument, word) = argument[:required] ? word : "[#{word}]"
|
|
135
|
+
|
|
136
|
+
# `--confirm` is what makes a verb act, so it stands bare; any other flag is optional.
|
|
137
|
+
def flag_word(argument)
|
|
138
|
+
word = "--#{argument[:path].tr('_', '-')}"
|
|
139
|
+
argument[:path] == "confirm" ? word : "[#{word}]"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @param text [String] the document as it stands
|
|
143
|
+
# @param fresh [String] the document the rows give
|
|
144
|
+
# @return [Integer] 0 when current, else 1 with the stale sections on stderr
|
|
145
|
+
def report(text, fresh)
|
|
146
|
+
return 0 if text == fresh
|
|
147
|
+
|
|
148
|
+
stale = SECTIONS.reject { |section| section_text(text, section) == section_text(fresh, section) }
|
|
149
|
+
warn "tools_doc: #{DOCUMENT} differs from the RetiredScript rows in: #{stale.join(', ')} " \
|
|
150
|
+
"(run hecks regeneration_run.project_tools_doc --confirm)"
|
|
151
|
+
1
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# @return [String, nil] the marked table of one section
|
|
155
|
+
def section_text(text, section)
|
|
156
|
+
text[/<!-- generated:begin tools section=#{section} -->\n(.*?)<!-- generated:end tools -->/m, 1]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# The booted Hecks chapters the forms are rendered from, built once.
|
|
160
|
+
class Context
|
|
161
|
+
# @param root [String] the checkout
|
|
162
|
+
def initialize(root)
|
|
163
|
+
@runtime = Hecks.boot(File.join(root, "lib/hecks/hecks"), install_doors: false)
|
|
164
|
+
@projections = {}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# @param row [Hash{String => String}] a `RetiredScript` row
|
|
168
|
+
# @return [Array(Hash, Array<String>)] the projected command or query, and the words that
|
|
169
|
+
# name it on the command line
|
|
170
|
+
# @raise [SystemExit] when the row names no command or query
|
|
171
|
+
def spec_for(row)
|
|
172
|
+
chapter = %w[Custodian Codebase].include?(row["section"]) ? "Hecks" : row["section"]
|
|
173
|
+
cli = projection(chapter)
|
|
174
|
+
name = "#{Naming.snake(row['aggregate'])}.#{row['verb']}"
|
|
175
|
+
command = cli[:commands][cli[:names][:command][name]]
|
|
176
|
+
question = cli[:questions][cli[:names][:question][name]]
|
|
177
|
+
spec = command || question or abort "tools_doc: #{chapter} has no command or query #{name}"
|
|
178
|
+
[spec, words(chapter, name, row)]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
private
|
|
182
|
+
|
|
183
|
+
def projection(chapter)
|
|
184
|
+
@projections[chapter] ||= begin
|
|
185
|
+
launcher = Doors::LauncherOptions.settings(@runtime, chapter)
|
|
186
|
+
options = Doors::LauncherOptions.projection(launcher, "hecks")
|
|
187
|
+
Projector.call(:cli, bluebook: @runtime.registry.bluebook(chapter), options: options)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# `hecks ir`, `hecks console`, `hecks quality_control sweep.run`, `hecks host.check_era`.
|
|
192
|
+
# The launcher takes a name that is only a query as a query, so no `query` word is needed.
|
|
193
|
+
def words(chapter, name, row)
|
|
194
|
+
settings = Doors::LauncherOptions.settings(@runtime, chapter) || {}
|
|
195
|
+
route = (settings[:names] || {}).key(name)
|
|
196
|
+
route ||= row["verb"] if chapter == "Hecks" && Array(settings[:legacy]).include?(row["verb"])
|
|
197
|
+
return [route] if route
|
|
198
|
+
|
|
199
|
+
[*(Naming.snake(chapter) unless chapter == "Hecks"), name]
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
data/lib/hecks/tools.rb
CHANGED
|
@@ -23,6 +23,7 @@ module Hecks
|
|
|
23
23
|
"argument_gate_matrix" => ["tools/argument_gate_matrix", "ArgumentGateMatrix"],
|
|
24
24
|
"project_ci_gates" => ["tools/ci_gates", "CiGates"],
|
|
25
25
|
"decide_ci_gate" => ["tools/ci_gate_decision", "CiGateDecision"],
|
|
26
|
+
"project_tools_doc" => ["tools/tools_doc", "ToolsDoc"],
|
|
26
27
|
"project_deploy" => ["tools/deploy_recipe", "DeployRecipe"],
|
|
27
28
|
"project_site" => ["tools/site_routes", "SiteRoutes"],
|
|
28
29
|
"lint_deploy_recipes" => ["tools/deploy_recipe_lint", "DeployRecipeLint"],
|
data/lib/hecks/version.rb
CHANGED
data/lib/hecks/vocabulary.rb
CHANGED
|
@@ -51,7 +51,7 @@ module Hecks
|
|
|
51
51
|
].freeze,
|
|
52
52
|
"CiGate" => [
|
|
53
53
|
{"name"=>"runtime_changed", "workflow"=>"ci.yml", "mode"=>"touches", "pattern"=>"^lib/hecks/runtime/", "push"=>"skip", "label"=>"does this change touch lib/hecks/runtime/**?"}.freeze,
|
|
54
|
-
{"name"=>"postgres_io_relevant_changed", "workflow"=>"ci-postgres-io-parallel.yml", "mode"=>"skips_unless", "pattern"=>"^(docs/|editors/|release/|deploy/|\\.claude/|\\.githooks/|rust/(parser|codegen|host|build|lsp|web|tests
|
|
54
|
+
{"name"=>"postgres_io_relevant_changed", "workflow"=>"ci-postgres-io-parallel.yml", "mode"=>"skips_unless", "pattern"=>"^(docs/|editors/|release/|deploy/|\\.claude/|\\.githooks/|rust/(parser|codegen|host|build|lsp|web|tests)/|\\.rubocop\\.yml$|\\.rubocop_todo\\.yml$|\\.mcp\\.json$|\\.rspec-local\\.example$|README\\.md$|CHANGELOG\\.md$|CONTRIBUTING\\.md$|SECURITY\\.md$|LICENSE$|\\.gitignore$)", "push"=>"before_sha", "label"=>"does this change touch anything rspec_postgres_io_parallel covers?"}.freeze
|
|
55
55
|
].freeze,
|
|
56
56
|
"Comparison" => [
|
|
57
57
|
{"symbol"=>">=", "compares_less_than"=>"true", "compares_equal"=>"false", "negated"=>"true"}.freeze,
|
|
@@ -137,6 +137,34 @@ module Hecks
|
|
|
137
137
|
{"name"=>"TrueClass"}.freeze,
|
|
138
138
|
{"name"=>"FalseClass"}.freeze
|
|
139
139
|
].freeze,
|
|
140
|
+
"QaDial" => [
|
|
141
|
+
{"name"=>"cadence_seconds", "type"=>"Integer", "meaning"=>"Minimum gap in seconds between one tick's report and the next dispatch; 0 is immediately. Read by the `/loop hecks_qa` caller, not by any script."}.freeze,
|
|
142
|
+
{"name"=>"pr_cap_per_day", "type"=>"Integer", "meaning"=>"Most PRs (Patch plus Improvement) `hecks quality_control patch.open` opens per calendar day; 0 is uncapped."}.freeze,
|
|
143
|
+
{"name"=>"widening_tiers", "type"=>"Array", "meaning"=>"Fuzz depth by `Target.clean_streak`, in three discrete tiers, read by `SweepDepth.for_streak`. The last row (`upto: Float::INFINITY`) is the ceiling."}.freeze,
|
|
144
|
+
{"name"=>"sweep_max_parallel", "type"=>"Integer", "meaning"=>"How many `hecks quality_control query sweep.run <target>` children `--all` keeps running at once."}.freeze,
|
|
145
|
+
{"name"=>"liveness_fallback_seconds", "type"=>"Integer", "meaning"=>"How long the `/loop hecks_qa` caller waits for a tick's report before assuming it stalled."}.freeze,
|
|
146
|
+
{"name"=>"draft_only", "type"=>"Boolean", "meaning"=>"Whether `hecks quality_control patch.open` opens its PR as a draft; false opens it ready for review."}.freeze,
|
|
147
|
+
{"name"=>"auto_merge", "type"=>"Boolean", "meaning"=>"Whether `hecks quality_control patch.open` queues the PR for auto-merge once it is open."}.freeze,
|
|
148
|
+
{"name"=>"adversarial_fraction", "type"=>"Numeric", "meaning"=>"Fraction (0.0..1.0) of generated command steps mutated adversarially; 0 turns the layer off. Higher finds refusal-ordering splits sooner but reaches deep state less often."}.freeze,
|
|
149
|
+
{"name"=>"guided_generation", "type"=>"Boolean", "meaning"=>"Coverage-guided generation across one sweep's seeds (`Hecks::Fuzzing::CoverageCampaign`)."}.freeze,
|
|
150
|
+
{"name"=>"corpus_splice_probability", "type"=>"Numeric", "meaning"=>"Fraction (0.0..1.0) of seeds that start from a prefix of an earlier seed's new coverage. Off by default: measured, it trades breadth for depth (banking reached 1.41x the deep-state tuples, chess lost 0.12x of all tuples), while favoring rare verbs alone never lost."}.freeze,
|
|
151
|
+
{"name"=>"favor_rare_verbs", "type"=>"Integer", "meaning"=>"How many of the least-hit verbs the next seed weights up; 0 turns the lever off."}.freeze,
|
|
152
|
+
{"name"=>"self_consistency_checks", "type"=>"Boolean", "meaning"=>"Whether `hecks quality_control query sweep.run` also runs the self-consistency pass (cold rehydration, replay idempotency, value-object JSON round trip) on the same generated sequence."}.freeze,
|
|
153
|
+
{"name"=>"shrink_budget", "type"=>"Integer", "meaning"=>"Candidate replays `hecks quality_control query sweep.run` may spend shrinking one surprised check; 0 turns shrinking off. `concurrency` is never shrunk: a race does not reproduce on demand."}.freeze,
|
|
154
|
+
{"name"=>"yield_weight_seconds", "type"=>"Integer", "meaning"=>"Seconds of staleness that one point of yield score is worth in `RotationPriority.pick`. Zero would make yield invisible, so pick a number that lets it matter."}.freeze,
|
|
155
|
+
{"name"=>"yield_decay_percent", "type"=>"Integer", "meaning"=>"Percent of the prior yield score kept at each release, so recent findings dominate. Applied by the caller: the mutation language cannot express \"decay, then add\" in `Release`."}.freeze,
|
|
156
|
+
{"name"=>"rotation_stale_floor_seconds", "type"=>"Integer", "meaning"=>"Once a waiting target is this stale, `RotationPriority.pick` takes it whatever its yield score, so a quiet target cannot starve."}.freeze,
|
|
157
|
+
{"name"=>"persistence_parity_seed_cap", "type"=>"Integer", "meaning"=>"Ceiling on `--seeds` for `--persistence-parity`, which pays for real Postgres per dispatch. `hecks quality_control query sweep.run` clamps down, never up, and prints a note."}.freeze,
|
|
158
|
+
{"name"=>"concurrency_seed_cap", "type"=>"Integer", "meaning"=>"Ceiling on `--seeds` for the concurrency mode, which needs two disposable schemas per seed."}.freeze,
|
|
159
|
+
{"name"=>"adapter_parity_pairs", "type"=>"Hash", "meaning"=>"The two adapters each adapter-parity mode compares, by mode name; a new pairing is a new entry. `adapter_parity_sqlite` needs no `database:`/`schema:` because sqlite has no disposable database."}.freeze,
|
|
160
|
+
{"name"=>"modes", "type"=>"Hash", "meaning"=>"Which comparison modes `hecks quality_control query sweep.run` may run: the enabled ones intersected with what `TargetCapabilities.infer(path)` finds in the target. `--modes a,b,c` overrides for one run. `wasm_front` and `adapter_parity_postgres` are off because nothing runs them; the others are built and off because their I/O cost across the rotation is unmeasured. `hecks quality_control query sweep.run` refuses to start when a mode outside `TargetCapabilities::RUNNABLE_MODES` is enabled."}.freeze,
|
|
161
|
+
{"name"=>"role_draw_probability", "type"=>"Numeric", "meaning"=>"How often a generated role-gated command step carries a drawn caller (`role:`/`actor_id:`); 0 turns the draw off."}.freeze,
|
|
162
|
+
{"name"=>"dry_run_fraction", "type"=>"Numeric", "meaning"=>"Fraction of generated command steps offered as a dry run instead of a real dispatch; 0 is off. Kept low: a dry run creates no state for later steps to act on."}.freeze,
|
|
163
|
+
{"name"=>"generated_domains_per_tick", "type"=>"Integer", "meaning"=>"How many generated domains one `hecks quality_control sweep.tick` checks after the rotation sweep; 0 skips the step."}.freeze,
|
|
164
|
+
{"name"=>"generated_domains_rust", "type"=>"Boolean", "meaning"=>"Whether generated domains are also compared against a compiled Rust binary built in a scratch copy."}.freeze,
|
|
165
|
+
{"name"=>"generated_domain_seeds", "type"=>"Integer", "meaning"=>"Generated sequences run per generated domain."}.freeze,
|
|
166
|
+
{"name"=>"structural_refusal_boundary", "type"=>"Array", "meaning"=>"Construct families a skipped query verb may belong to. A skip inside the list is logged Held, one outside it Surprised. Shrink-only: spec/fuzzing/rust_gap_manifest_spec.rb fails when a family here is declared by no committed manifest."}.freeze
|
|
167
|
+
].freeze,
|
|
140
168
|
"QueryComparator" => [
|
|
141
169
|
{"name"=>"eq"}.freeze,
|
|
142
170
|
{"name"=>"ne"}.freeze,
|
|
@@ -330,6 +358,129 @@ module Hecks
|
|
|
330
358
|
{"refusal"=>"AttributeAbsent", "site"=>"absent_read", "template"=>"{aggregate} {field} is absent on this record — declared, not optional, and added since it was written. Backfill it in a translation (backfill :{field}, default: ...), or declare it optional: true"}.freeze,
|
|
331
359
|
{"refusal"=>"ProjectionAbsent", "site"=>"absent_read", "template"=>"{aggregate} {field} is not yet projected on this record — declared via projects :{field}, but no rebuild sweep has populated it. Run the sweep, or read {reference}.{remote_field} directly if this rule cannot wait"}.freeze
|
|
332
360
|
].freeze,
|
|
361
|
+
"RetiredScript" => [
|
|
362
|
+
{"script"=>"ir", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"ir"}.freeze,
|
|
363
|
+
{"script"=>"shape", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"shape"}.freeze,
|
|
364
|
+
{"script"=>"stores", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"stores"}.freeze,
|
|
365
|
+
{"script"=>"history", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"history"}.freeze,
|
|
366
|
+
{"script"=>"statements", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"statements"}.freeze,
|
|
367
|
+
{"script"=>"narrate", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"narrate"}.freeze,
|
|
368
|
+
{"script"=>"docs", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"docs"}.freeze,
|
|
369
|
+
{"script"=>"project_diagrams", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"project_diagrams"}.freeze,
|
|
370
|
+
{"script"=>"project_glossary", "section"=>"Custodian", "aggregate"=>"Introspection", "verb"=>"glossary"}.freeze,
|
|
371
|
+
{"script"=>"model_check", "section"=>"Custodian", "aggregate"=>"ModelCheckRun", "verb"=>"model_check"}.freeze,
|
|
372
|
+
{"script"=>"run", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"run", "form"=>"hecks run [domain] <verb [name=value …] | script.json | - | '{\"steps\":[…]}'>"}.freeze,
|
|
373
|
+
{"script"=>"project", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"refresh_projections"}.freeze,
|
|
374
|
+
{"script"=>"behaviors", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"run_behaviors"}.freeze,
|
|
375
|
+
{"script"=>"console", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"open_console"}.freeze,
|
|
376
|
+
{"script"=>"follow", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"follow"}.freeze,
|
|
377
|
+
{"script"=>"smoke_test", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"smoke_test"}.freeze,
|
|
378
|
+
{"script"=>"smoke_http", "section"=>"Custodian", "aggregate"=>"Operation", "verb"=>"smoke_http"}.freeze,
|
|
379
|
+
{"script"=>"check_era", "section"=>"Custodian", "aggregate"=>"Host", "verb"=>"check_era"}.freeze,
|
|
380
|
+
{"script"=>"merge_tail", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"merge_tail"}.freeze,
|
|
381
|
+
{"script"=>"reattest_era", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"reattest"}.freeze,
|
|
382
|
+
{"script"=>"backfill_era_projections", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"backfill_projections"}.freeze,
|
|
383
|
+
{"script"=>"scaffold_translation", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"scaffold_translation"}.freeze,
|
|
384
|
+
{"script"=>"translation_audit", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"audit_translation"}.freeze,
|
|
385
|
+
{"script"=>"translation_audit", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"approve_translation"}.freeze,
|
|
386
|
+
{"script"=>"compact", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"compact"}.freeze,
|
|
387
|
+
{"script"=>"heki_compact", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"compact_heki"}.freeze,
|
|
388
|
+
{"script"=>"vendor_bluebook", "section"=>"Custodian", "aggregate"=>"Package", "verb"=>"vendor", "note"=>"waits: a refusal exits 1 with its reason on stderr"}.freeze,
|
|
389
|
+
{"script"=>"project_cli", "section"=>"Custodian", "aggregate"=>"Door", "verb"=>"project_cli"}.freeze,
|
|
390
|
+
{"script"=>"hecks_mcp_door", "section"=>"Custodian", "aggregate"=>"Door", "verb"=>"serve_mcp"}.freeze,
|
|
391
|
+
{"script"=>"project_rust", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"project_rust"}.freeze,
|
|
392
|
+
{"script"=>"project_wasm", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"build_wasm"}.freeze,
|
|
393
|
+
{"script"=>"project_host", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"build_host"}.freeze,
|
|
394
|
+
{"script"=>"project_wasm_browser", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"build_browser_wasm"}.freeze,
|
|
395
|
+
{"script"=>"rust_coverage", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"rust_coverage"}.freeze,
|
|
396
|
+
{"script"=>"rust_coverage", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"check_coverage_allowlist"}.freeze,
|
|
397
|
+
{"script"=>"rust_conformance", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"check_conformance"}.freeze,
|
|
398
|
+
{"script"=>"rust_conformance_fuzz", "section"=>"Custodian", "aggregate"=>"Build", "verb"=>"fuzz_conformance"}.freeze,
|
|
399
|
+
{"script"=>"fuzz", "section"=>"Custodian", "aggregate"=>"FuzzRun", "verb"=>"fuzz"}.freeze,
|
|
400
|
+
{"script"=>"generate", "section"=>"Custodian", "aggregate"=>"FuzzRun", "verb"=>"generate_sequence"}.freeze,
|
|
401
|
+
{"script"=>"bench", "section"=>"Custodian", "aggregate"=>"FuzzRun", "verb"=>"bench"}.freeze,
|
|
402
|
+
{"script"=>"(new)", "section"=>"Custodian", "aggregate"=>"Era", "verb"=>"hold_first"}.freeze,
|
|
403
|
+
{"script"=>"project_deploy", "section"=>"Deploy", "aggregate"=>"Recipe", "verb"=>"project"}.freeze,
|
|
404
|
+
{"script"=>"lint_deploy_recipes", "section"=>"Deploy", "aggregate"=>"MakefileCheck", "verb"=>"lint"}.freeze,
|
|
405
|
+
{"script"=>"deploy_template_diff", "section"=>"Deploy", "aggregate"=>"TemplateComparison", "verb"=>"diff"}.freeze,
|
|
406
|
+
{"script"=>"project_oidc", "section"=>"Deploy", "aggregate"=>"OidcManifest", "verb"=>"project_oidc"}.freeze,
|
|
407
|
+
{"script"=>"project_tenant", "section"=>"Deploy", "aggregate"=>"Tenant", "verb"=>"provision"}.freeze,
|
|
408
|
+
{"script"=>"project_tenant", "section"=>"Deploy", "aggregate"=>"Tenant", "verb"=>"reprovision"}.freeze,
|
|
409
|
+
{"script"=>"(new)", "section"=>"Site", "aggregate"=>"SiteProjection", "verb"=>"project_site"}.freeze,
|
|
410
|
+
{"script"=>"project_model", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_model"}.freeze,
|
|
411
|
+
{"script"=>"project_vocabulary", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_vocabulary"}.freeze,
|
|
412
|
+
{"script"=>"project_rust_vocabulary", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_rust_vocabulary"}.freeze,
|
|
413
|
+
{"script"=>"project_refusal_wording", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_refusal_wording"}.freeze,
|
|
414
|
+
{"script"=>"project_reserved_names", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_reserved_names"}.freeze,
|
|
415
|
+
{"script"=>"project_parser_table", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_parser_table"}.freeze,
|
|
416
|
+
{"script"=>"project_bootstrap_table", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_bootstrap_table"}.freeze,
|
|
417
|
+
{"script"=>"project_field_hints", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_field_hints"}.freeze,
|
|
418
|
+
{"script"=>"expression_projection", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_expression_tables"}.freeze,
|
|
419
|
+
{"script"=>"reference", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"project_reference"}.freeze,
|
|
420
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"word_status"}.freeze,
|
|
421
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"propose"}.freeze,
|
|
422
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"admit"}.freeze,
|
|
423
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"deprecate"}.freeze,
|
|
424
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"retire"}.freeze,
|
|
425
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"rename"}.freeze,
|
|
426
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"propose_argument"}.freeze,
|
|
427
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"admit_argument"}.freeze,
|
|
428
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"deprecate_argument"}.freeze,
|
|
429
|
+
{"script"=>"evolve", "section"=>"Codebase", "aggregate"=>"LanguageRun", "verb"=>"retire_argument"}.freeze,
|
|
430
|
+
{"script"=>"project_kernel_capabilities", "section"=>"Codebase", "aggregate"=>"KernelRun", "verb"=>"project_kernel_capabilities"}.freeze,
|
|
431
|
+
{"script"=>"rust_kernel_coverage", "section"=>"Codebase", "aggregate"=>"KernelRun", "verb"=>"measure_kernel_coverage"}.freeze,
|
|
432
|
+
{"script"=>"check_engine_agreement", "section"=>"Codebase", "aggregate"=>"ConformanceRun", "verb"=>"check_engine_agreement"}.freeze,
|
|
433
|
+
{"script"=>"doc_coverage", "section"=>"Codebase", "aggregate"=>"ConformanceRun", "verb"=>"measure_doc_coverage"}.freeze,
|
|
434
|
+
{"script"=>"argument_gate_matrix", "section"=>"Codebase", "aggregate"=>"ConformanceRun", "verb"=>"argument_gate_matrix"}.freeze,
|
|
435
|
+
{"script"=>"regen_codegen_domains", "section"=>"Codebase", "aggregate"=>"RegenerationRun", "verb"=>"regenerate_corpus"}.freeze,
|
|
436
|
+
{"script"=>"standardize_comments", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"report_comments"}.freeze,
|
|
437
|
+
{"script"=>"standardize_comments", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"check_comments"}.freeze,
|
|
438
|
+
{"script"=>"standardize_comments", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"fix_comments"}.freeze,
|
|
439
|
+
{"script"=>"standardize_comments", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"write_comment_baseline"}.freeze,
|
|
440
|
+
{"script"=>"standardize_comments", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"check_comments_unchanged"}.freeze,
|
|
441
|
+
{"script"=>"standardize_comments_rust", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"report_rust_comments"}.freeze,
|
|
442
|
+
{"script"=>"standardize_comments_rust", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"check_rust_comments"}.freeze,
|
|
443
|
+
{"script"=>"standardize_comments_rust", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"fix_rust_comments"}.freeze,
|
|
444
|
+
{"script"=>"canonicalise", "section"=>"Codebase", "aggregate"=>"StyleRun", "verb"=>"canonicalise"}.freeze,
|
|
445
|
+
{"script"=>"codemod_hoist_local_givens", "section"=>"Codebase", "aggregate"=>"CodemodRun", "verb"=>"hoist_local_givens"}.freeze,
|
|
446
|
+
{"script"=>"codemod_implicit_append_fields", "section"=>"Codebase", "aggregate"=>"CodemodRun", "verb"=>"drop_implicit_append_fields"}.freeze,
|
|
447
|
+
{"script"=>"rspec_shard_files", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"shard_specs"}.freeze,
|
|
448
|
+
{"script"=>"rspec_io_parallel_files", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"list_io_parallel_specs"}.freeze,
|
|
449
|
+
{"script"=>"rspec_io_parallel_files", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"write_io_parallel_spec_list"}.freeze,
|
|
450
|
+
{"script"=>"refresh_rspec_runtime_baseline", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"refresh_runtime_baseline"}.freeze,
|
|
451
|
+
{"script"=>"spec_example", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"run_spec_example"}.freeze,
|
|
452
|
+
{"script"=>"stress_concurrency_specs", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"stress_concurrency"}.freeze,
|
|
453
|
+
{"script"=>"regenerate_persistence_legacy_fixtures", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"regenerate_legacy_fixtures"}.freeze,
|
|
454
|
+
{"script"=>"seed_semantics_corpus", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"seed_semantics_corpus"}.freeze,
|
|
455
|
+
{"script"=>"pattern-cases", "section"=>"Codebase", "aggregate"=>"TestSuiteRun", "verb"=>"record_pattern_cases"}.freeze,
|
|
456
|
+
{"script"=>"corpus", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"rust_domains"}.freeze,
|
|
457
|
+
{"script"=>"corpus", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"regen_order"}.freeze,
|
|
458
|
+
{"script"=>"corpus", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"corpus_rust_coverage"}.freeze,
|
|
459
|
+
{"script"=>"query_ir", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"ir_constructs"}.freeze,
|
|
460
|
+
{"script"=>"query_ir", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"ir_duplicates"}.freeze,
|
|
461
|
+
{"script"=>"query_ir", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"ir_impact"}.freeze,
|
|
462
|
+
{"script"=>"hecks_query_ir_mcp", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"serve_query_ir_mcp"}.freeze,
|
|
463
|
+
{"script"=>"present", "section"=>"Codebase", "aggregate"=>"CorpusRun", "verb"=>"present"}.freeze,
|
|
464
|
+
{"script"=>"release", "section"=>"Codebase", "aggregate"=>"PublishingRun", "verb"=>"publish", "note"=>"without --confirm, the old --dry-run"}.freeze,
|
|
465
|
+
{"script"=>"release_gem", "section"=>"Codebase", "aggregate"=>"PublishingRun", "verb"=>"publish_gem"}.freeze,
|
|
466
|
+
{"script"=>"(new)", "section"=>"Codebase", "aggregate"=>"GateRun", "verb"=>"gate"}.freeze,
|
|
467
|
+
{"script"=>"qa_tick", "section"=>"QualityControl", "aggregate"=>"Sweep", "verb"=>"tick"}.freeze,
|
|
468
|
+
{"script"=>"qa_sweep", "section"=>"QualityControl", "aggregate"=>"Sweep", "verb"=>"run", "passes"=>"--all --seeds N --steps N --adversarial F --role-draw F --dry-run F --self-consistency BOOL --modes a,b --persistence-parity --no-parity"}.freeze,
|
|
469
|
+
{"script"=>"qa_sweep", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"release"}.freeze,
|
|
470
|
+
{"script"=>"qa_pr_check", "section"=>"QualityControl", "aggregate"=>"Clearance", "verb"=>"check_pull_requests"}.freeze,
|
|
471
|
+
{"script"=>"qa_open_pr", "section"=>"QualityControl", "aggregate"=>"Patch", "verb"=>"open"}.freeze,
|
|
472
|
+
{"script"=>"qa_open_pr", "section"=>"QualityControl", "aggregate"=>"Improvement", "verb"=>"open"}.freeze,
|
|
473
|
+
{"script"=>"qa_log_bug", "section"=>"QualityControl", "aggregate"=>"Bug", "verb"=>"log"}.freeze,
|
|
474
|
+
{"script"=>"qa_seed_angles", "section"=>"QualityControl", "aggregate"=>"Angle", "verb"=>"seed"}.freeze,
|
|
475
|
+
{"script"=>"qa_seed_targets", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"seed"}.freeze,
|
|
476
|
+
{"script"=>"qa_generated_domains", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"check_generated_domains", "passes"=>"--domains 3 --start N --forms a,b --seeds 5 --steps 25 --adversarial 0.3 --rust --shrink-budget 200 --domain-shrink-budget 40 --promote dir --name N --from-dials --blueprint F --source F"}.freeze,
|
|
477
|
+
{"script"=>"qa_mine_combinations", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"mine_combinations", "passes"=>"--candidates 3 --rust --seeds 5 --steps 25 --adversarial 0.3 --repair-rounds 1 --agent CMD --from DIR --against PATH --brief"}.freeze,
|
|
478
|
+
{"script"=>"qa_domain_novelty", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"judge_novelty", "passes"=>"--against PATH …"}.freeze,
|
|
479
|
+
{"script"=>"qa_discover_external_domains", "section"=>"QualityControl", "aggregate"=>"Target", "verb"=>"discover_external_domains", "passes"=>"--projects-dir ~/Projects --max-depth 3 --known-path PATH …"}.freeze,
|
|
480
|
+
{"script"=>"qa_postgres_migrate", "section"=>"QualityControl", "aggregate"=>"Sweep", "verb"=>"migrate_ledger_from_heki", "passes"=>"[aggregate …] --force", "note"=>"a dry run without --force"}.freeze,
|
|
481
|
+
{"script"=>"qa_postgres_role", "section"=>"QualityControl", "aggregate"=>"Sweep", "verb"=>"create_ledger_role"}.freeze,
|
|
482
|
+
{"script"=>"qa_concurrency_racer", "section"=>"QualityControl", "aggregate"=>"Sweep", "verb"=>"race", "note"=>"not user-facing; ProcessPool starts it"}.freeze
|
|
483
|
+
].freeze,
|
|
333
484
|
"RustReservedWord" => [
|
|
334
485
|
{"word"=>"as"}.freeze,
|
|
335
486
|
{"word"=>"break"}.freeze,
|
data/lib/hecks.rb
CHANGED
|
@@ -34,6 +34,7 @@ require_relative "hecks/doors/cli_runner"
|
|
|
34
34
|
require_relative "hecks/storehouse"
|
|
35
35
|
require_relative "hecks/mcp_stdio_guard"
|
|
36
36
|
require_relative "hecks/doors/mcp_door_scope"
|
|
37
|
+
require_relative "hecks/doors/mcp_guide_cache"
|
|
37
38
|
require_relative "hecks/framework"
|
|
38
39
|
require_relative "hecks/vendoring"
|
|
39
40
|
require_relative "hecks/embryonaut_bluebook"
|