refactor(examples): replace sector-specific example material with generic, fictitious examples

The context sets, the packaged knowledge bases and the example bundles are
replaced by one fictitious example set about IT operations in an invented
organisation: three context sets (serverrom-2027, driftsavtale-2027 and the
two-base drift-og-avtale-2027), two synthetic knowledge bases under
src/portfolio_optimiser/data/kunnskapsbaser and two example bundles under
src/portfolio_optimiser/data/bundles. Numbers, codes and structural values in
tests and fixtures are kept; names, ids and wording change. Dated measurement
documents that only recorded runs on the replaced material are deleted.

Gate figures measured on the new set are not comparable with earlier ones.
The exclusion gate from the previous commit is green: 0 tracked files hit
outside the shared/ subtree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-23 15:04:21 +02:00
commit 37547fe292
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
1147 changed files with 24138 additions and 9503 deletions

View file

@ -17,24 +17,26 @@ and the set's own ``mandate.json`` / ``fasit.json`` / ``bundle.txt``.
**THE ORDER'S (a) WAS VACUOUS AS WRITTEN, AND THE DEVIATION IS MEASURED, NOT CHOSEN.** The order
defines grounded as "a ``must_cite`` path was OPENED *or* CITED". But on the S2c navigation path
``run_project`` stamps ``citations = bundle_citations(bundle)``, which is one citation PER CONTEXT
FILE - the whole corpus. Measured on n100-2023: 446 context files, 446 citations, and **6 of 6
fasit paths already "cited" before a single model call**. A judge honouring that literally would be
a gate that can only be green - the repo's own vacuous-gate class, inside the gate built to catch
it. So a CITATION grounds an approach only when the citation list is NARROWER than the base (a
declared pre-pass cut, where the stamp really does name what was read). Both halves are reported
either way (``opened`` / ``cited`` / ``citation_scope``), so which one fired stays readable.
FILE - the whole corpus. Measured on a requirements base during development: 446 context files,
446 citations, and **6 of 6 fasit paths already "cited" before a single model call**. A judge
honouring that literally would be a gate that can only be green - the repo's own vacuous-gate
class, inside the gate built to catch it. So a CITATION grounds an approach only when the citation
list is NARROWER than the base (a declared pre-pass cut, where the stamp really does name what was
read). Both halves are reported either way (``opened`` / ``cited`` / ``citation_scope``), so which
one fired stays readable.
**(b') was checked for the same vacuity and is CLEAN for the N corpora, so the order stands.**
``bundle_citations`` snippets are concept BODIES while ``ref``/``title`` live in FRONTMATTER:
measured 0 of 446 n100 bodies contain ``Krav 4.1.2-1``. ``named_in_measure`` / ``named_in_snippet``
are still reported apart, because the measure is the model's own prose and a snippet is the base's.
**(b') was checked for the same vacuity and is CLEAN for the requirement bases, so the order
stands.** ``bundle_citations`` snippets are concept BODIES while ``ref``/``title`` live in
FRONTMATTER: measured 0 of 446 bodies of that base contain its ``Krav 4.1.2-1``.
``named_in_measure`` / ``named_in_snippet`` are still reported apart, because the measure is the
model's own prose and a snippet is the base's.
**P18/C2 (PM decision, P16 § 6.2): the snippet arm counts only under a NARROWED scope, as (a)
does.** The paragraph above holds for a reference like ``Krav 4.1.2-1``, which no body repeats — it
does NOT hold for R761, where a process number such as ``12.1`` stands in the bodies themselves.
Under a whole-base citation list that mark is "cited" before any model call, so the row was
``named`` for a run in which the model had said nothing of the kind. The scope gate is the same
correction (a) already carries, applied to the half that was still exposed.
does NOT hold for a process catalogue, where a process number such as ``12.1`` stands in the
bodies themselves. Under a whole-base citation list that mark is "cited" before any model call, so
the row was ``named`` for a run in which the model had said nothing of the kind. The scope gate
is the same correction (a) already carries, applied to the half that was still exposed.
**A DENOMINATOR, ALWAYS** (Verifiseringsloven ansikt 4). Every verdict names how many tool calls,
citations, approach rows and base concepts it saw, and an outbox with no proposal artefact - or a
@ -305,14 +307,14 @@ def score_context_set(
CLI resolves it from ``--bundle-root`` plus the set's own ``bundle.txt`` name).
``bundle_id`` RESTRICTS the judgement to the approaches a multi-base set routed at THIS base
(P17b DEL 2). Without it, judging a two-base set's n200 outbox would report the r761 approach
as ``not_evaluated`` with reason ``absent`` — a false finding, because that approach WAS
evaluated, against the other base, under the other ``run_id``. ``None`` keeps every single-base
set judged exactly as before, which is why this is a restriction rather than a new mode: the
order offered a ``--multibase`` summary reader, and MEASURED against the shape the artefacts
actually take, the per-base run already has its own full artefact set and its own run_id — so
what the judge was missing was not a new file to read but the one thing the mandate already
knows, namely which approaches belong here."""
(P17b DEL 2). Without it, judging a two-base set's requirements-base outbox would report the
process-catalogue approach as ``not_evaluated`` with reason ``absent`` — a false finding,
because that approach WAS evaluated, against the other base, under the other ``run_id``.
``None`` keeps every single-base set judged exactly as before, which is why this is a
restriction rather than a new mode: the order offered a ``--multibase`` summary reader, and
MEASURED against the shape the artefacts actually take, the per-base run already has its own
full artefact set and its own run_id — so what the judge was missing was not a new file to read
but the one thing the mandate already knows, namely which approaches belong here."""
context = Path(context_dir)
outbox = Path(outbox_dir)
base = Path(bundle_dir)
@ -330,8 +332,8 @@ def score_context_set(
baseline = okf.load_optional_cost_baseline(str(base))
baseline_codes = set(baseline.items) if baseline is not None else set()
# P21 B3: the PROJECT's own price schedule, which is where the prices live — a road normal
# carries requirements and no amounts, so the ``load_optional_cost_baseline`` above finds
# P21 B3: the PROJECT's own price schedule, which is where the prices live — a requirements
# base carries requirements and no amounts, so the ``load_optional_cost_baseline`` above finds
# nothing on every one of the four bases (measured). Read from the SET, which is the same file
# the run is given with ``--cost-baseline``, and read whether or not the run was anchored: that
# is what lets rounds written before the schedule existed be re-judged with this instrument.
@ -474,10 +476,11 @@ def score_context_set(
named_in_measure = any(m in measure for m in marks)
# P18/C2 (PM decision, P16 § 6.2): the snippet arm counts ONLY under a narrowed citation
# scope, exactly as (a) does. A whole-base citation list is stamped by ``bundle_citations``
# before a single model call — measured on n100, 446 context files, 446 citations, 6 of 6
# fasit paths "cited" for free — so a mark found in THOSE snippets is evidence about the
# base's contents, not about this run. Measured on r761: ``12.1`` appears in whole-base
# snippets and gave this row ``named`` without the model having said anything.
# before a single model call — measured on a requirements base, 446 context files, 446
# citations, 6 of 6 fasit paths "cited" for free — so a mark found in THOSE snippets is
# evidence about the base's contents, not about this run. Measured on a process catalogue:
# ``12.1`` appears in whole-base snippets and gave this row ``named`` without the model
# having said anything.
named_in_snippet = scope == "narrowed" and any(m in snippets for m in marks)
codes = [str(i.get("code", "")) for i in proposal.get("affected_items", [])]