test(okf): the one unquoting rule was pinned at its edge, not in its three clauses
D7 mirroring candidate (a)/(i) `unquote_scalar`, measured. The sibling grew that function after a duplicated conversion had drifted; our counterpart `okf._strip_matching_quotes` is genuinely ONE rule -- one definition, one call site, and `unquote` appears in 0 of 76 .py files under src+tests (positive control: the same query finds `parse_frontmatter`). So the drift shape is absent. But the rule was covered only at its edge. Detaching it outright is red; each of its three clauses was green-but-dead against the whole 950-test suite -- weakening the length guard, dropping the matching requirement, and widening the quote set with a symmetric delimiter all left the suite green. Same class as the _STRUCTURE_MARKERS hole: named and edge-covered is not covered. tests/test_okf_unquote_loadbearing.py closes the three clauses (950 -> 955). Each clause test is green before and red after exactly its own mutation, with the population control green in both, clause 3 pinned on its line via --red-at. A measuring trap, measured: the first clause-3 mutation added '[' to the quote set and the suite stayed green -- which reads as "not covered" but is a NO-OP, since '[' can never satisfy the matching clause. Flow-form values are protected by the matching clause, not the quote set. The harness cannot distinguish a behaviour-preserving mutation from an undetected seam; both surface as "stayed GREEN". A mutation must be shown to change behaviour before its green is read as a hole. No flow decoding is added here -- that is the sibling's B4 work, and these tests pin today's boundary so it cannot land silently on this side. Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
c267bfa255
commit
607f017537
2 changed files with 190 additions and 1 deletions
|
|
@ -41,7 +41,7 @@ kandidater, ikke som planlagt arbeid:
|
||||||
- S3.2
|
- S3.2
|
||||||
- S4.0 (`126807a`)
|
- S4.0 (`126807a`)
|
||||||
- (p) `to_ore` — TO kallsteder
|
- (p) `to_ore` — TO kallsteder
|
||||||
- (a)/(i) `unquote_scalar`
|
- ~~(a)/(i) `unquote_scalar`~~ — **MÅLT 2026-08-31, se under**
|
||||||
- `mandate.py`
|
- `mandate.py`
|
||||||
- A5 — TO halvdeler
|
- A5 — TO halvdeler
|
||||||
- ~~B4 `ToolCallRecorder`~~ — **BESVART 2026-08-25, se under**
|
- ~~B4 `ToolCallRecorder`~~ — **BESVART 2026-08-25, se under**
|
||||||
|
|
@ -77,6 +77,55 @@ grønn er nettopp populasjons-kontrollen, som den skal. SDK-fila ble restaurert
|
||||||
**Datering (D7-rammen):** dette er arbeid ETTER 2026-08-09 og skal **ikke** leses som
|
**Datering (D7-rammen):** dette er arbeid ETTER 2026-08-09 og skal **ikke** leses som
|
||||||
uavhengig konvergens selv om svaret er identisk med søskenets.
|
uavhengig konvergens selv om svaret er identisk med søskenets.
|
||||||
|
|
||||||
|
### (a)/(i) `unquote_scalar` — svaret er JA, den var ÉN regel, men pinnet bare i kanten (målt 2026-08-31)
|
||||||
|
|
||||||
|
Kandidaten står i køen fordi søskenet vokste en navngitt `unquote_scalar` etter at en
|
||||||
|
**duplisert konvertering hadde driftet** — to steder som fjernet anførselstegn fra en
|
||||||
|
frontmatter-skalar, etter to regler. Speilings-spørsmålet er derfor ikke «har vi funksjonen»,
|
||||||
|
men det søskenets defekt faktisk stiller: **er den ÉN regel hos oss, og er selve regelen
|
||||||
|
load-bearing?**
|
||||||
|
|
||||||
|
**Populasjonen først.** `unquote_scalar` finnes ikke hos oss: **0 treff av 76 undersøkte
|
||||||
|
`.py`-filer** i `src`+`tests` (positiv kontroll: samme spørring finner `parse_frontmatter` i
|
||||||
|
`okf.py`), og `unquote` finnes ikke i repoet utenfor `.venv`. Vår motpart er
|
||||||
|
`okf._strip_matching_quotes` — **én definisjon, ett kallsted** (`_parse_frontmatter_and_body`).
|
||||||
|
Søskenets drift-form finnes altså ikke her.
|
||||||
|
|
||||||
|
**Men regelen var dekket bare i kanten.** Med `scripts/mutation_harness.py`, nevner `tests/`
|
||||||
|
(hele suiten, 950 tester), hver kjøring sha256-restaurert:
|
||||||
|
|
||||||
|
- Å detache regelen helt (`return value[1:-1]` → `return value`) er **RØD** —
|
||||||
|
`test_okf.py::TestFrontmatter::test_unknown_fields_preserved_and_quotes_stripped` fanger den.
|
||||||
|
- Hver av de tre **klausulene** var **grønn-men-død**: å svekke lengdevakten (`>= 2` → `>= 1`),
|
||||||
|
å droppe matching-kravet (`value[0] == value[-1] and`), og å utvide quote-settet med en
|
||||||
|
symmetrisk delimiter (backtick) lot hele suiten stå grønn.
|
||||||
|
|
||||||
|
Samme klasse som `_STRUCTURE_MARKERS`-hullet i økt 32: sømmen var NAVNGITT og kant-dekket, som
|
||||||
|
ikke er det samme som dekket. **Pinnet av** `tests/test_okf_unquote_loadbearing.py` (5 tester,
|
||||||
|
950 → 955). Value-beviset er kjørt, ikke påstått: hver klausul-test er grønn før og rød etter
|
||||||
|
nøyaktig sin egen mutasjon, med populasjons-kontrollen grønn i begge (mutasjonen landet ikke
|
||||||
|
for bredt), og ledd 3 pinnet på linje via `--red-at`.
|
||||||
|
|
||||||
|
**EN MÅLETRAP, MÅLT — ny lærdom om harnesset.** Første forsøk på klausul 3 utvidet settet med
|
||||||
|
`'['`. Suiten forble grønn, hvilket leses som «klausulen er ikke dekket» — men mutasjonen er en
|
||||||
|
**no-op**: `'['` kan aldri tilfredsstille matching-kravet, siden `[` ikke er `]`. Flow-form-
|
||||||
|
verdier er altså beskyttet av **matching-klausulen, ikke av quote-settet**, og en grønn kjøring
|
||||||
|
under den mutasjonen var aldri bevis om quote-settet i det hele tatt. **Harnesset kan ikke
|
||||||
|
skille en oppførsels-bevarende mutasjon fra en udekket søm — begge kommer ut som «stayed
|
||||||
|
GREEN».** En mutasjon må vises å endre oppførsel før dens grønne leses som et hull. Dette er
|
||||||
|
Verifiseringsloven ansikt 4 anvendt på selve måleapparatet: et negativt resultat fra en
|
||||||
|
spørring som ikke KAN finne, er ikke null — det er ikke målt.
|
||||||
|
|
||||||
|
**Ærlig grense — hva dette IKKE sier.** Å pinne at flow-verdier passerer **urørt** er ikke
|
||||||
|
flow-DEKODING, og fila legger ingen til: `tags: [a, b]` forblir strengen `"[a, b]"`. Den
|
||||||
|
linje-orienterte parseren har ingen nesting-modell ved design (§1 ærlighets-regelen). Den
|
||||||
|
additive flow-dekoderen er søskenets B4-arbeid i `portfolio-optimiser` og er bevisst **ikke**
|
||||||
|
bygget her; testene pinner dagens grense slik at det arbeidet ikke kan lande stille på denne
|
||||||
|
siden.
|
||||||
|
|
||||||
|
**Datering (D7-rammen):** arbeid ETTER 2026-08-09 — skal **ikke** leses som uavhengig konvergens.
|
||||||
|
|
||||||
|
|
||||||
Rammen rundt køen: å lese søskenets kode er tillatt (`3bdf7f0`), men kopiering skal kun skje
|
Rammen rundt køen: å lese søskenets kode er tillatt (`3bdf7f0`), men kopiering skal kun skje
|
||||||
der det tjener løsningen, aldri som snarvei. **Uavhengighets-beviset er DATERT** t.o.m.
|
der det tjener løsningen, aldri som snarvei. **Uavhengighets-beviset er DATERT** t.o.m.
|
||||||
2026-08-09; arbeid etter den datoen kan ikke leses som uavhengig konvergens.
|
2026-08-09; arbeid etter den datoen kan ikke leses som uavhengig konvergens.
|
||||||
|
|
|
||||||
140
tests/test_okf_unquote_loadbearing.py
Normal file
140
tests/test_okf_unquote_loadbearing.py
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
"""(a)/(i) `unquote_scalar`: is our one unquoting rule pinned, or pinned only at the edge?
|
||||||
|
|
||||||
|
The D7 mirroring queue (``docs/2026-08-18-funn-koeer-og-gater.md § D7-speilingskøen``)
|
||||||
|
carries this candidate because the MAF sibling grew a named ``unquote_scalar`` after
|
||||||
|
a DUPLICATED conversion had drifted — two places unquoting a frontmatter scalar, by
|
||||||
|
two rules. Our counterpart is ``okf._strip_matching_quotes``: one definition, one
|
||||||
|
call site (``_parse_frontmatter_and_body``). The mirroring question is therefore not
|
||||||
|
"do we have the function" but the one the sibling's defect actually poses — **is it
|
||||||
|
the ONE rule, and is the rule itself load-bearing in each of its three clauses?**
|
||||||
|
|
||||||
|
MEASURED 2026-08-31 with ``scripts/mutation_harness.py``, denominator ``tests/``
|
||||||
|
(the whole suite, 950 tests), each run restored sha256-verified:
|
||||||
|
|
||||||
|
- Detaching the rule outright (``return value[1:-1]`` -> ``return value``) is RED —
|
||||||
|
``test_okf.py::TestFrontmatter::test_unknown_fields_preserved_and_quotes_stripped``
|
||||||
|
catches it. The seam has an edge guard.
|
||||||
|
- Each of the three CLAUSES is GREEN-BUT-DEAD. Weakening the length guard
|
||||||
|
(``>= 2`` -> ``>= 1``), dropping the matching requirement
|
||||||
|
(``value[0] == value[-1] and``), and widening the quote set with a SYMMETRIC
|
||||||
|
delimiter (adding a backtick) each left the pre-existing suite green. Nothing
|
||||||
|
noticed.
|
||||||
|
|
||||||
|
So the answer mirrors økt 32's ``_STRUCTURE_MARKERS`` hole, not B4's: the seam was
|
||||||
|
NAMED and edge-covered, which is not the same as covered. This file closes the three
|
||||||
|
clauses. Each test below was proved RED under exactly the mutation it names.
|
||||||
|
|
||||||
|
WHY THIS CANDIDATE, NOW. ``llm-ingestion-okf`` pins its emission to FLOW form, so a
|
||||||
|
frontmatter value may legally arrive as ``[a, b]`` or ``{k: v}``. Which clause
|
||||||
|
actually protects those turned out NOT to be the one reached for first — see below.
|
||||||
|
|
||||||
|
A MEASURING TRAP, MEASURED. The first attempt at the third clause widened the set
|
||||||
|
with ``'['``. The suite stayed green, which reads as "clause not covered" — but the
|
||||||
|
mutation is a NO-OP: ``'['`` can never satisfy the matching clause, since ``[`` is
|
||||||
|
not ``]``. So flow-form values are protected by the MATCHING clause, not by the
|
||||||
|
quote set, and a green run under that mutation was never evidence about the quote
|
||||||
|
set at all. The harness cannot tell a behaviour-preserving mutation from an
|
||||||
|
undetected seam — both surface as "stayed GREEN". A mutation must be shown to
|
||||||
|
change behaviour before its green is read as a hole; the backtick, being
|
||||||
|
symmetric, does change it and is what the clause is pinned with below.
|
||||||
|
|
||||||
|
HONEST LIMIT — what this does NOT say. Pinning that flow values pass through
|
||||||
|
UNTOUCHED is not flow DECODING, and this file does not add any: ``tags: [a, b]``
|
||||||
|
stays the string ``"[a, b]"``. The line-oriented parser has no nesting model by
|
||||||
|
design (``_parse_frontmatter_and_body``'s own docstring, §1 honesty rule). An
|
||||||
|
additive flow decoder is the sibling's B4 work in ``portfolio-optimiser`` and is
|
||||||
|
deliberately NOT built here; these tests pin today's boundary so that work cannot
|
||||||
|
land silently on this side.
|
||||||
|
|
||||||
|
Dated under the D7 frame: this is work AFTER 2026-08-09 and must NOT be read as
|
||||||
|
independent convergence with the sibling.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import ast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from portfolio_optimiser_claude.okf import parse_concept_file
|
||||||
|
|
||||||
|
SRC_PKG = Path(__file__).resolve().parents[1] / "src" / "portfolio_optimiser_claude"
|
||||||
|
OKF_SOURCE = SRC_PKG / "okf.py"
|
||||||
|
RULE_NAME = "_strip_matching_quotes"
|
||||||
|
|
||||||
|
|
||||||
|
def _concept_with(tmp_path: Path, value: str) -> dict[str, str]:
|
||||||
|
"""Parse ``title: <value>`` through the PUBLIC path and hand back the frontmatter.
|
||||||
|
|
||||||
|
Through ``parse_concept_file``, never by calling the private rule directly: a
|
||||||
|
layer you do not run is not a seam (økt 37). What is asserted below is what the
|
||||||
|
parser actually hands downstream.
|
||||||
|
"""
|
||||||
|
path = tmp_path / "a.md"
|
||||||
|
path.write_text(f"---\ntype: reference\ntitle: {value}\n---\nBody.\n", encoding="utf-8")
|
||||||
|
return parse_concept_file(path).frontmatter
|
||||||
|
|
||||||
|
|
||||||
|
class TestTheUnquotingRuleIsOneRule:
|
||||||
|
"""The population control — and it runs first, because every clause below is
|
||||||
|
worth only as much as the claim that there is exactly ONE place to pin."""
|
||||||
|
|
||||||
|
def test_exactly_one_definition_and_one_call_site(self) -> None:
|
||||||
|
# This is the sibling's defect made measurable on our side: their duplicate
|
||||||
|
# drifted. RED the day a second unquoting rule appears, or the single call
|
||||||
|
# site becomes two. Read from the AST, not from a grep of prose.
|
||||||
|
tree = ast.parse(OKF_SOURCE.read_text(encoding="utf-8"))
|
||||||
|
definitions = [
|
||||||
|
n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef) and n.name == RULE_NAME
|
||||||
|
]
|
||||||
|
call_sites = [
|
||||||
|
n
|
||||||
|
for n in ast.walk(tree)
|
||||||
|
if isinstance(n, ast.Call) and isinstance(n.func, ast.Name) and n.func.id == RULE_NAME
|
||||||
|
]
|
||||||
|
assert len(definitions) == 1, f"the ONE unquoting rule is now {len(definitions)}"
|
||||||
|
assert len(call_sites) == 1, (
|
||||||
|
f"{RULE_NAME} gained a second call site — the sibling's drift shape: "
|
||||||
|
f"lines {[c.lineno for c in call_sites]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_the_rule_still_strips_the_ordinary_case(self, tmp_path: Path) -> None:
|
||||||
|
# POSITIVE CONTROL FOR EVERY NEGATIVE BELOW. Each clause test asserts that
|
||||||
|
# some value comes through UNSTRIPPED; that is vacuous unless stripping
|
||||||
|
# demonstrably happens at all on this path.
|
||||||
|
frontmatter = _concept_with(tmp_path, '"Quoted title"')
|
||||||
|
assert frontmatter["title"] == "Quoted title"
|
||||||
|
|
||||||
|
|
||||||
|
class TestEachClauseOfTheRuleIsLoadBearing:
|
||||||
|
"""One test per clause of ``len(value) >= 2 and value[0] == value[-1] and
|
||||||
|
value[0] in {'"', "'"}`` — each proved RED under its own mutation."""
|
||||||
|
|
||||||
|
def test_length_guard_protects_a_single_quote_character(self, tmp_path: Path) -> None:
|
||||||
|
# RED under `len(value) >= 2` -> `len(value) >= 1`.
|
||||||
|
# A lone quote is its own first AND last character, so without the length
|
||||||
|
# guard it satisfies the other two clauses and `value[1:-1]` erases it.
|
||||||
|
# A malformed scalar must survive as itself — OKF robustness: tolerate,
|
||||||
|
# never silently rewrite.
|
||||||
|
assert _concept_with(tmp_path, '"')["title"] == '"'
|
||||||
|
|
||||||
|
def test_matching_requirement_protects_an_unterminated_quote(self, tmp_path: Path) -> None:
|
||||||
|
# RED under dropping `value[0] == value[-1] and`.
|
||||||
|
# Without it, an unterminated `"Oslo` is stripped from BOTH ends and
|
||||||
|
# arrives as `Osl` — a silent corruption strictly worse than the
|
||||||
|
# malformed input it came from.
|
||||||
|
assert _concept_with(tmp_path, '"Oslo')["title"] == '"Oslo'
|
||||||
|
assert _concept_with(tmp_path, "Oslo'")["title"] == "Oslo'"
|
||||||
|
|
||||||
|
def test_the_quote_set_is_exactly_two_characters(self, tmp_path: Path) -> None:
|
||||||
|
# RED under widening the set with a SYMMETRIC delimiter:
|
||||||
|
# `{'"', "'"}` -> `{'"', "'", '`'}`. A backtick pair is not a YAML quote,
|
||||||
|
# and the set is closed at two.
|
||||||
|
assert _concept_with(tmp_path, "`code`")["title"] == "`code`"
|
||||||
|
# Flow-form values (llm-ingestion-okf pins its emission to flow form) must
|
||||||
|
# ride through navigation UNTOUCHED (ingest-spec §7). These are guarded by
|
||||||
|
# the MATCHING clause above, not by the quote set — `[` is not `]` — and
|
||||||
|
# they are asserted here because that is where a flow decoder would first
|
||||||
|
# be reached for. Stripping the delimiters would hand downstream a string
|
||||||
|
# that is neither the flow value nor its decoding.
|
||||||
|
assert _concept_with(tmp_path, "[a, b]")["title"] == "[a, b]"
|
||||||
|
assert _concept_with(tmp_path, "{k: v}")["title"] == "{k: v}"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue