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
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Each bin/ script and exe/hecks route, and the hecks 3.0 form that replaces it: the verb spelling the
|
|
2
|
-
# 3.0 launcher answers to (ADR 0080, section 7), with QualityControl verbs after `hecks quality_control`.
|
|
3
|
-
---
|
|
4
|
-
argument_gate_matrix: hecks conformance_run.argument_gate_matrix [--confirm] (writes only with --confirm)
|
|
5
|
-
backfill_era_projections: hecks era.backfill_projections <domain>
|
|
6
|
-
behaviors: hecks operation.run_behaviors subject=<path>
|
|
7
|
-
bench: hecks fuzz_run.bench [domains=pizzas,banking] [targets=] [iterations=1000] [warmup=200]
|
|
8
|
-
[runs=3] [rust_binary=] [format=markdown] [output=]
|
|
9
|
-
canonicalise: hecks style_run.canonicalise <file.json>
|
|
10
|
-
check_engine_agreement: hecks conformance_run.check_engine_agreement
|
|
11
|
-
check_era: hecks host.check_era <url> expected=era-file [timeout=]
|
|
12
|
-
codemod_hoist_local_givens: hecks codemod_run.hoist_local_givens --confirm
|
|
13
|
-
codemod_implicit_append_fields: hecks codemod_run.drop_implicit_append_fields --confirm
|
|
14
|
-
compact: hecks era.compact <domain> [aggregates=A,B] --confirm
|
|
15
|
-
console: hecks console [subject=<domain>]
|
|
16
|
-
corpus: hecks corpus_run.rust_domains; hecks corpus_run.regen_order; hecks corpus_run.corpus_rust_coverage
|
|
17
|
-
deploy_template_diff: hecks deploy template_comparison.diff before=a.yaml after=b.yaml [--json] [--strict]
|
|
18
|
-
doc_coverage: hecks conformance_run.measure_doc_coverage
|
|
19
|
-
docs: hecks docs [domain-path] [aggregate]
|
|
20
|
-
evolve: hecks language_run.word_status; hecks language_run.propose <word> context=X [body=none] [inner=] [opens=]
|
|
21
|
-
[fills=]; hecks language_run.admit|deprecate|retire <word> context=X; hecks language_run.rename <word> context=X
|
|
22
|
-
new_name=Y; hecks language_run.propose_argument <word> context=X kind=K [required=false] [at=N]
|
|
23
|
-
[named=] [fills=] [pairs_shape=]; hecks language_run.admit_argument|deprecate_argument|retire_argument
|
|
24
|
-
<word> context=X [at=N] [named=]
|
|
25
|
-
expression_projection: hecks language_run.project_expression_tables [--stdout]
|
|
26
|
-
follow: hecks operation.follow <domain> [aggregate=Name] [since=N] [interval=0.5] [wait=N] [--from-now] [--stream]
|
|
27
|
-
fuzz: hecks fuzz_run.fuzz [domain] [seeds=20] [steps=30] [workers=] [adapter=memory]
|
|
28
|
-
generate: hecks fuzz_run.generate_sequence <domain> [seed=1] [steps=30] [adversarial=0.0]
|
|
29
|
-
hecks_mcp_door: hecks mcp [--stdio]
|
|
30
|
-
hecks_query_ir_mcp: hecks corpus_run.serve_query_ir_mcp
|
|
31
|
-
heki_compact: hecks era.compact_heki <domain> [aggregates=A,B] --confirm
|
|
32
|
-
history: hecks introspection.history <domain>
|
|
33
|
-
ir: hecks ir <domain> [--translations] | hecks ir --meta
|
|
34
|
-
lint_deploy_recipes: hecks deploy makefile_check.lint [makefiles=a,b]
|
|
35
|
-
merge_tail: hecks era.merge_tail <domain> winners=id:old,id:new --confirm
|
|
36
|
-
model_check: hecks model_check [--strict] [--profile client] [<domain> …]
|
|
37
|
-
narrate: hecks narrate [domain-path] [aggregate]
|
|
38
|
-
pattern-cases: hecks test_suite_run.record_pattern_cases
|
|
39
|
-
present: hecks corpus_run.present [port=4567]
|
|
40
|
-
project: hecks operation.refresh_projections subject=<domain>
|
|
41
|
-
project_bootstrap_table: hecks language_run.project_bootstrap_table
|
|
42
|
-
project_cli: hecks project_cli [domain-path …]
|
|
43
|
-
project_deploy: hecks deploy recipe.project <domain> [tenant=] [schema=] [out=] [environment=]
|
|
44
|
-
project_diagrams: hecks project_diagrams <domain-path> <ChapterName>
|
|
45
|
-
project_field_hints: hecks language_run.project_field_hints
|
|
46
|
-
project_glossary: hecks introspection.glossary <domain> chapter=Name
|
|
47
|
-
project_kernel_capabilities: hecks kernel_run.project_kernel_capabilities
|
|
48
|
-
project_model: hecks language_run.project_model
|
|
49
|
-
project_oidc: hecks deploy oidc_manifest.project_oidc [domains=a,b]
|
|
50
|
-
project_parser_table: hecks language_run.project_parser_table
|
|
51
|
-
project_refusal_wording: hecks language_run.project_refusal_wording
|
|
52
|
-
project_reserved_names: hecks language_run.project_reserved_names
|
|
53
|
-
project_rust: hecks build.project_rust <domain>
|
|
54
|
-
project_rust_vocabulary: hecks language_run.project_rust_vocabulary
|
|
55
|
-
project_tenant: hecks deploy tenant.provision <domain_dir> slug=s domain= realm= schema=
|
|
56
|
-
database= [adapter=PostgresEra]; hecks deploy tenant.reprovision <tenant> directory= database=
|
|
57
|
-
[adapter=PostgresEra]
|
|
58
|
-
project_vocabulary: hecks language_run.project_vocabulary
|
|
59
|
-
project_wasm: hecks build.build_wasm <domain>
|
|
60
|
-
project_wasm_browser: hecks build.build_browser_wasm <domain>
|
|
61
|
-
qa_concurrency_racer: not user-facing; ProcessPool starts it as hecks quality_control
|
|
62
|
-
sweep.race domain= database= schema= verb= step_arguments=
|
|
63
|
-
qa_discover_external_domains: hecks quality_control target.discover_external_domains [arguments="--projects-dir
|
|
64
|
-
~/Projects --max-depth 3 --known-path PATH …"]
|
|
65
|
-
qa_domain_novelty: hecks quality_control target.judge_novelty <domain> [arguments="--against
|
|
66
|
-
PATH …"]
|
|
67
|
-
qa_generated_domains: hecks quality_control target.check_generated_domains [arguments="--domains
|
|
68
|
-
3 --start N --forms a,b --seeds 5 --steps 25 --adversarial 0.3 --rust --shrink-budget
|
|
69
|
-
200 --domain-shrink-budget 40 --promote dir --name N --from-dials --blueprint F
|
|
70
|
-
--source F"]
|
|
71
|
-
qa_log_bug: hecks quality_control bug.log sweep=<sweep id> reference= sequence=N title=
|
|
72
|
-
demonstration= symptom= expectation= submitter= [tags=a,b] [name=] [reproduced=yes|no]
|
|
73
|
-
qa_mine_combinations: hecks quality_control target.mine_combinations [arguments="--candidates
|
|
74
|
-
3 --rust --seeds 5 --steps 25 --adversarial 0.3 --repair-rounds 1 --agent CMD --from
|
|
75
|
-
DIR --against PATH --brief"]
|
|
76
|
-
qa_open_pr: hecks quality_control patch.open bug=BUG#n number=N url=… branch=… commit=SHA
|
|
77
|
-
title=… [now=]; hecks quality_control improvement.open [angle=ANGLE-n] number=N
|
|
78
|
-
url=… branch=… title=… [now=]
|
|
79
|
-
qa_postgres_migrate: hecks quality_control sweep.migrate_ledger_from_heki domain=<domain_dir>
|
|
80
|
-
data=<heki_dir> [arguments="[aggregate …] --force"] (a dry run without --force)
|
|
81
|
-
qa_postgres_role: hecks quality_control sweep.create_ledger_role <database> [role=hecks_qa]
|
|
82
|
-
qa_pr_check: hecks quality_control clearance.check_pull_requests
|
|
83
|
-
qa_seed_angles: hecks quality_control angle.seed
|
|
84
|
-
qa_seed_targets: hecks quality_control target.seed
|
|
85
|
-
qa_sweep: hecks quality_control query sweep.run [target=] [arguments="--all --seeds N --steps
|
|
86
|
-
N --adversarial F --role-draw F --dry-run F --self-consistency BOOL --modes a,b
|
|
87
|
-
--persistence-parity --no-parity"]; hecks quality_control target.release <target> [now=]
|
|
88
|
-
[next_streak=] [capabilities=] [yield_score=]
|
|
89
|
-
qa_tick: hecks quality_control sweep.tick
|
|
90
|
-
query_ir: hecks corpus_run.ir_constructs [names=a,b]; hecks corpus_run.ir_duplicates [domains=a,b] [--meta];
|
|
91
|
-
hecks corpus_run.ir_impact name=N field=F
|
|
92
|
-
reattest_era: hecks era.reattest <domain> era=N --confirm
|
|
93
|
-
reference: hecks language_run.project_reference
|
|
94
|
-
refresh_rspec_runtime_baseline: hecks test_suite_run.refresh_runtime_baseline [workers=] [from_run=ID]
|
|
95
|
-
regen_codegen_domains: hecks regeneration_run.regenerate_corpus [--check]
|
|
96
|
-
regenerate_persistence_legacy_fixtures: hecks test_suite_run.regenerate_legacy_fixtures --confirm
|
|
97
|
-
release: hecks publishing_run.publish [--gem-only] [--npm-only] [--npm-local] [--no-wait] --confirm
|
|
98
|
-
(without --confirm, the old --dry-run)
|
|
99
|
-
release_gem: hecks publishing_run.publish_gem --confirm
|
|
100
|
-
rspec_io_parallel_files: hecks test_suite_run.list_io_parallel_specs exclude=REGEX [tags=] [check=file];
|
|
101
|
-
hecks test_suite_run.write_io_parallel_spec_list exclude=REGEX [tags=] write=file --confirm
|
|
102
|
-
rspec_shard_files: hecks test_suite_run.shard_specs group=1 groups=N [runtime_log=]
|
|
103
|
-
run: hecks run [domain] <verb [name=value …] | script.json | - | '{"steps":[…]}'>
|
|
104
|
-
rust_conformance: hecks build.check_conformance <domain> script=steps.json [artifact=native]
|
|
105
|
-
rust_conformance_fuzz: hecks build.fuzz_conformance <domain> artifact=native [seeds=10]
|
|
106
|
-
[steps=25]
|
|
107
|
-
rust_coverage: hecks build.rust_coverage <module> [codegen=ruby]; hecks build.check_coverage_allowlist
|
|
108
|
-
rust_kernel_coverage: hecks kernel_run.measure_kernel_coverage
|
|
109
|
-
scaffold_translation: hecks era.scaffold_translation <domain>
|
|
110
|
-
seed_semantics_corpus: hecks test_suite_run.seed_semantics_corpus [fixture=name]
|
|
111
|
-
shape: hecks introspection.shape <domain>
|
|
112
|
-
smoke_http: hecks operation.smoke_http path=/p [url=] [header=] [scheme=timestamped]
|
|
113
|
-
[payload=] [payload_file=] [health_path=] [state_path=]
|
|
114
|
-
smoke_test: hecks smoke_test [domain]
|
|
115
|
-
spec_example: hecks test_suite_run.run_spec_example file=path example=text
|
|
116
|
-
standardize_comments: hecks style_run.report_comments paths=a,b [only=] [--json] [top=20]; hecks
|
|
117
|
-
style_run.check_comments paths=…; hecks style_run.fix_comments paths=… --confirm; hecks style_run.write_comment_baseline
|
|
118
|
-
--confirm; hecks style_run.check_comments_unchanged ref=REF
|
|
119
|
-
standardize_comments_rust: hecks style_run.report_rust_comments paths=a,b [only=] [--json] [top=N];
|
|
120
|
-
hecks style_run.check_rust_comments paths=… [only=]; hecks style_run.fix_rust_comments paths=… [only=]
|
|
121
|
-
--confirm
|
|
122
|
-
statements: hecks introspection.statements <domain> chapter=Name
|
|
123
|
-
stores: hecks stores <domain>
|
|
124
|
-
stress_concurrency_specs: hecks test_suite_run.stress_concurrency [runs=] [parallel=] [seed_start=]
|
|
125
|
-
translation_audit: hecks era.audit_translation <domain>; hecks era.approve_translation <domain>
|
|
126
|
-
[snapshot=] [host_version=] [rehearsal=pass|fail] [rehearsed_at=] --confirm
|
|
127
|
-
vendor_bluebook: hecks package.vendor <package[@version]> [from=path] [root=path]
|
data/lib/hecks/three_zero.rb
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "yaml"
|
|
4
|
-
|
|
5
|
-
module Hecks
|
|
6
|
-
# The table of what each retired `bin/` script became in hecks 3.0.0 (ADR 0080): a command on
|
|
7
|
-
# the Hecks domain, run through `exe/hecks`. `docs/tools.md` is pinned to it.
|
|
8
|
-
module ThreeZero
|
|
9
|
-
# Each retired script's name mapped to the 3.0 form that replaced it.
|
|
10
|
-
FORMS = YAML.safe_load_file(File.join(__dir__, "three_zero/forms.yml")).freeze
|
|
11
|
-
end
|
|
12
|
-
end
|
data/rust/build/src/json.rs
DELETED
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
//! A minimal, dependency-free, mutable JSON value with a reader and a pretty writer.
|
|
2
|
-
//! The writer matches `JSON.pretty_generate` byte-for-byte, including its empty-array quirk.
|
|
3
|
-
|
|
4
|
-
use std::fmt::Write as _;
|
|
5
|
-
|
|
6
|
-
#[derive(Debug, Clone, PartialEq)]
|
|
7
|
-
pub enum Json {
|
|
8
|
-
Null,
|
|
9
|
-
Bool(bool),
|
|
10
|
-
/// Raw literal text as scanned, so numbers round-trip unchanged.
|
|
11
|
-
Number(String),
|
|
12
|
-
String(String),
|
|
13
|
-
Array(Vec<Json>),
|
|
14
|
-
/// Insertion-ordered pairs; byte-exact re-emission depends on key order.
|
|
15
|
-
Object(Vec<(String, Json)>),
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
impl Json {
|
|
19
|
-
pub fn parse(text: &str) -> Result<Json, String> {
|
|
20
|
-
let mut p = Parser { bytes: text.as_bytes(), pos: 0 };
|
|
21
|
-
p.skip_ws();
|
|
22
|
-
let value = p.parse_value()?;
|
|
23
|
-
p.skip_ws();
|
|
24
|
-
if p.pos != p.bytes.len() {
|
|
25
|
-
return Err(format!("trailing content at byte {}", p.pos));
|
|
26
|
-
}
|
|
27
|
-
Ok(value)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/// Looks up `key`, treating a `null` value as missing.
|
|
31
|
-
pub fn get(&self, key: &str) -> Option<&Json> {
|
|
32
|
-
match self {
|
|
33
|
-
Json::Object(pairs) => pairs.iter().find(|(k, v)| k == key && !matches!(v, Json::Null)).map(|(_, v)| v),
|
|
34
|
-
_ => None,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
pub fn get_mut(&mut self, key: &str) -> Option<&mut Json> {
|
|
39
|
-
match self {
|
|
40
|
-
Json::Object(pairs) => pairs.iter_mut().find(|(k, _)| k == key).map(|(_, v)| v),
|
|
41
|
-
_ => None,
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
pub fn as_str(&self) -> Option<&str> {
|
|
46
|
-
match self {
|
|
47
|
-
Json::String(s) => Some(s.as_str()),
|
|
48
|
-
_ => None,
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
pub fn as_array(&self) -> Option<&[Json]> {
|
|
53
|
-
match self {
|
|
54
|
-
Json::Array(items) => Some(items.as_slice()),
|
|
55
|
-
_ => None,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Json>> {
|
|
60
|
-
match self {
|
|
61
|
-
Json::Array(items) => Some(items),
|
|
62
|
-
_ => None,
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
pub fn as_object(&self) -> Option<&[(String, Json)]> {
|
|
67
|
-
match self {
|
|
68
|
-
Json::Object(pairs) => Some(pairs.as_slice()),
|
|
69
|
-
_ => None,
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/// Ruby truthiness: everything except `false` and `null` is true.
|
|
74
|
-
pub fn as_bool(&self) -> bool {
|
|
75
|
-
!matches!(self, Json::Bool(false) | Json::Null)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/// Iterates an array field; empty for any other value.
|
|
79
|
-
pub fn each(&self) -> &[Json] {
|
|
80
|
-
self.as_array().unwrap_or(&[])
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/// Sets `key` to `value`, the only mutation the optional-marking pass performs.
|
|
84
|
-
/// Overwrites the existing pair, or appends one if absent.
|
|
85
|
-
pub fn set_bool(&mut self, key: &str, value: bool) {
|
|
86
|
-
if let Json::Object(pairs) = self {
|
|
87
|
-
if let Some((_, existing)) = pairs.iter_mut().find(|(k, _)| k == key) {
|
|
88
|
-
*existing = Json::Bool(value);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
pairs.push((key.to_string(), Json::Bool(value)));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/// Sets `key` to `value`, overwriting in place or else appending last.
|
|
96
|
-
pub fn set(&mut self, key: &str, value: Json) {
|
|
97
|
-
if let Json::Object(pairs) = self {
|
|
98
|
-
if let Some((_, existing)) = pairs.iter_mut().find(|(k, _)| k == key) {
|
|
99
|
-
*existing = value;
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
pairs.push((key.to_string(), value));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
struct Parser<'a> {
|
|
108
|
-
bytes: &'a [u8],
|
|
109
|
-
pos: usize,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
impl<'a> Parser<'a> {
|
|
113
|
-
fn peek(&self) -> Option<u8> {
|
|
114
|
-
self.bytes.get(self.pos).copied()
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
fn skip_ws(&mut self) {
|
|
118
|
-
while let Some(b) = self.peek() {
|
|
119
|
-
if b == b' ' || b == b'\t' || b == b'\n' || b == b'\r' {
|
|
120
|
-
self.pos += 1;
|
|
121
|
-
} else {
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
fn expect(&mut self, b: u8) -> Result<(), String> {
|
|
128
|
-
if self.peek() == Some(b) {
|
|
129
|
-
self.pos += 1;
|
|
130
|
-
Ok(())
|
|
131
|
-
} else {
|
|
132
|
-
Err(format!("expected {:?} at byte {}, found {:?}", b as char, self.pos, self.peek().map(|c| c as char)))
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
fn parse_value(&mut self) -> Result<Json, String> {
|
|
137
|
-
self.skip_ws();
|
|
138
|
-
match self.peek() {
|
|
139
|
-
Some(b'{') => self.parse_object(),
|
|
140
|
-
Some(b'[') => self.parse_array(),
|
|
141
|
-
Some(b'"') => Ok(Json::String(self.parse_string()?)),
|
|
142
|
-
Some(b't') => {
|
|
143
|
-
self.expect_literal("true")?;
|
|
144
|
-
Ok(Json::Bool(true))
|
|
145
|
-
}
|
|
146
|
-
Some(b'f') => {
|
|
147
|
-
self.expect_literal("false")?;
|
|
148
|
-
Ok(Json::Bool(false))
|
|
149
|
-
}
|
|
150
|
-
Some(b'n') => {
|
|
151
|
-
self.expect_literal("null")?;
|
|
152
|
-
Ok(Json::Null)
|
|
153
|
-
}
|
|
154
|
-
Some(c) if c == b'-' || c.is_ascii_digit() => self.parse_number(),
|
|
155
|
-
other => Err(format!("unexpected byte {:?} at {}", other.map(|c| c as char), self.pos)),
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
fn expect_literal(&mut self, lit: &str) -> Result<(), String> {
|
|
160
|
-
let end = self.pos + lit.len();
|
|
161
|
-
if end <= self.bytes.len() && &self.bytes[self.pos..end] == lit.as_bytes() {
|
|
162
|
-
self.pos = end;
|
|
163
|
-
Ok(())
|
|
164
|
-
} else {
|
|
165
|
-
Err(format!("expected literal {lit:?} at byte {}", self.pos))
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
fn parse_object(&mut self) -> Result<Json, String> {
|
|
170
|
-
self.expect(b'{')?;
|
|
171
|
-
let mut pairs = Vec::new();
|
|
172
|
-
self.skip_ws();
|
|
173
|
-
if self.peek() == Some(b'}') {
|
|
174
|
-
self.pos += 1;
|
|
175
|
-
return Ok(Json::Object(pairs));
|
|
176
|
-
}
|
|
177
|
-
loop {
|
|
178
|
-
self.skip_ws();
|
|
179
|
-
let key = self.parse_string()?;
|
|
180
|
-
self.skip_ws();
|
|
181
|
-
self.expect(b':')?;
|
|
182
|
-
let value = self.parse_value()?;
|
|
183
|
-
pairs.push((key, value));
|
|
184
|
-
self.skip_ws();
|
|
185
|
-
match self.peek() {
|
|
186
|
-
Some(b',') => {
|
|
187
|
-
self.pos += 1;
|
|
188
|
-
}
|
|
189
|
-
Some(b'}') => {
|
|
190
|
-
self.pos += 1;
|
|
191
|
-
break;
|
|
192
|
-
}
|
|
193
|
-
other => return Err(format!("expected ',' or '}}' at byte {}, found {:?}", self.pos, other.map(|c| c as char))),
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
Ok(Json::Object(pairs))
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
fn parse_array(&mut self) -> Result<Json, String> {
|
|
200
|
-
self.expect(b'[')?;
|
|
201
|
-
let mut items = Vec::new();
|
|
202
|
-
self.skip_ws();
|
|
203
|
-
if self.peek() == Some(b']') {
|
|
204
|
-
self.pos += 1;
|
|
205
|
-
return Ok(Json::Array(items));
|
|
206
|
-
}
|
|
207
|
-
loop {
|
|
208
|
-
let value = self.parse_value()?;
|
|
209
|
-
items.push(value);
|
|
210
|
-
self.skip_ws();
|
|
211
|
-
match self.peek() {
|
|
212
|
-
Some(b',') => {
|
|
213
|
-
self.pos += 1;
|
|
214
|
-
}
|
|
215
|
-
Some(b']') => {
|
|
216
|
-
self.pos += 1;
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
|
-
other => return Err(format!("expected ',' or ']' at byte {}, found {:?}", self.pos, other.map(|c| c as char))),
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
Ok(Json::Array(items))
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
fn parse_string(&mut self) -> Result<String, String> {
|
|
226
|
-
self.expect(b'"')?;
|
|
227
|
-
let mut out = String::new();
|
|
228
|
-
loop {
|
|
229
|
-
match self.peek() {
|
|
230
|
-
None => return Err("unterminated string".to_string()),
|
|
231
|
-
Some(b'"') => {
|
|
232
|
-
self.pos += 1;
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
Some(b'\\') => {
|
|
236
|
-
self.pos += 1;
|
|
237
|
-
match self.peek() {
|
|
238
|
-
Some(b'"') => {
|
|
239
|
-
out.push('"');
|
|
240
|
-
self.pos += 1;
|
|
241
|
-
}
|
|
242
|
-
Some(b'\\') => {
|
|
243
|
-
out.push('\\');
|
|
244
|
-
self.pos += 1;
|
|
245
|
-
}
|
|
246
|
-
Some(b'/') => {
|
|
247
|
-
out.push('/');
|
|
248
|
-
self.pos += 1;
|
|
249
|
-
}
|
|
250
|
-
Some(b'n') => {
|
|
251
|
-
out.push('\n');
|
|
252
|
-
self.pos += 1;
|
|
253
|
-
}
|
|
254
|
-
Some(b't') => {
|
|
255
|
-
out.push('\t');
|
|
256
|
-
self.pos += 1;
|
|
257
|
-
}
|
|
258
|
-
Some(b'r') => {
|
|
259
|
-
out.push('\r');
|
|
260
|
-
self.pos += 1;
|
|
261
|
-
}
|
|
262
|
-
Some(b'b') => {
|
|
263
|
-
out.push('\u{8}');
|
|
264
|
-
self.pos += 1;
|
|
265
|
-
}
|
|
266
|
-
Some(b'f') => {
|
|
267
|
-
out.push('\u{c}');
|
|
268
|
-
self.pos += 1;
|
|
269
|
-
}
|
|
270
|
-
Some(b'u') => {
|
|
271
|
-
self.pos += 1;
|
|
272
|
-
let hex = std::str::from_utf8(&self.bytes[self.pos..self.pos + 4]).map_err(|e| e.to_string())?;
|
|
273
|
-
let code = u32::from_str_radix(hex, 16).map_err(|e| e.to_string())?;
|
|
274
|
-
self.pos += 4;
|
|
275
|
-
if let Some(c) = char::from_u32(code) {
|
|
276
|
-
out.push(c);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
other => return Err(format!("bad escape {:?}", other.map(|c| c as char))),
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
Some(_) => {
|
|
283
|
-
// One UTF-8 char at a time so multi-byte text survives.
|
|
284
|
-
let start = self.pos;
|
|
285
|
-
let rest = std::str::from_utf8(&self.bytes[start..]).map_err(|e| e.to_string())?;
|
|
286
|
-
let ch = rest.chars().next().ok_or("empty remainder")?;
|
|
287
|
-
out.push(ch);
|
|
288
|
-
self.pos += ch.len_utf8();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
Ok(out)
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Keeps the raw literal text, so numbers round-trip unchanged.
|
|
296
|
-
fn parse_number(&mut self) -> Result<Json, String> {
|
|
297
|
-
let start = self.pos;
|
|
298
|
-
if self.peek() == Some(b'-') {
|
|
299
|
-
self.pos += 1;
|
|
300
|
-
}
|
|
301
|
-
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
302
|
-
self.pos += 1;
|
|
303
|
-
}
|
|
304
|
-
if self.peek() == Some(b'.') {
|
|
305
|
-
self.pos += 1;
|
|
306
|
-
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
307
|
-
self.pos += 1;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if matches!(self.peek(), Some(b'e') | Some(b'E')) {
|
|
311
|
-
self.pos += 1;
|
|
312
|
-
if matches!(self.peek(), Some(b'+') | Some(b'-')) {
|
|
313
|
-
self.pos += 1;
|
|
314
|
-
}
|
|
315
|
-
while matches!(self.peek(), Some(c) if c.is_ascii_digit()) {
|
|
316
|
-
self.pos += 1;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
let text = std::str::from_utf8(&self.bytes[start..self.pos]).map_err(|e| e.to_string())?;
|
|
320
|
-
Ok(Json::Number(text.to_string()))
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/// Renders `value` exactly as `JSON.pretty_generate` does for the pinned json gem.
|
|
325
|
-
pub fn write(value: &Json) -> String {
|
|
326
|
-
let mut out = String::new();
|
|
327
|
-
write_value(&mut out, value, 0);
|
|
328
|
-
out
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
fn indent(out: &mut String, depth: usize) {
|
|
332
|
-
for _ in 0..depth {
|
|
333
|
-
out.push_str(" ");
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
fn write_value(out: &mut String, value: &Json, depth: usize) {
|
|
338
|
-
match value {
|
|
339
|
-
Json::Null => out.push_str("null"),
|
|
340
|
-
Json::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
|
|
341
|
-
Json::Number(n) => out.push_str(n),
|
|
342
|
-
Json::String(s) => write_string(out, s),
|
|
343
|
-
Json::Array(items) => write_array(out, items, depth),
|
|
344
|
-
Json::Object(pairs) => write_object(out, pairs, depth),
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
fn write_string(out: &mut String, text: &str) {
|
|
349
|
-
out.push('"');
|
|
350
|
-
for ch in text.chars() {
|
|
351
|
-
match ch {
|
|
352
|
-
'"' => out.push_str("\\\""),
|
|
353
|
-
'\\' => out.push_str("\\\\"),
|
|
354
|
-
'\n' => out.push_str("\\n"),
|
|
355
|
-
'\t' => out.push_str("\\t"),
|
|
356
|
-
'\r' => out.push_str("\\r"),
|
|
357
|
-
c if (c as u32) < 0x20 => {
|
|
358
|
-
let _ = write!(out, "\\u{:04x}", c as u32);
|
|
359
|
-
}
|
|
360
|
-
c => out.push(c),
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
out.push('"');
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
fn write_array(out: &mut String, items: &[Json], depth: usize) {
|
|
367
|
-
if items.is_empty() {
|
|
368
|
-
// Empty arrays render with a blank line, matching the pinned json gem.
|
|
369
|
-
out.push_str("[\n\n");
|
|
370
|
-
indent(out, depth);
|
|
371
|
-
out.push(']');
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
out.push_str("[\n");
|
|
375
|
-
for (idx, item) in items.iter().enumerate() {
|
|
376
|
-
indent(out, depth + 1);
|
|
377
|
-
write_value(out, item, depth + 1);
|
|
378
|
-
if idx + 1 < items.len() {
|
|
379
|
-
out.push(',');
|
|
380
|
-
}
|
|
381
|
-
out.push('\n');
|
|
382
|
-
}
|
|
383
|
-
indent(out, depth);
|
|
384
|
-
out.push(']');
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
fn write_object(out: &mut String, pairs: &[(String, Json)], depth: usize) {
|
|
388
|
-
// An empty object needs no special case: the loop runs zero times.
|
|
389
|
-
out.push_str("{\n");
|
|
390
|
-
for (idx, (key, val)) in pairs.iter().enumerate() {
|
|
391
|
-
indent(out, depth + 1);
|
|
392
|
-
write_string(out, key);
|
|
393
|
-
out.push_str(": ");
|
|
394
|
-
write_value(out, val, depth + 1);
|
|
395
|
-
if idx + 1 < pairs.len() {
|
|
396
|
-
out.push(',');
|
|
397
|
-
}
|
|
398
|
-
out.push('\n');
|
|
399
|
-
}
|
|
400
|
-
indent(out, depth);
|
|
401
|
-
out.push('}');
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
#[cfg(test)]
|
|
405
|
-
mod tests {
|
|
406
|
-
use super::*;
|
|
407
|
-
|
|
408
|
-
#[test]
|
|
409
|
-
fn round_trips_an_empty_object() {
|
|
410
|
-
let text = "{\n}";
|
|
411
|
-
let value = Json::parse(text).expect("parses");
|
|
412
|
-
assert_eq!(write(&value), text);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
#[test]
|
|
416
|
-
fn set_bool_overwrites_an_existing_key() {
|
|
417
|
-
let mut value = Json::parse("{\n \"optional\": false\n}").expect("parses");
|
|
418
|
-
value.set_bool("optional", true);
|
|
419
|
-
assert_eq!(write(&value), "{\n \"optional\": true\n}");
|
|
420
|
-
}
|
|
421
|
-
}
|