canon 0.3.117 → 0.3.119
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/CLAUDE.md +4 -4
- data/Rakefile +0 -40
- data/docs/HANDOFF.adoc +255 -0
- data/lib/canon/version.rb +1 -1
- metadata +9 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 21b508095633774da379c4f7c13cfaeabce997fbdb400139e7ecf7aedbf3df95
|
|
4
|
+
data.tar.gz: 9528d6c70d4b84f43bf77e5ca7b30a4bbf2ee8f3a172a010d0c6ea90228a9c75
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2de6ab858f2c4ca1ba6b83cad30058af17c2427e9688b13babde2bc249fdf5234d453575c36956b5edc2b343c4876647439b8d604bc5a3bcb96c746759c31a86
|
|
7
|
+
data.tar.gz: 51ac169753e93464ff16be5e869f0d157c1dcc0446311551322fcd19ee120a38a94d5581db9f167436f1d6ed8461b4fedff2899dd1d3fd12b32ac68957521b23
|
data/CLAUDE.md
CHANGED
|
@@ -128,18 +128,18 @@ The comparison pipeline flows through four independent layers:
|
|
|
128
128
|
- `lib/canon/formatters/` — Pretty-printers for canonicalization/formatting (distinct from diff formatters). `XmlFormatter` supports Canonical XML (C14N).
|
|
129
129
|
- `lib/canon/config.rb` — Global configuration with per-format settings (profiles, preprocessing, diff options). Read at runtime via `Canon::Config.instance`.
|
|
130
130
|
- `lib/canon/rspec_matchers.rb` — RSpec matchers (`be_xml_equivalent_to`, `be_json_equivalent_to`, etc.). These delegate to `Canon::Comparison.equivalent?` with the global config. Automatically included in RSpec.
|
|
131
|
-
- `lib/canon/xml/sax_builder.rb` — SAX-based canon-tree builder (~6x faster than DOM parsing for large documents). Engine-neutral; `lib/canon/xml/sax.rb` selects the driver following the resolved adapter (`MoxmlDriver` → leptris SAX under the leptris default, `NokogiriDriver` when the adapter is nokogiri
|
|
131
|
+
- `lib/canon/xml/sax_builder.rb` — SAX-based canon-tree builder (~6x faster than DOM parsing for large documents). Engine-neutral; `lib/canon/xml/sax.rb` selects the driver following the resolved adapter (`MoxmlDriver` → leptris SAX under the leptris default, `NokogiriDriver` when the adapter is nokogiri).
|
|
132
132
|
|
|
133
133
|
### XML Engines
|
|
134
134
|
|
|
135
135
|
Canon is engine-agnostic across three seams (MECE — one concern per module):
|
|
136
136
|
|
|
137
|
-
- `Canon::XmlBackend` — XML engine selection. The default follows moxml's resolved adapter: **leptris whenever it is installed** (parse ~1.6x, serialize ~3.8x vs Nokogiri), raw Nokogiri otherwise (wrapping Nokogiri in moxml buys nothing — the wrapper adds 2-3x overhead).
|
|
137
|
+
- `Canon::XmlBackend` — XML engine selection. The default follows moxml's resolved adapter: **leptris whenever it is installed** (parse ~1.6x, serialize ~3.8x vs Nokogiri), raw Nokogiri otherwise (wrapping Nokogiri in moxml buys nothing — the wrapper adds 2-3x overhead). Opal is retired (moxml 0.6 deleted the Opal surface, lutaml/moxml#516; the forward path is the moxml-ts wasm binding, lutaml/moxml#489). `CANON_XML_BACKEND=nokogiri|moxml` forces either engine.
|
|
138
138
|
- `Canon::XmlParsing` — the only place that talks to engines for XML parse/serialize (moxml parses pass `readonly: true` — canon never mutates engine documents); node type queries answer for ANY recognized node (Nokogiri or moxml) by type, never by active backend — user-supplied Nokogiri nodes keep working under the moxml engine.
|
|
139
139
|
- `Canon::Html::NokogiriSupport` — HTML engine seam. **HTML is engine-served end-to-end** since 0.3.86-0.3.101: `HtmlParser.parse` routes through moxml `Context#parse_html_fragment` (WHATWG fragment parsing, moxml#353 riding leptris) and builds a Canon tree via the materialize-records fast path — whitespace text nodes survive the parse unconditionally (HTML whitespace significance is the comparison profile's decision, #112/#137), and `parse_node` walks Canon trees directly. The semantic lane's `DataModel.from_html`, the `:format` string normalizer, the canonical HTML formatters, `format_html`'s default/XHTML display modes, and `validate_xhtml!` are all engine-served (0.3.99/0.3.100/0.3.101) — **HTML comparison and formatting run nokogiri-less** (pinned by the optionality contract spec). The Nokogiri HTML fragment path remains only for runtimes without an engine HTML adapter and for user-supplied Nokogiri nodes. Nokogiri's residual roles: the `fixture_ready` display mode (libxml FORMAT|AS_XHTML — moxml#390 filed for an engine XHTML mode), the HTML5 validation lint layer (gumbo error-level classification — leptris#1771 filed), and the fragment-records lane once delivered nil URIs for prefixed attributes (moxml#367, fixed in moxml 0.5.130 — the bulk read now falls back to the reserved-prefix table); the TreeBuilder keeps the one legal `xml`-prefix binding as standing defense.
|
|
140
|
-
- `Canon::Xml::Sax` — SAX driver selection follows the resolved adapter: `MoxmlDriver` (leptris SAX — the comparison hot path, CI-gated in the split flip) under the leptris default, `NokogiriDriver` when the resolved adapter is nokogiri
|
|
140
|
+
- `Canon::Xml::Sax` — SAX driver selection follows the resolved adapter: `MoxmlDriver` (leptris SAX — the comparison hot path, CI-gated in the split flip) under the leptris default, `NokogiriDriver` when the resolved adapter is nokogiri. The builder (`SaxBuilder`) is engine-neutral.
|
|
141
141
|
|
|
142
|
-
Engine parity is complete through libleptris 1.9.8 / leptris-ruby 1.9.33 / moxml 0.5.12: attribute-value normalization, prolog/epilog PIs and comments, DTD ATTLIST defaults off by default (opt-in via `ParseOptions::DTDATTR`), PI-data whitespace matching libxml2, materialize with namespace declarations and a root-subtree-only record contract (moxml#140), readonly parse, deterministic `Document#free` (wired into `from_moxml_xml` — moxml#134). Canon's moxml conversion is record-based (`build_from_moxml` consumes `materialize` records — no per-node wrapper allocation; ~0.55x the Nokogiri conversion). `spec/canon/xml/engine_parity_spec.rb` is fully green. Pretty-printing runs the leptris serializer through `PrettyPrinter::Xml#moxml_format` (byte parity via moxml#153/#155/#156; the #167 escaping race fixed in 0.5.28), with Nokogiri serving the fallback engine
|
|
142
|
+
Engine parity is complete through libleptris 1.9.8 / leptris-ruby 1.9.33 / moxml 0.5.12: attribute-value normalization, prolog/epilog PIs and comments, DTD ATTLIST defaults off by default (opt-in via `ParseOptions::DTDATTR`), PI-data whitespace matching libxml2, materialize with namespace declarations and a root-subtree-only record contract (moxml#140), readonly parse, deterministic `Document#free` (wired into `from_moxml_xml` — moxml#134). Canon's moxml conversion is record-based (`build_from_moxml` consumes `materialize` records — no per-node wrapper allocation; ~0.55x the Nokogiri conversion). `spec/canon/xml/engine_parity_spec.rb` is fully green. Pretty-printing runs the leptris serializer through `PrettyPrinter::Xml#moxml_format` (byte parity via moxml#153/#155/#156; the #167 escaping race fixed in 0.5.28), with Nokogiri serving the fallback engine — pretty-printed bytes are canon's product, gated by the fixture-integrity suite and the CI performance gate.
|
|
143
143
|
|
|
144
144
|
Engine A/B testing: `CANON_XML_BACKEND=nokogiri bundle exec rspec` (or `=moxml` to force leptris when it isn't the resolved default). The default suite must stay green under BOTH values; the only expected pendings are the upstream-tracked ones. The benchmark header (`rake performance:quick`) reports the active engine.
|
|
145
145
|
|
data/Rakefile
CHANGED
|
@@ -5,50 +5,10 @@ require "rspec/core/rake_task"
|
|
|
5
5
|
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
|
8
|
-
begin
|
|
9
|
-
require "opal/rspec/rake_task"
|
|
10
|
-
|
|
11
|
-
# Configure Opal load paths at load time (same pattern as moxml)
|
|
12
|
-
if defined?(Opal)
|
|
13
|
-
Opal.append_path File.expand_path("lib", __dir__)
|
|
14
|
-
|
|
15
|
-
# moxml gem
|
|
16
|
-
begin
|
|
17
|
-
moxml_spec = Gem::Specification.find_by_name("moxml")
|
|
18
|
-
moxml_lib = moxml_spec.full_require_paths.first
|
|
19
|
-
Opal.append_path moxml_lib
|
|
20
|
-
moxml_compat = File.expand_path("compat/opal", moxml_lib)
|
|
21
|
-
Opal.append_path moxml_compat if File.directory?(moxml_compat)
|
|
22
|
-
rescue Gem::MissingSpecError
|
|
23
|
-
# moxml not installed
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# REXML: bundled gem since Ruby 3.4
|
|
27
|
-
rexml_lib = $LOAD_PATH.find do |p|
|
|
28
|
-
File.exist?(File.join(p, "rexml", "document.rb"))
|
|
29
|
-
end
|
|
30
|
-
Opal.append_path rexml_lib if rexml_lib
|
|
31
|
-
end
|
|
32
|
-
rescue LoadError
|
|
33
|
-
# Opal not available or incompatible with current Ruby version
|
|
34
|
-
end
|
|
35
|
-
|
|
36
8
|
require "rubocop/rake_task"
|
|
37
9
|
|
|
38
10
|
RuboCop::RakeTask.new
|
|
39
11
|
|
|
40
12
|
Dir.glob("lib/tasks/**/*.rake").each { |r| load r }
|
|
41
13
|
|
|
42
|
-
namespace :spec do
|
|
43
|
-
if defined?(Opal::RSpec::RakeTask)
|
|
44
|
-
desc "Run Opal (JavaScript) tests"
|
|
45
|
-
Opal::RSpec::RakeTask.new(:opal) do |_server, runner|
|
|
46
|
-
runner.default_path = "spec"
|
|
47
|
-
runner.requires = %w[rexml_compat rexml/document rexml/xpath
|
|
48
|
-
moxml moxml/adapter/rexml spec_helper]
|
|
49
|
-
runner.pattern = "spec/canon/opal_xml_smoke_spec.rb"
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
14
|
task default: %i[spec rubocop]
|
data/docs/HANDOFF.adoc
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
---
|
|
2
|
+
published: false
|
|
3
|
+
---
|
|
4
|
+
= Cross-team handoff: the engine issue board
|
|
5
|
+
|
|
6
|
+
A snapshot of the open arcs across the org repos — what is known, where
|
|
7
|
+
to dig, and what has already been proven — so any team can pick an issue
|
|
8
|
+
up cold. Statuses as of 2026-11-01.
|
|
9
|
+
|
|
10
|
+
== State of the world
|
|
11
|
+
|
|
12
|
+
Shipped since the last board (2026-10-28): leptris 1.9.398.0 (the
|
|
13
|
+
#1866 adopt + parent-of-attribute fixes and the #1846/#1854/#1855 perf
|
|
14
|
+
slices), yeptris 0.6.52.0/0.6.53.0 (marshal reader #322, multibyte
|
|
15
|
+
breaks #782), moxml **0.6.0** (the Opal surface deleted by the owner's
|
|
16
|
+
phase-4 call, lutaml/moxml#516 — the forward Opal path is the moxml-ts
|
|
17
|
+
wasm binding, lutaml/moxml#489), lutaml-model 0.8.155 (admits both
|
|
18
|
+
moxml lines: `>= 0.5.139, < 0.7`), canon 0.3.118 (floors `leptris ~>
|
|
19
|
+
1.9.398`, `yeptris ~> 0.6.52`, `moxml ~> 0.6.0`; Opal lane retired).
|
|
20
|
+
|
|
21
|
+
== lutaml/canon
|
|
22
|
+
|
|
23
|
+
[cols="1,1,2"]
|
|
24
|
+
|===
|
|
25
|
+
|Item |Status |Known + first moves
|
|
26
|
+
|
|
27
|
+
|Floors raised (0.3.118)
|
|
28
|
+
|Shipped
|
|
29
|
+
|`leptris ~> 1.9.398`, `yeptris ~> 0.6.52`, `moxml ~> 0.6.0` — all
|
|
30
|
+
verified against exactly those engines (2744 examples, 0 failures, 25
|
|
31
|
+
pending). Constraints live in the gemspec only; Gemfile/Gemfile.local
|
|
32
|
+
are untracked verification lanes.
|
|
33
|
+
|
|
34
|
+
|Opal lane
|
|
35
|
+
|Retired
|
|
36
|
+
|moxml 0.6 deleted the Opal surface (moxml#516), so canon's opal
|
|
37
|
+
workflow, `spec:opal` task, `:opal` group, and smoke spec are gone.
|
|
38
|
+
The `RUBY_ENGINE == "opal"` branches in lib stay for the moxml-ts wasm
|
|
39
|
+
migration (moxml#489).
|
|
40
|
+
|
|
41
|
+
|Subset-xpath mini engine (`lib/canon/xml/xpath_engine.rb`)
|
|
42
|
+
|Reported, owner decision pending
|
|
43
|
+
|It silently returns `[]` for `..` and `@attr` step forms (XPath 1.0
|
|
44
|
+
§2.2 names the owner element). No `lib/` caller uses those forms today
|
|
45
|
+
(swept 2026-10-28); decide between implementing the steps and
|
|
46
|
+
documenting/raising on unsupported forms.
|
|
47
|
+
|===
|
|
48
|
+
|
|
49
|
+
== lutaml/moxml
|
|
50
|
+
|
|
51
|
+
All three canon-filed engine issues are CLOSED by the moxml team —
|
|
52
|
+
#474 (parent-of-attribute through the Ruby engine), #472
|
|
53
|
+
(attribute-existence predicate segfault), #473 (unbounded occurrence
|
|
54
|
+
products at XSD compile). Nothing to pick up here; re-file against
|
|
55
|
+
moxml 0.6.x if the metanorma-standoc svg lanes regress.
|
|
56
|
+
|
|
57
|
+
== leptris/leptris
|
|
58
|
+
|
|
59
|
+
[cols="1,1,2"]
|
|
60
|
+
|===
|
|
61
|
+
|Issue |Status |Known + first moves
|
|
62
|
+
|
|
63
|
+
|leptris#1866 — cross-doc replace + `@id/..` + serialize
|
|
64
|
+
|CLOSED (v1.9.385, #1869)
|
|
65
|
+
|Shipped: the adopt copy's attribute-tail resync
|
|
66
|
+
(`copy_subtree_detached`, `src/leptris/dom/element_modify.c`) and the
|
|
67
|
+
evaluator-path parent-of-attribute (`apply_axis`,
|
|
68
|
+
`src/leptris/xpath/evaluator_axes.c`).
|
|
69
|
+
|
|
70
|
+
|leptris#1846/#1854/#1855 — the parse-allocator, pointer-emission, and
|
|
71
|
+
plan-path-FFI perf slices
|
|
72
|
+
|CLOSED (through v1.9.398)
|
|
73
|
+
|All three slices landed; the umbrella gap moved accordingly.
|
|
74
|
+
|
|
75
|
+
|leptris#1842 — C-face XML parse/gen/xpath vs pugixml
|
|
76
|
+
|Open (umbrella)
|
|
77
|
+
|Re-baseline against 1.9.398 with the interleaved A/B harness before
|
|
78
|
+
opening new slices — the old ~3-4x numbers predate the closed slices.
|
|
79
|
+
|===
|
|
80
|
+
|
|
81
|
+
== leptris/yeptris
|
|
82
|
+
|
|
83
|
+
[cols="1,1,2"]
|
|
84
|
+
|===
|
|
85
|
+
|Issue |Status |Known + first moves
|
|
86
|
+
|
|
87
|
+
|yeptris#739 — JSON parse 2x behind yyjson
|
|
88
|
+
|Open
|
|
89
|
+
|The 12x WRITE gap is closed (serialize 16->221 MB/s: the one-pass
|
|
90
|
+
route, the run-batched `emit_dq_json` SWAR scan, the `emit_json_value`
|
|
91
|
+
walker). Parse remains; profile with the counting-malloc interposer.
|
|
92
|
+
|
|
93
|
+
|yeptris#742 — YAML emit ~1.5x behind rapidyaml; CBOR decode 1.3-2.2x
|
|
94
|
+
behind tinycbor
|
|
95
|
+
|Open
|
|
96
|
+
|13-leg matrix. The emit side shares machinery with the closed #739
|
|
97
|
+
write work — reuse the walker patterns.
|
|
98
|
+
|
|
99
|
+
|yeptris#474 — `parse_json_tape` 0.61x vs simdjson on arm64 (ubuntu
|
|
100
|
+
1.07x, same binary)
|
|
101
|
+
|Open
|
|
102
|
+
|Platform-specific: diff the arm64 SIMD kernels vs the scalar fallback
|
|
103
|
+
(`src/yeptris/common/simd_text*`), starting from the kernel-selection
|
|
104
|
+
law.
|
|
105
|
+
|
|
106
|
+
|yeptris#352 — yaml generation 1.4-1.7x behind rapidyaml (10/12
|
|
107
|
+
platforms)
|
|
108
|
+
|Open, partially improved
|
|
109
|
+
|Remaining: scalar-route derivation cost. `benchmarks/PERF-LEDGER.md`
|
|
110
|
+
has the trusted-into entries.
|
|
111
|
+
|===
|
|
112
|
+
|
|
113
|
+
== leptris/yeptris-ruby
|
|
114
|
+
|
|
115
|
+
[cols="1,1,2"]
|
|
116
|
+
|===
|
|
117
|
+
|Issue |Status |Known + first moves
|
|
118
|
+
|
|
119
|
+
|yeptris-ruby#322 — dump face is marshaling-bound
|
|
120
|
+
|CLOSED
|
|
121
|
+
|The marshal face shipped (4.4x end-to-end, yeptris 0.6.47/0.6.48; the
|
|
122
|
+
reader's REGISTRY LAW pinned in `test/unit/test_marshal_json.cpp`).
|
|
123
|
+
If the CBOR face reopens, copy the registry law and its pin wholesale.
|
|
124
|
+
|===
|
|
125
|
+
|
|
126
|
+
== lutaml/lutaml-model and the dependent legs
|
|
127
|
+
|
|
128
|
+
[cols="1,1,2"]
|
|
129
|
+
|===
|
|
130
|
+
|Item |Status |Known + first moves
|
|
131
|
+
|
|
132
|
+
|moxml 0.6 admission
|
|
133
|
+
|Shipped (0.8.155)
|
|
134
|
+
|`>= 0.5.139, < 0.7`; the Opal boot lane pins moxml 0.5.x locally in
|
|
135
|
+
`opal.yml` (Gemfile-append + plain `bundle update moxml` — bundler 4
|
|
136
|
+
removed `update --version`) until the moxml-ts wasm migration.
|
|
137
|
+
|
|
138
|
+
|update-baselines red on every main push
|
|
139
|
+
|PR lutaml-model#1076
|
|
140
|
+
|checkout's persisted Authorization extraheader collides with
|
|
141
|
+
create-pull-request's token ("Duplicate header: Authorization", HTTP
|
|
142
|
+
400) on the action's `git remote prune`. Fix: `persist-credentials:
|
|
143
|
+
false` on that job's checkout (the documented pairing).
|
|
144
|
+
|
|
145
|
+
|metanorma/docbook dependent leg (ubuntu/macos)
|
|
146
|
+
|PR metanorma/docbook#15
|
|
147
|
+
|ferrum 0.20 rejects `file://` at boot (`parse_base_url` is
|
|
148
|
+
http/https-only); docbook's `Capybara.app_host = "file://"` died in a
|
|
149
|
+
`before(:suite)` hook with zero examples run (windows skips the boot).
|
|
150
|
+
Fix: loopback http app_host placeholder; the specs visit absolute
|
|
151
|
+
file:// URLs directly. Same PR carries the pre-existing rubocop debt
|
|
152
|
+
that failed docbook's own rake lane (dead `custom_data` captures).
|
|
153
|
+
|
|
154
|
+
|ukiryu dependent leg (macos)
|
|
155
|
+
|Transient — resolved
|
|
156
|
+
|`bundle add lutaml-model` exit 7: the runner's rubygems compact index
|
|
157
|
+
had not propagated yeptris 0.6.53.0 (released hours earlier; the
|
|
158
|
+
version EXISTS with full platform coverage). Passed on the next
|
|
159
|
+
dependent run.
|
|
160
|
+
|
|
161
|
+
|glossarist/iev dependent legs (all OSes) + iev's own rake lane
|
|
162
|
+
|RESOLVED (2026-11-01)
|
|
163
|
+
|The republished `plurimath 0.10.0` (sha `7b870bf0...`) required
|
|
164
|
+
`mml/configuration` at line 2 — an API no mml version ships; iev's
|
|
165
|
+
silent LoadError rescue turned that into 21x
|
|
166
|
+
`uninitialized constant Plurimath::Math` (diag: glossarist/iev#75,
|
|
167
|
+
filed as plurimath/plurimath#528). Fixed by the org-wide moxml-0.6
|
|
168
|
+
update (below): plurimath 0.10.0 yanked, omml released with
|
|
169
|
+
`moxml ~> 0.6.0`, so 0.11.12 resolves again. Full iev suite green
|
|
170
|
+
(489/0) on canon 0.3.118 + moxml 0.6.1 + omml 0.2.8 +
|
|
171
|
+
lutaml-model 0.8.156. iev#75 (the diag) is revert-on-sight.
|
|
172
|
+
|
|
173
|
+
**Gotcha for any release: a YANKED VERSION NUMBER STAYS INVISIBLE to
|
|
174
|
+
bundler's resolution index even after re-pushing the same number** —
|
|
175
|
+
omml 0.2.7 published, yanked, re-pushed identically, and bundler
|
|
176
|
+
still could not see it. Always release a FRESH patch number after a
|
|
177
|
+
yank (0.2.8).
|
|
178
|
+
|
|
179
|
+
|The org-wide moxml 0.6 sweep (owner call, 2026-11-01)
|
|
180
|
+
|Shipped
|
|
181
|
+
|Every org gem now rides the moxml 0.6 line: canon 0.3.118
|
|
182
|
+
(`~> 0.6.0`), omml 0.2.8, dcc 0.2.2, metanorma-standoc 3.5.5,
|
|
183
|
+
relaton 3.0.4, expressir (admits), lutaml-model 0.8.156 (admits
|
|
184
|
+
`< 0.7`), mml (unpinned). lutaml-xsd: owner PRs #214/#215. iev's
|
|
185
|
+
suite is the executable proof: 489/0 on the resolved modern stack.
|
|
186
|
+
|
|
187
|
+
|metanorma-standoc legs: parsanol 1.3.120 removed the `mode` alias
|
|
188
|
+
|Open — relaton-chain grammar follow-up
|
|
189
|
+
|`Parsanol::PARG::ParseError: the grammar header keyword is edition;
|
|
190
|
+
mode (the pre-1.3.113 alias) was removed` fires in
|
|
191
|
+
`@bibdb.fetch_async` (relaton bibdb chain) on standoc's fresh
|
|
192
|
+
resolutions. Some grammar file still says `mode`; move it to
|
|
193
|
+
`edition "v1"` / `edition "v2"` per the parsanol message. Separate
|
|
194
|
+
from moxml entirely.
|
|
195
|
+
|===
|
|
196
|
+
|
|
197
|
+
== Mechanics every team hits
|
|
198
|
+
|
|
199
|
+
[cols="1,3"]
|
|
200
|
+
|===
|
|
201
|
+
|Topic |The law
|
|
202
|
+
|
|
203
|
+
|Differential corpora
|
|
204
|
+
|Random-tree corpora never produce repeated keys or shared references —
|
|
205
|
+
shift/registration bugs survive 300/300 "green". Include linked shapes
|
|
206
|
+
(users-style rows). Lock byte-level fixtures to FILES (Ruby's fstring
|
|
207
|
+
interning varies per process).
|
|
208
|
+
|
|
209
|
+
|Performance claims
|
|
210
|
+
|Cross-wave serialbench comparison is INVALID (runner noise; pugixml
|
|
211
|
+
swung 1.7x between waves). Only within-run interleaved A/B on fresh
|
|
212
|
+
binaries counts. The perf gate is best-of-N per side.
|
|
213
|
+
|
|
214
|
+
|Release cuts (canon)
|
|
215
|
+
|`gh workflow run release.yml -f next_version=patch` (patch only; new
|
|
216
|
+
minors/majors are the owner's stated call). The gem bump is committed
|
|
217
|
+
by the workflow. Gemfile.lock is gitignored — CI resolves fresh from
|
|
218
|
+
the gemspec, so constraint PRs are gemspec-only.
|
|
219
|
+
|
|
220
|
+
|Release cuts (yeptris)
|
|
221
|
+
|`next_version` must be a LITERAL X.Y.Z. The release PR self-closes ~2
|
|
222
|
+
min after cut if checks never start: push a PARENTED trigger commit
|
|
223
|
+
(`git commit-tree -p "$sha" -m ... "$sha^{tree}"` — without `-p` the
|
|
224
|
+
commit orphans and the PR creation fails) within the window, then
|
|
225
|
+
approve runs gated at `conclusion == "action_required"` (the `status`
|
|
226
|
+
field reads `completed` while gated). The changelog gate requires an
|
|
227
|
+
`## [Unreleased]` section before EVERY cut, version-only ones included.
|
|
228
|
+
|
|
229
|
+
|Release cuts (yeptris-ruby)
|
|
230
|
+
|RELEASE_TOKEN unset -> the bump job's 60-min wait step always fails;
|
|
231
|
+
the PR opens anyway. Hand-merge on green, then dispatch the republish
|
|
232
|
+
with EMPTY next_version (reuses main's VERSION). A new gem version needs
|
|
233
|
+
its C `v<c_semver>` tag to EXIST first (platform legs vendor from it).
|
|
234
|
+
|
|
235
|
+
|Release cuts (leptris)
|
|
236
|
+
|The same cut/trigger/approve cycle; the Unreleased section exists on
|
|
237
|
+
main — keep it fed.
|
|
238
|
+
|
|
239
|
+
|Dependent legs (rake-with-tools)
|
|
240
|
+
|They run each downstream repo at its own main against lutaml-model's
|
|
241
|
+
branch — a red leg is usually the DOWNSTREAM repo's bug (ferrum boot,
|
|
242
|
+
stale locks), not lutaml-model's. Diagnose in the downstream repo and
|
|
243
|
+
PR there.
|
|
244
|
+
|
|
245
|
+
|Formatting
|
|
246
|
+
|The repos target clang-format 14+ (CI runs LLVM 18); local 11.1/22.1
|
|
247
|
+
both reject the config — the CI format job is the gate.
|
|
248
|
+
|
|
249
|
+
|CI flakes
|
|
250
|
+
|`pull_request` events intermittently vanish for fresh PRs (yeptris,
|
|
251
|
+
leptris). Fallback: `gh workflow run test.yml format.yml asan.yml --ref
|
|
252
|
+
<branch>` — sha-keyed check runs satisfy required-context protection.
|
|
253
|
+
A "failed" check may be CANCELLED by a concurrent push (concurrency
|
|
254
|
+
groups) — read the conclusion, `gh run rerun <id> --failed`.
|
|
255
|
+
|===
|
data/lib/canon/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: canon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.119
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|
|
@@ -44,28 +44,28 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 1.9.
|
|
47
|
+
version: 1.9.401
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 1.9.
|
|
54
|
+
version: 1.9.401
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: moxml
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 0.
|
|
61
|
+
version: 0.6.0
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.
|
|
68
|
+
version: 0.6.0
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: paint
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -142,14 +142,14 @@ dependencies:
|
|
|
142
142
|
requirements:
|
|
143
143
|
- - "~>"
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 0.6.
|
|
145
|
+
version: 0.6.54
|
|
146
146
|
type: :runtime
|
|
147
147
|
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
150
|
- - "~>"
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: 0.6.
|
|
152
|
+
version: 0.6.54
|
|
153
153
|
description: |-
|
|
154
154
|
Canon provides canonicalization and pretty-printing for various serialization
|
|
155
155
|
formats (XML, HTML, JSON, YAML), producing standardized forms suitable for
|
|
@@ -171,6 +171,7 @@ files:
|
|
|
171
171
|
- Rakefile
|
|
172
172
|
- docs/.lycheeignore
|
|
173
173
|
- docs/Gemfile
|
|
174
|
+
- docs/HANDOFF.adoc
|
|
174
175
|
- docs/INDEX.adoc
|
|
175
176
|
- docs/_config.yml
|
|
176
177
|
- docs/_references/canonical-digests.adoc
|