feat(frozen-bundles): the measurements read a pinned copy, not another repo's build dir

Measured 2026-09-17 17:43: vegnormal-okf rebuilt build/ferdig/r761-2025 while this
repository's v1 gate, the stress judge and four corpus tests pointed straight at it.
Rows 6-7 went IKKE MAALT and five tests fell, for a change no one here made. The failure
mode was never falsehood - the gate says IKKE MAALT and exits non-zero, never green - it
was instability: two projects shared a directory neither owns, so what this repository
MEASURES could move without a commit here.

A copy alone would push that directory one move away, so the copy comes with a pin.
frozen_bundles.json (tracked) carries path + sha256 + file count per base; the bundles
themselves are NEVER committed here. Three states, separated by construction: match ->
resolves; gone -> FrozenBundleMissing (an OSError, so the gate's existing except OSError
gives IKKE MAALT + exit 1 unchanged and the corpus tests SKIP, MAJOR-3's ceiling); drift
-> FrozenBundleDrift (a ValueError), loud, named, and never a skip. The two classes are
deliberately unrelated: a caller that catches "missing" to skip must not swallow "drift".

The NAME is hashed alongside the bytes, and the directory name carries the first 12 chars
of the digest so a stale copy is visible in ls. Renewal is a decision: new copy + new pin
in the SAME commit (README). --bundle-root / PORTFOLIO_VEGNORMAL_ROOT stays as the
operator's explicit, UNPINNED live mount.

Iron Law: the tests were written and run RED first (collection error, then two arms of my
own making). Load-bearing MEASURED, eight mutations all red against the WHOLE suite with a
green control of 1984 passed / 5 skipped / 5 xfailed and a strict node-id superset
(1977 -> 1994, 0 removed): M1 the pin is never verified (7) - M2 drift collapsed into
missing (5) - M3 the name is not hashed (40) - M4 the gate seam reverted to root/name (1) -
M5 the corpus helpers skip on drift too (4, one per file) - M6a the slash spelling back in
src (1) - M6b the quoted path segment back in a test (1) - M7 the directory name drops the
short digest (1, and 45 skipped, which proves absence is a SKIP and not a false green) -
M8 the explicit override ignored (3, two of them in test_stress_judge_loadbearing.py,
independent witnesses older than this work).

M2 FALSIFIED THE TEST FIRST: the four parametrised arms did not go red, they went to SKIP
(5 -> 9 skipped) and stayed green - pytest.skip inside a pytest.raises is not a failure.
The arm now catches pytest.skip.Exception explicitly and turns it into an AssertionError.

grep -rnE 'vegnormal-okf/build|["'"'"']vegnormal-okf["'"'"']' src tests contexts -> 0
(3 + 4 hits before; the three remaining prose mentions document history and are allowed).
Gate re-run against the frozen copy: identical to the live mount (rows 0/3 - 0/3 - 3/8 -
no report - 3/8 - IKKE MAALT - 1/20, exit 1).

Order 20260917T223645Z-1296211942-from-.claude.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-18 03:22:22 +02:00
commit 50c9763706
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
12 changed files with 654 additions and 60 deletions

View file

@ -3148,6 +3148,51 @@ Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 —
uten `approach_id` (eldre artefakter) som `run`; v1-gatens rad 6 sier da «IKKE MÅLT», og IKKE
MÅLT feller exit-koden (aldri grønn). Load-bearing MÅLT
(`tests/test_row6_declaration_rule_loadbearing.py` + rad 6-probene), ti mutasjoner alle røde.
- **Målingene leser en FROSSET kopi av korpuset, pinnet med sha256 — aldri et annet repos levende
build-mappe (18.09, ordre `20260917T223645Z-1296211942`):** gaten, stressdommeren og fire
korpus-tester leste `~/repos/vegnormal-okf/build/ferdig` DIREKTE. **MÅLT 17.09 17:43:** vegnormal
bygget om `r761-2025`, rad 67 sa «IKKE MÅLT» og fem tester falt, for en endring ingen her gjorde.
**Feilmodusen var aldri usannhet** — gaten sier IKKE MÅLT og exit 1, aldri falskt grønn — den var
USTABILITET: to prosjekter delte en mappe ingen av dem eier, så hva dette repoet MÅLER kunne
flytte seg uten en commit her. **En kopi alene ville bare skjøvet den mappa ett hakk unna**, så
kopien kommer med en PIN: `frozen_bundles.json` (tracked) bærer sti + sha256 + filantall per base,
mens BUNDLENE ALDRI committes her (vegnormal-korpus skal ikke til en offentlig flate).
**Tre tilstander, skilt VED KONSTRUKSJON, og den tredje er hele poenget:** kopien MATCHER → den
eneste stien som måler noe; kopien er BORTE → `FrozenBundleMissing`, en `OSError`, så gatens
eksisterende `except OSError` gir IKKE MÅLT + exit 1 uendret og korpus-testene SKIPPER (MAJOR-3s
tak: en hard feil ville brutt `uv run pytest` i overleveringsarkivet, der intet korpus er
montert); kopien AVVIKER → `FrozenBundleDrift`, en `ValueError`, høylytt og navngitt og ALDRI en
skip — en drevet kopi er ikke en uleselig måling, den er en måling av FEIL korpus, altså den ene
tilstanden som produserer et stille galt tall. **De to klassene er BEVISST uten slektskap:** en
kaller som fanger «mangler» for å skippe må ikke svelge «avvik». **NAVNET hashes ved siden av
bytene** — uten det ville et korpus stokket om under samme bytes pinnet rent — og katalognavnet
BÆRER de 12 første tegnene av digesten, så en foreldet kopi er synlig i `ls`, ikke bare for
verifisereren. **Fornyelse er en BESLUTNING, aldri rydding:** ny kopi + ny pin i SAMME commit
(README § Frozen knowledge bases). `--bundle-root` / `PORTFOLIO_VEGNORMAL_ROOT` består som
operatørens EKSPLISITTE, UPINNEDE levende montering — måten å se på et ferskt korpus før man
bestemmer seg for å fryse på nytt; uten den kan ikke gaten brukes til å ta den beslutningen.
**Grep-gaten dekker BEGGE stavemåtene, hver med sin egen kjent-positiv:** `vegnormal-okf/build`
(3 treff før) og det siterte sti-segmentet `"vegnormal-okf"` (4 treff før) — en fil-bred gate med
ÉN av dem ville vært grønn mot fire av de sju stedene, og prosa som dokumenterer historikk
(3 treff) er eksplisitt tillatt. Testfila bygger tokenet med `"-".join(...)`, fordi `ruff format`
MÅLT folder `"vegnormal" "-okf"` tilbake til én literal og gaten da blir rød mot sin egen kilde.
Load-bearing MÅLT (`tests/test_frozen_bundles_loadbearing.py`, 17 armer), **åtte mutasjoner alle
røde mot HELE suiten** + grønn kontroll **1984/5 + 5 xfailed** og node-ID-supersett (1977 → 1994,
**0 fjernet**): M1 pinnen verifiseres aldri (7 røde) · M2 avvik kollapset inn i «mangler» (5) ·
M3 navnet hashes ikke (40) · M4 gate-sømmen reverteres til `root/name` (1) · M5 korpus-testene
skipper på avvik også (4 — én per fil) · M6a `vegnormal-okf/build` tilbake i `src` (1) ·
M6b det siterte sti-segmentet tilbake i en test (1) · M7 katalognavnet dropper den korte digesten
(1, og 45 skipped — som beviser at fravær er en SKIP, ikke en falsk grønn) · M8 den eksplisitte
overstyringen ignoreres (3, hvorav TO i `test_stress_judge_loadbearing.py`, uavhengige vitner
eldre enn dette arbeidet). **M2 FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse,
TJUEFJERDE gang):** de fire parametriserte armene gikk ikke røde, de gikk til SKIP (5 → 9 skipped
over suiten) og sto grønne — `pytest.skip` inne i en `pytest.raises` er ikke en feil. Armen fanger
`pytest.skip.Exception` EKSPLISITT og gjør den til en `AssertionError`. **Ærlighets-grenser,
uttalt:** en overstyrt montering er UPINNET ved konstruksjon (operatøren navnga den), så gaten
kjørt med `--bundle-root` måler ikke det pinnede korpuset og sier det ikke — pinnen er default,
ikke et påbud; digesten dekker hver fil, så en `.DS_Store` som dukker opp i kopien er et AVVIK
(MÅLT: null `.DS_Store` og null symlenker i alle fire basene da kopien ble tatt); og kopien ble
tatt 18.09 fra vegnormals mappe KUN ved lesing — kildens mtimer er uendret.
- **STATE.md er local-only** (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
- Prosess: Voyage-plugin (`/trekbrief → /trekplan → /trekexecute → /trekreview`) per større fase.

View file

@ -1040,3 +1040,17 @@ uv sync
uv run pytest
uv run ruff check .
```
### Frozen knowledge bases
The measurements that read a delivered corpus (the v1 gate's rows 67, the stress judge, and four
corpus tests) read a **frozen copy** under `~/corpora/po-frosne-bundles/<name>-<short sha256>/`,
outside every repository, pinned by `src/portfolio_optimiser/frozen_bundles.json`. The bundles
themselves are never committed here; only the pin is. A copy that no longer matches its pin fails
loudly (`frosset bundle … avviker fra pin`), and a copy that is absent is `IKKE MÅLT`, never green.
**Renewing a copy is a decision, not maintenance: a new copy and a new pin go in the SAME commit.**
Re-copy the base, recompute with `portfolio_optimiser.frozen_bundles.digest_bundle`, rename the
directory to carry the new short digest, and update `frozen_bundles.json` in that same change.
`--bundle-root` (or `PORTFOLIO_VEGNORMAL_ROOT`) stays as an explicit, **unpinned** live mount — the
way to look at a fresh corpus before deciding to refreeze.

View file

@ -760,11 +760,11 @@ def _own_proposals(
def measure_stress(
evidence: Mapping[str, Any], repo_root: Path, stress_root: Path, bundle_root: Path
evidence: Mapping[str, Any], repo_root: Path, stress_root: Path, bundle_root: Path | None
) -> StressMeasure:
"""Re-judge every listed outbox with the current judge. Any run that cannot be judged makes the
whole measurement absent a partial one would carry the wrong denominator."""
from portfolio_optimiser import stress
from portfolio_optimiser import frozen_bundles, stress
from portfolio_optimiser.mandate import load_mandate
verdicts = []
@ -779,8 +779,11 @@ def measure_stress(
chosen = [d for d in declared if wanted in (None, d["name"], d["bundle_id"])]
if len(chosen) != 1:
return StressMeasure(where=str(stress_root), missing=f"{context}: base ikke entydig")
base = bundle_root / chosen[0]["name"]
try:
# The frozen copy this repository pins, unless the operator named a live mount.
# Drift is a ValueError and absence an OSError: both land in ``missing`` below, so a
# corpus that moved is IKKE MÅLT with the reason said, never a silently wrong number.
base = frozen_bundles.bundle_dir(chosen[0]["name"], override=bundle_root)
verdicts.append(
stress.score_context_set(
context,
@ -933,10 +936,7 @@ def evaluate(
evidence,
repo_root,
stress_root or repo_root / evidence["root"],
bundle_root
or Path(
os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", "~/repos/vegnormal-okf/build/ferdig")
).expanduser(),
bundle_root,
)
return [
score_rounds(rounds_dir, required, ai),
@ -999,7 +999,10 @@ def main(argv: Sequence[str] | None = None) -> int:
"--stress-root", default=None, help="utboks-roten for stressrunden rad 6-7 dømmer"
)
parser.add_argument(
"--bundle-root", default=None, help="der stressrundens kunnskapsbaser er montert"
"--bundle-root",
default=None,
help="en EKSPLISITT, UPINNET levende montering; uten den svarer den frosne kopien og "
"sha256-pinnen verifiseres",
)
parser.add_argument("--json", action="store_true", help="maskinlesbar output")
args = parser.parse_args(argv)

View file

@ -0,0 +1,27 @@
{
"store": "~/corpora/po-frosne-bundles",
"source": "vegnormal-okf build/ferdig, READ-ONLY copy taken 2026-09-18",
"renewal": "Ny kopi + ny pin i SAMME commit - se README, 'Frosne kunnskapsbaser'.",
"bundles": {
"n100-2023": {
"directory": "n100-2023-69c62e5c5414",
"sha256": "69c62e5c541455fd4bfafbfde0a45b604ec3788532b61441e1445494c9e70bea",
"files": 450
},
"n200-2024": {
"directory": "n200-2024-9950f2f4cc8c",
"sha256": "9950f2f4cc8ccec8605c47035e8e9de3ba4028f4a4091c95a64953242a69137d",
"files": 1137
},
"n500-2024": {
"directory": "n500-2024-c68f18d6375f",
"sha256": "c68f18d6375f4461710c9cea54b2e8335d1b6461446364c9bfaf764fb88efdcb",
"files": 274
},
"r761-2025": {
"directory": "r761-2025-58e1ecca6007",
"sha256": "58e1ecca60075d77f3ca4776ee7e76466ef2631566099f37856eeef96620ab02",
"files": 5564
}
}
}

View file

@ -0,0 +1,134 @@
"""The frozen knowledge bases the measurements read — a copy this repository PINS, never another
repository's live build directory.
Measured 2026-09-17 17:43: ``vegnormal-okf`` rebuilt ``build/ferdig/r761-2025`` while this
repository's v1 gate and four corpus tests pointed straight at it. Rows 6-7 went "IKKE MÅLT" and
five tests fell, for a change no one here made. The failure mode was never falsehood the gate
says IKKE MÅLT and exits non-zero, never green it was *instability*: two projects shared a
directory neither owns, so what this repository MEASURES could move without a commit here.
A copy alone would only push that directory one move away, so the copy comes with a pin: the
sha256 of the bundle's files in deterministic order, tracked in ``frozen_bundles.json``. Three
states, separated by construction:
* the copy MATCHES the pin -> it resolves, and that is the only path that measures anything;
* the copy is GONE -> :class:`FrozenBundleMissing`, an ``OSError``, so the gate's existing
``except OSError`` says IKKE MÅLT and fails the exit code exactly as before, and the corpus
tests SKIP (MAJOR-3's ceiling: a hard error would break ``uv run pytest`` in the handover
archive, where no corpus is mounted);
* the copy DIFFERS -> :class:`FrozenBundleDrift`, a ``ValueError``, loud and named and
NEVER a skip. A drifted copy is not an unreadable measurement, it is a measurement of the wrong
corpus the one state that produces a silently wrong number.
The two classes are deliberately unrelated: a caller that catches "missing" in order to skip must
not swallow "drift".
The bundles themselves are NEVER committed here vegnormal corpora must not reach a public
remote. Only the pin is tracked. Renewing a copy is a DECISION, not maintenance: a new copy and a
new pin in the SAME commit (see README).
"""
from __future__ import annotations
import hashlib
import json
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Mapping
#: The pin this repository tracks: path fragment + sha256 + file count, one entry per base.
PIN_FILE = Path(__file__).with_name("frozen_bundles.json")
#: Where the frozen copies live, unless the environment says otherwise. OUTSIDE both repositories:
#: inside either one, the copy is a build artefact of a project that did not make it.
DEFAULT_STORE = "~/corpora/po-frosne-bundles"
#: Moves the store on a machine that keeps its corpora elsewhere. Read at CALL time.
STORE_ENV = "PORTFOLIO_FROZEN_BUNDLES"
#: The operator's explicit, UNPINNED escape hatch: a live mount, named on purpose. Kept because a
#: gate that cannot be pointed at a fresh corpus cannot be used to decide whether to refreeze.
OVERRIDE_ENV = "PORTFOLIO_VEGNORMAL_ROOT"
#: How much of the digest the directory name carries, so a stale copy is visible in ``ls``.
SHORT = 12
class FrozenBundleMissing(FileNotFoundError):
"""The pinned copy is not on this machine. Never green; never confused with drift."""
class FrozenBundleDrift(ValueError):
"""The copy on disk is not the copy that was pinned."""
@dataclass(frozen=True)
class Pin:
name: str
directory: str
sha256: str
files: int
def store_root(store: Path | str | None = None) -> Path:
return Path(store or os.environ.get(STORE_ENV) or DEFAULT_STORE).expanduser()
def load_pins(path: Path | None = None) -> dict[str, Pin]:
data = json.loads((path or PIN_FILE).read_text(encoding="utf-8"))
return {
name: Pin(name, spec["directory"], spec["sha256"], int(spec["files"]))
for name, spec in data["bundles"].items()
}
def digest_bundle(root: Path) -> tuple[str, int]:
"""(sha256 over every file, file count). Deterministic: sorted by the bundle-relative POSIX
path, and the NAME is hashed alongside the bytes without it a corpus reshuffled under the
same bytes would pin clean."""
entries = sorted((p.relative_to(root).as_posix(), p) for p in root.rglob("*") if p.is_file())
outer = hashlib.sha256()
for rel, path in entries:
outer.update(rel.encode("utf-8"))
outer.update(b"\0")
outer.update(hashlib.sha256(path.read_bytes()).hexdigest().encode("ascii"))
outer.update(b"\n")
return outer.hexdigest(), len(entries)
def bundle_dir(
name: str,
*,
override: Path | str | None = None,
store: Path | str | None = None,
pins: Mapping[str, Pin] | None = None,
) -> Path:
"""The directory a measurement reads for the base called ``name``.
``override`` (or ``PORTFOLIO_VEGNORMAL_ROOT``) is the operator's explicit live mount and is
NOT verified they named it. Without one, the frozen store answers and the pin is checked.
"""
named = override if override is not None else os.environ.get(OVERRIDE_ENV) or None
if named is not None:
base = Path(named).expanduser() / name
if not base.is_dir():
raise FrozenBundleMissing(f"knowledge base {name!r} is not mounted under {named}")
return base
pinned = dict(pins) if pins is not None else load_pins()
if name not in pinned:
raise FrozenBundleMissing(
f"{name!r} is not pinned in {PIN_FILE.name} (pinned: {', '.join(sorted(pinned))})"
)
pin = pinned[name]
base = store_root(store) / pin.directory
if not base.is_dir():
raise FrozenBundleMissing(
f"frozen knowledge base {name!r} is not at {base} "
f"(set {STORE_ENV}, or refreeze: new copy + new pin in the same commit)"
)
actual, files = digest_bundle(base)
if actual != pin.sha256:
raise FrozenBundleDrift(
f"frosset bundle {name!r} avviker fra pin: pinnet {pin.sha256[:SHORT]} "
f"({pin.files} filer), på disk {actual[:SHORT]} ({files} filer) i {base}. "
"En kopi fornyes BEVISST: ny kopi + ny pin i samme commit."
)
return base

View file

@ -67,20 +67,19 @@ from __future__ import annotations
import argparse
import json
import os
import sys
from collections.abc import Mapping, Sequence
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Any
from portfolio_optimiser import okf
from portfolio_optimiser import frozen_bundles, okf
from portfolio_optimiser.mandate import Mandate, load_mandate
from portfolio_optimiser.validator import classify_codes, rejection_stage
#: Where the vegnormal bases are mounted, unless ``--bundle-root`` says otherwise. Read at CALL
#: time (the ``shared_root()`` idiom) so a test or an operator can move the mount without a reimport.
_DEFAULT_BUNDLE_ROOT = "~/repos/vegnormal-okf/build/ferdig"
#: Where a base is read from: the FROZEN store this repository pins, resolved at CALL time (the
#: ``shared_root()`` idiom). ``--bundle-root`` stays as the operator's explicit, unpinned live
#: mount. See ``frozen_bundles`` for why a shared build directory is not read directly any more.
class EmptyMeasurement(RuntimeError):
@ -604,8 +603,9 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument("--run-id", required=True)
parser.add_argument(
"--bundle-root",
default=os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", _DEFAULT_BUNDLE_ROOT),
help="directory the set's bundle.txt name is mounted under",
default=None,
help="an explicit, UNPINNED live mount to read the set's bundle.txt name under; without "
"it the frozen store answers and its sha256 pin is verified",
)
parser.add_argument(
"--bundle",
@ -638,7 +638,11 @@ def main(argv: list[str] | None = None) -> int:
file=sys.stderr,
)
return 1
base = Path(args.bundle_root).expanduser() / chosen["name"]
try:
base = frozen_bundles.bundle_dir(chosen["name"], override=args.bundle_root)
except (frozen_bundles.FrozenBundleMissing, frozen_bundles.FrozenBundleDrift) as exc:
print(f"stress refused: {exc}", file=sys.stderr)
return 1
try:
verdict = score_context_set(

View file

@ -39,13 +39,12 @@ keys on. Rule U itself is UNCHANGED, and its known-positive is still red.
from __future__ import annotations
import json
import os
from pathlib import Path
import pytest
from pydantic import ValidationError
from portfolio_optimiser import okf
from portfolio_optimiser import frozen_bundles, okf
from portfolio_optimiser.ir import CostBaseline, CostBaselineLine
from portfolio_optimiser.mandate import load_mandate
from portfolio_optimiser.stress import read_bundle_declarations
@ -53,10 +52,9 @@ from portfolio_optimiser.stress import read_bundle_declarations
_REPO_ROOT = Path(__file__).resolve().parent.parent
_CONTEXT_ROOT = _REPO_ROOT / "contexts"
#: Where the vegnormal bases are mounted. A SYMBOLIC name in ``bundle.txt`` is resolved against
#: this, never an absolute path in the set: this repository is published, and an absolute path
#: would pin a set to one machine's home directory and ride out in the handover archive.
_DEFAULT_BUNDLE_ROOT = Path.home() / "repos" / "vegnormal-okf" / "build" / "ferdig"
#: A SYMBOLIC name in ``bundle.txt`` is resolved against the frozen store, never an absolute path
#: in the set: this repository is published, and an absolute path would pin a set to one machine's
#: home directory and ride out in the handover archive.
#: The concept types the four bases declare. ``index.md`` carries none of them — it is navigation,
#: not content — which is why the file count and the concept count differ.
@ -107,8 +105,16 @@ def own_frontmatter(path: Path) -> dict[str, str]:
return out
def _bundle_root() -> Path:
return Path(os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", str(_DEFAULT_BUNDLE_ROOT)))
def _bundle_dir(name: str) -> Path:
"""The FROZEN copy this repository pins, resolved at call time.
Absence SKIPS (MAJOR-3's ceiling: no corpus is mounted in the handover archive), drift is
allowed to propagate and FAIL a measurement of the wrong corpus is not a missing one.
"""
try:
return frozen_bundles.bundle_dir(name)
except frozen_bundles.FrozenBundleMissing as exc:
pytest.skip(str(exc))
#: The ONE reader, imported from production rather than copied here (P17b). It used to be a
@ -167,13 +173,7 @@ _SET_IDS = [p.name for p in _SETS]
def _require_base(declared: dict[str, str]) -> Path:
root = _bundle_root()
base = root / declared["name"]
if not base.is_dir():
pytest.skip(
f"knowledge base {declared['name']!r} not mounted under {root} (PORTFOLIO_VEGNORMAL_ROOT)"
)
return base
return _bundle_dir(declared["name"])
def _base_by_approach(set_dir: Path) -> dict[str, Path]:

View file

@ -0,0 +1,360 @@
"""The measurements read a FROZEN copy of the vegnormal bases, pinned by sha256 — never another
repository's live build directory.
Measured 2026-09-17 17:43: ``vegnormal-okf`` rebuilt ``build/ferdig/r761-2025`` while this
repository's gate pointed straight at it. Rows 6-7 went "IKKE MÅLT" and five tests fell, for a
change no one here made. The failure mode was never falsehood the gate says IKKE MÅLT and exits
non-zero, never green it was that two projects shared a directory neither owns, so what this
repository MEASURES could change without a commit here.
The fix is a copy outside both repositories plus a pin this repository tracks. The pin is the whole
point: a copy with no pin is the same shared directory one move further away. So the three states
are separated by construction, and each has its own arm below:
* the copy matches the pin -> it resolves, and that is the only green path;
* the copy is GONE -> ``FrozenBundleMissing`` (an ``OSError``): the gate says
IKKE MÅLT and fails the exit code exactly as it did before this change; the delivered-corpus
tests SKIP, which is MAJOR-3's ceiling rule (a hard error would break ``uv run pytest`` in the
handover archive, where no corpus is mounted);
* the copy DIFFERS from the pin -> ``FrozenBundleDrift`` (a ``ValueError``): loud, named, and
NEVER a skip. A drifted copy is not an unreadable measurement, it is a measurement of the wrong
corpus, which is the one thing that produces a silently wrong number.
The two exception classes are deliberately unrelated: a caller that catches "missing" to skip must
not swallow "drift". ``test_drift_is_not_a_missing_copy`` is that gate.
"""
from __future__ import annotations
import json
import re
import shutil
from pathlib import Path
from typing import Any
import pytest
from portfolio_optimiser import frozen_bundles as fb
from portfolio_optimiser.evals import v1_gate as gate
from portfolio_optimiser.stress import read_bundle_declarations
_REPO = Path(__file__).resolve().parent.parent
#: Joined at run time on purpose: this file NAMES the forbidden path spellings, and a literal
#: would make the gate below red against its own source. (Implicit concatenation is not enough —
#: ``ruff format`` folds ``"a" "b"`` back into one literal, measured here.)
_OTHER_REPO = "-".join(("vegnormal", "okf"))
#: The two spellings a path to that repository's build directory takes in this codebase. Both were
#: present before this change (3 + 4 hits, the known positives recorded in the order's evidence).
#: Each is paired with the line that PROVES it can match: a pattern that matches nothing makes a
#: gate that can only be green, and the two spellings do not match each other's sample.
_FORBIDDEN = (
(
re.compile(re.escape(_OTHER_REPO + "/build")),
f'ROOT = Path("~/repos/{_OTHER_REPO}/build/ferdig")',
),
(
re.compile("[\"']" + re.escape(_OTHER_REPO) + "[\"']"),
'ROOT = Path.home() / "repos" / "' + _OTHER_REPO + '" / "build" / "ferdig"',
),
)
#: Prose that documents history is explicitly allowed by the order; only paths are forbidden.
_SCANNED = ("src", "tests", "contexts")
# ---------------------------------------------------------------------------------------------
# helpers
# ---------------------------------------------------------------------------------------------
def _bundle(root: Path, body: str = "one") -> Path:
root.mkdir(parents=True, exist_ok=True)
(root / "index.md").write_text("# base\n\n- [a](krav/a.md)\n", encoding="utf-8")
(root / "krav").mkdir(exist_ok=True)
(root / "krav" / "a.md").write_text(
f"---\ntype: Krav\ntitle: A\n---\n\n{body}\n", encoding="utf-8"
)
return root
def _store(tmp_path: Path, name: str = "n500-2024", body: str = "one") -> tuple[Path, Path]:
"""A frozen store holding ONE pinned bundle, and the pin file that names it."""
store = tmp_path / "store"
digest, files = fb.digest_bundle(_bundle(tmp_path / "src-of-truth", body))
directory = f"{name}-{digest[: fb.SHORT]}"
_bundle(store / directory, body)
pin = tmp_path / "pin.json"
pin.write_text(
json.dumps(
{
"store": str(store),
"bundles": {name: {"directory": directory, "sha256": digest, "files": files}},
}
),
encoding="utf-8",
)
return store, pin
def _use(monkeypatch: pytest.MonkeyPatch, store: Path, pin: Path) -> None:
monkeypatch.setenv(fb.STORE_ENV, str(store))
monkeypatch.setattr(fb, "PIN_FILE", pin)
def _touch_one_byte(base: Path) -> None:
doc = base / "krav" / "a.md"
doc.write_text(doc.read_text(encoding="utf-8").replace("one", "ONE"), encoding="utf-8")
# ---------------------------------------------------------------------------------------------
# (a)-(b) the digest
# ---------------------------------------------------------------------------------------------
def test_the_digest_covers_every_byte_and_every_name(tmp_path: Path) -> None:
"""Stable across recomputation; moved by one byte AND by a rename that changes no byte —
without the name in the hash, a corpus reshuffled under the same bytes would pin clean."""
base = _bundle(tmp_path / "b")
first, files = fb.digest_bundle(base)
assert (first, files) == fb.digest_bundle(base)
assert files == 2
_touch_one_byte(base)
changed, _ = fb.digest_bundle(base)
assert changed != first
renamed = _bundle(tmp_path / "c")
(renamed / "krav" / "a.md").rename(renamed / "krav" / "b.md")
assert fb.digest_bundle(renamed)[0] != fb.digest_bundle(_bundle(tmp_path / "d"))[0]
def test_a_matching_copy_resolves_to_the_pinned_directory(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
resolved = fb.bundle_dir("n500-2024")
assert resolved.parent == store
assert (resolved / "index.md").is_file()
# ---------------------------------------------------------------------------------------------
# (c)-(e) the three states
# ---------------------------------------------------------------------------------------------
def test_one_changed_byte_is_drift_named_with_both_digests(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
base = fb.bundle_dir("n500-2024") # green before the edit — the control
expected = json.loads(pin.read_text(encoding="utf-8"))["bundles"]["n500-2024"]["sha256"]
_touch_one_byte(base)
with pytest.raises(fb.FrozenBundleDrift) as exc:
fb.bundle_dir("n500-2024")
message = str(exc.value)
assert "avviker fra pin" in message
assert "n500-2024" in message
assert expected[: fb.SHORT] in message # what was pinned
assert fb.digest_bundle(base)[0][: fb.SHORT] in message # what is on disk
def test_a_missing_copy_is_missing_and_stays_an_oserror(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""``measure_stress`` already catches ``OSError`` -> IKKE MÅLT + exit 1; that path is unchanged."""
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
shutil.rmtree(store / fb.load_pins()["n500-2024"].directory)
with pytest.raises(fb.FrozenBundleMissing) as exc:
fb.bundle_dir("n500-2024")
assert isinstance(exc.value, OSError)
assert "n500-2024" in str(exc.value)
def test_drift_is_not_a_missing_copy(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""A caller that catches "missing" in order to SKIP must never swallow drift: skipping on a
wrong corpus is the silent failure this whole change exists to remove."""
assert not issubclass(fb.FrozenBundleDrift, fb.FrozenBundleMissing)
assert not issubclass(fb.FrozenBundleMissing, fb.FrozenBundleDrift)
assert not isinstance(fb.FrozenBundleDrift("x"), OSError)
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
_touch_one_byte(fb.bundle_dir("n500-2024"))
with pytest.raises(fb.FrozenBundleDrift):
try:
fb.bundle_dir("n500-2024")
except fb.FrozenBundleMissing: # pragma: no cover - the defect this arm forbids
pytest.fail("drift was answered as a missing copy")
def test_an_unknown_name_is_refused_by_name(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
with pytest.raises(fb.FrozenBundleMissing) as exc:
fb.bundle_dir("n100-2023")
assert "n100-2023" in str(exc.value) and "n500-2024" in str(exc.value)
def test_an_explicit_override_is_unpinned_and_the_operator_named_it(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""``--bundle-root`` / ``PORTFOLIO_VEGNORMAL_ROOT`` stays an escape hatch: the operator who
names a live mount gets it, pin or no pin. Absent it, the frozen store answers."""
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
live = tmp_path / "live"
_bundle(live / "n500-2024", body="something else entirely")
assert fb.bundle_dir("n500-2024", override=live) == live / "n500-2024"
monkeypatch.setenv(fb.OVERRIDE_ENV, str(live))
assert fb.bundle_dir("n500-2024") == live / "n500-2024"
# ---------------------------------------------------------------------------------------------
# (f)-(g) the tracked pin
# ---------------------------------------------------------------------------------------------
def test_the_pin_names_every_base_the_context_sets_declare() -> None:
declared = {
d["name"]
for path in sorted((_REPO / "contexts").glob("*/bundle.txt"))
for d in read_bundle_declarations(path)
}
assert declared, "no context set declares a base — the denominator would be vacuous"
assert declared <= set(fb.load_pins())
def test_the_pinned_directory_name_carries_the_short_digest() -> None:
"""A stale copy is visible in ``ls``, not only to the verifier."""
pins = fb.load_pins()
assert pins, "the pin file names no bundle"
for name, pin in pins.items():
assert pin.directory == f"{name}-{pin.sha256[: fb.SHORT]}"
assert pin.files > 0
def test_the_bundle_itself_is_never_tracked_here() -> None:
"""Vegnormal corpora must not reach a public remote: only the pin is tracked."""
tracked = (_REPO / "src" / "portfolio_optimiser" / "frozen_bundles.json").read_text("utf-8")
assert "index.md" not in tracked
# ---------------------------------------------------------------------------------------------
# (h) nothing reads the other repository's build directory any more
# ---------------------------------------------------------------------------------------------
def test_no_measurement_reads_the_other_repos_build_directory() -> None:
"""Both spellings, each with a known-positive control: a pattern that cannot match anything
is a gate that can only be green."""
for pattern, known_positive in _FORBIDDEN:
assert pattern.search(known_positive), pattern.pattern
hits = [
f"{path.relative_to(_REPO)}:{n}: {line.strip()}"
for top in _SCANNED
for path in sorted((_REPO / top).rglob("*"))
if path.is_file() and path.suffix in {".py", ".json", ".txt"}
for n, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1)
if any(p.search(line) for p, _ in _FORBIDDEN)
]
assert hits == [], "\n".join(hits)
# ---------------------------------------------------------------------------------------------
# (i)-(j) the gate
# ---------------------------------------------------------------------------------------------
def _evidence(tmp_path: Path) -> tuple[dict[str, Any], Path]:
stress_root = tmp_path / "stress"
(stress_root / "o").mkdir(parents=True)
return {
"label": "s",
"root": "scratchpad",
"runs": [
{
"context": "contexts/tunnel-hauglia-2027",
"outbox": "o",
"run_id": "r",
"bundle": None,
}
],
}, stress_root
def test_a_drifted_copy_fails_the_gate_with_the_reason_said(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
_touch_one_byte(fb.bundle_dir("n500-2024"))
evidence, stress_root = _evidence(tmp_path)
m = gate.measure_stress(evidence, _REPO, stress_root, None)
assert "avviker fra pin" in m.missing
row = gate.score_undeclared(["p"], {"p": "passed"}, m, "s")
assert (row.k, row.status, row.failing) == (None, gate.NOT_MEASURED, True)
assert gate.exit_code([row]) == 1
def test_a_missing_copy_is_not_measured_and_never_green(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
evidence, stress_root = _evidence(tmp_path)
monkeypatch.setenv(fb.STORE_ENV, str(tmp_path / "gone"))
m = gate.measure_stress(evidence, _REPO, stress_root, None)
assert m.missing and m.validated == 0
row = gate.score_undeclared(["p"], {"p": "passed"}, m, "s")
assert (row.status, row.failing) == (gate.NOT_MEASURED, True)
assert gate.exit_code([row]) == 1
# ---------------------------------------------------------------------------------------------
# (k) the delivered-corpus tests: missing SKIPS, drift FAILS
# ---------------------------------------------------------------------------------------------
@pytest.mark.parametrize(
"module,helper",
[
("test_context_sets_loadbearing", "_bundle_dir"),
("test_navigation_window_loadbearing", "_delivered"),
("test_inert_identifier_loadbearing", "_base"),
("test_requirement_number_gate_loadbearing", "_base"),
],
)
def test_the_corpus_tests_skip_when_absent_but_fail_on_drift(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, module: str, helper: str
) -> None:
mod = __import__(module)
resolve = getattr(mod, helper)
store, pin = _store(tmp_path)
_use(monkeypatch, store, pin)
assert resolve("n500-2024").is_dir() # control: the matching copy resolves
_touch_one_byte(fb.bundle_dir("n500-2024"))
# A skip is caught EXPLICITLY, never left to ``pytest.raises``: measured against the mutation
# that makes drift a subclass of missing, these four arms SKIPPED instead of failing (5 -> 9
# skipped over the whole suite) and stayed green — a gate that cannot see the one defect it
# exists for.
try:
resolve("n500-2024")
except fb.FrozenBundleDrift:
pass
except pytest.skip.Exception as exc:
raise AssertionError(f"{module}.{helper} SKIPPED a drifted copy: {exc}") from None
else:
raise AssertionError(f"{module}.{helper} accepted a drifted copy")
monkeypatch.setenv(fb.STORE_ENV, str(tmp_path / "gone"))
with pytest.raises(pytest.skip.Exception):
resolve("n500-2024")

View file

@ -33,11 +33,12 @@ floor, and the composition seam run over synthetic input and are UNCONDITIONAL.
from __future__ import annotations
import json
import os
from pathlib import Path
import pytest
from portfolio_optimiser import frozen_bundles
from portfolio_optimiser import okf
from portfolio_optimiser.ir import AffectedItem, SavingsProposal
from portfolio_optimiser.validator import (
@ -48,7 +49,6 @@ from portfolio_optimiser.validator import (
validate_proposal,
)
_DEFAULT_BUNDLE_ROOT = Path.home() / "repos" / "vegnormal-okf" / "build" / "ferdig"
_A4 = Path(
"scratchpad/p14-stress/kontrakt-sorasen-2027/"
"kontrakt-sorasen-2027-01-a4-indeksregulering-proposal.json"
@ -56,10 +56,15 @@ _A4 = Path(
def _base(name: str) -> Path:
root = Path(os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", str(_DEFAULT_BUNDLE_ROOT)))
if not (root / name).is_dir():
pytest.skip(f"knowledge base {name!r} is not mounted under {root}")
return root / name
"""The FROZEN copy this repository pins, resolved at call time.
Absence SKIPS (MAJOR-3's ceiling: no corpus is mounted in the handover archive), drift is
allowed to propagate and FAIL a measurement of the wrong corpus is not a missing one.
"""
try:
return frozen_bundles.bundle_dir(name)
except frozen_bundles.FrozenBundleMissing as exc:
pytest.skip(str(exc))
def _grounding_over(name: str) -> Grounding:

View file

@ -34,33 +34,29 @@ run over a synthetic base, so this file can never be silently absent in full.
from __future__ import annotations
import json
import os
from pathlib import Path
from typing import Any
import pytest
from portfolio_optimiser import okf
from portfolio_optimiser import frozen_bundles, okf
from portfolio_optimiser.explore import navigator_tools
_DEFAULT_BUNDLE_ROOT = Path.home() / "repos" / "vegnormal-okf" / "build" / "ferdig"
#: S7a-3's ceiling, restated here rather than imported: a gate that imported the implementation's
#: own budget would move with it, and raising the budget is exactly the regression it guards.
_CEILING_CHARS = 1_500
def _root() -> Path:
return Path(os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", str(_DEFAULT_BUNDLE_ROOT)))
def _delivered(name: str) -> Path:
base = _root() / name
if not base.is_dir():
pytest.skip(
f"knowledge base {name!r} is not mounted under {_root()} (PORTFOLIO_VEGNORMAL_ROOT)"
)
return base
"""The FROZEN copy this repository pins, resolved at call time.
Absence SKIPS (MAJOR-3's ceiling: no corpus is mounted in the handover archive), drift is
allowed to propagate and FAIL a measurement of the wrong corpus is not a missing one.
"""
try:
return frozen_bundles.bundle_dir(name)
except frozen_bundles.FrozenBundleMissing as exc:
pytest.skip(str(exc))
def _tools(bundle_dir: Path) -> dict[str, Any]:

View file

@ -55,11 +55,12 @@ What each arm pins:
from __future__ import annotations
import json
import os
from pathlib import Path
import pytest
from portfolio_optimiser import frozen_bundles
from portfolio_optimiser import okf
from portfolio_optimiser.generate import _grounding_text
from portfolio_optimiser.ir import CostBaseline, SavingsProposal
@ -73,16 +74,20 @@ from portfolio_optimiser.validator import (
validate_proposal,
)
_DEFAULT_BUNDLE_ROOT = Path.home() / "repos" / "vegnormal-okf" / "build" / "ferdig"
_ROUND3 = Path("scratchpad/p19-stress/tunnel-hauglia-2027")
_P17B = Path("scratchpad/p17b-multibase/lindaas")
def _base(name: str) -> Path:
root = Path(os.environ.get("PORTFOLIO_VEGNORMAL_ROOT", str(_DEFAULT_BUNDLE_ROOT)))
if not (root / name).is_dir():
pytest.skip(f"knowledge base {name!r} is not mounted under {root}")
return root / name
"""The FROZEN copy this repository pins, resolved at call time.
Absence SKIPS (MAJOR-3's ceiling: no corpus is mounted in the handover archive), drift is
allowed to propagate and FAIL a measurement of the wrong corpus is not a missing one.
"""
try:
return frozen_bundles.bundle_dir(name)
except frozen_bundles.FrozenBundleMissing as exc:
pytest.skip(str(exc))
def _grounding_over(name: str) -> Grounding:

View file

@ -22,6 +22,7 @@ from typing import Any
import pytest
from portfolio_optimiser import frozen_bundles
from portfolio_optimiser.evals import v1_gate as gate
from portfolio_optimiser.validator import UNSUPPORTED_REASON
@ -678,12 +679,12 @@ def test_row6_measures_the_stress_outboxes_when_they_exist(tmp_path: Path) -> No
"""Against the real artefacts when this machine has them; otherwise the absence is named."""
evidence = _CONFIG["stress_evidence"]
root = _REPO / evidence["root"]
bundles = Path("~/repos/vegnormal-okf/build/ferdig").expanduser()
bundles = frozen_bundles.store_root()
if not root.is_dir() or not bundles.is_dir():
m = gate.measure_stress(evidence, _REPO, tmp_path / "absent", bundles)
m = gate.measure_stress(evidence, _REPO, tmp_path / "absent", None)
assert m.missing and m.validated == 0
pytest.skip(f"stress artefacts not mounted ({root}, {bundles})")
m = gate.measure_stress(evidence, _REPO, root, bundles)
m = gate.measure_stress(evidence, _REPO, root, None)
if m.missing:
# The mount belongs to another repository and can be mid-rebuild; the gate then says
# "ikke målt", which test_row6_missing_artefacts_are_never_zero already pins.