From 0a9d20a20795277f6696494b08ca8c10a7b60fca Mon Sep 17 00:00:00 2001 From: Emmanuel Prunet Date: Sun, 4 Oct 2026 01:23:13 +0200 Subject: [PATCH] =?UTF-8?q?spec(0.10.0):=20=C2=A73.5=20=E2=80=94=20param?= =?UTF-8?q?=5Findex=20is=20the=20ordinal=20among=20the=20template's=20whol?= =?UTF-8?q?e-token=20wildcards,=20and=20a=20producer=20MUST=20emit=20exact?= =?UTF-8?q?ly=20one=20param=20for=20each,=20in=20token=20order,=20and=20no?= =?UTF-8?q?ne=20for=20a=20wildcard=20inside=20a=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 23 +++++++++++++++++++++-- SPEC.md | 10 +++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b76b617..8da14e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,9 +38,11 @@ on `MetaLogDiff`, a rewritten §13.2 clause, a `diff_version` rule (§13.1.1) th a producer stamping an older value now violates, and a definition of `window.start` and `window.end` (§2.2) that a producer writing its own bounds there now violates, a definition of `behavior.top_ngrams[].probability` (§4) that a producer writing a -joint probability at `ngram_size` above 2 now violates, and a rule on which templates get a +joint probability at `ngram_size` above 2 now violates, a rule on which templates get a `branching_delta` row (§13.1) that a producer emitting one for a template branching on one -side only now violates. +side only now violates, and a binding of each param to a whole-token wildcard (§3.5) that a +producer emitting a param for a wildcard inside a token, or none for a whole-token wildcard, +now violates. It also adds one optional member (`withheld_signals`, §13.2.2), which is additive on its own. MINOR bump: MAJOR stays `0`, so §6's *"the MAJOR field of `metalog_version` must equal the MAJOR of the spec"* is @@ -154,6 +156,23 @@ proposed; any of them that is taken lands as an editor change recorded here. adopts it in the same release; on its determinism corpus the rule removes 45 of 48 rows, every one comparing a template the other window never held in `branching`. +- **§3.5 — `param_index` is the ordinal among the template's whole-token wildcards, and a + producer MUST bind one param to each.** The comment called `param_index` a "0-based wildcard + position", which a template whose normalization writes a wildcard INSIDE a token (a path + segment, a bracketed index) makes ambiguous: counting every wildcard puts a param on a slot + that carries no value. A new paragraph after the §3.5 example requires a producer to emit + exactly one param for every template token that is the wildcard, in token order, and none + for a wildcard inside a token, so `param_index` *i* names the value under the (*i* + 1)-th + whole-token wildcard and a consumer can put each value back into its slot from the template + alone. The reference producer emitted no param for a whole token its normalization reduced to + the wildcard (a dashed UUID standing alone), so the indices after it pointed one slot early. + **Breaking** — a producer that emits a param for a wildcard inside a token, or none for a + whole-token wildcard, becomes non-conformant — and editor-merged under + [`GOVERNANCE.md`](GOVERNANCE.md) §2's 0.x rule. No schema changed: the rule relates a + template's text to its params, which no keyword can see. The reference implementation + adopts it in the same release; template text and ids do not move, and only templates + carrying such a whole-token wildcard gain a param. + ### Added - **§13.2.1 — `x-metalog-vacuous`, a per-property vacuity declaration.** The witness diff --git a/SPEC.md b/SPEC.md index f3c2212..ac6ba35 100644 --- a/SPEC.md +++ b/SPEC.md @@ -448,7 +448,8 @@ paths, status codes) rather than only at the template level. "frequency": 0.0676, "param_histograms": [ // array, optional; one entry per tracked wildcard slot { - "param_index": 0, // integer, required, 0-based wildcard position + "param_index": 0, // integer, required, 0-based ordinal among the template's + // tokens that are exactly the wildcard "value_counts": { // object, required, top-N observed values → count "/api/users": 800, "/health": 200 @@ -467,6 +468,13 @@ paths, status codes) rather than only at the template level. } ``` +A producer **MUST** emit exactly one param for every template token that is the wildcard, +in token order, and none for a wildcard inside a token, which is a normalization. So +`param_index` *i* is the value under the (*i* + 1)-th whole-token wildcard: in +`"GET <*> -> <*>"` it is 0 for the path and 1 for the status, and in +`"fetch cache/<*> took <*> ms"` the only param, index 0, is the duration, because +`cache/<*>` is one token that merely contains the wildcard. + - A producer **MUST NOT** emit `param_histograms` for entries not in `top_k`. - The `value_counts` map **MUST** be bounded (producers **SHOULD** cap at a configurable limit, default 256, and count overflows in `total`).