P18 parts B and C (order 20260914T105139Z).
B1 -- stage 0b. P7 made it `item.code in grounding`: plain containment over
ONE concatenated string. P16 ran it against a delivered corpus and measured
what containment cannot tell apart: the falsification arm a4-indeksregulering
put 250 000 NOK on a single cost line coded R761 -- the knowledge base's OWN
NAME, carried by all 2 756 of its concept documents -- and the whole gate
said validated (stage 0 skipped, un-anchored run; checker approve).
The grounding is now carried as the DOCUMENTS it is made of (validator.
Grounding), not as a blob. A structure and not a second argument beside the
text: the boundaries and the text are one fact, and .text is derived, so the
gate and P8's report measure the same characters. run.py composes one
document per concept file where the base is already walked; generate.
_grounding_text folds each cost line in as a one-line document.
N and A are MEASURED, not chosen (14.09, four mounted vegnormal bases):
- every must_cite ref and mandate affected_code in the four context sets --
shortest real identifier is FOUR characters (12.1, 52.1), so N = 3 sits one
below the measurement and cannot refuse anything measured;
- document frequency of every code-shaped token per base -- 1 692 distinct
and NOT ONE reaches 5 %. Highest anywhere 6/446 (1.35 %), highest a fasit
names 3/446 (0.67 %), R761 2 756/2 756 (100 %). A = 0.05 therefore sits
3.7x above the highest real token and 20x below the defect.
Length is NOT what makes the defect inert (R761 is four characters); the
share is. And a share is not a measurement without a denominator big enough
to take one (ansikt 4): one of three is 33 %, so an ABSOLUTE floor of 10
documents gates it. Highest absolute count any real identifier reaches is 6,
and every fixture in the repo is far below 10 -- which is why every pre-P18
gate is UNTOUCHED by this rule rather than exempted from it. Grounding.of
(one document) can never reach the floor by construction.
The refusal NAMES the denominator ("appears in 2756 of the 2756 documents
this run was given"), because Step 5 feeds that reason verbatim into the next
attempt's prompt: a proposer told only "ungrounded" answers with another
token of the same kind.
B2 SPIKE (measured, NOT built) FELLED the order's own alternative: option (b)
"ground in what the run OPENED" was run over P16's 16 code rows -- R761
stands in every OPENED document too, so (b) would NOT have caught the defect,
while B1 makes it inert and still grounds the real process line 65
ASFALTDEKKER (29/2756 = 1.05 %). (b) is not a substitute for B1.
C1 -- --docs-dir is optional once --bundle-dir is given (P16 FUNN 2). On the
bundle path docs_dir is never read: retrieval, the chunk tool and the "no
citable content" check all live in the road branch. Bound ONCE from
--bundle-dir, which is byte-identically what the README already tells an
operator to type by hand. NOT the "--docs-dir omvei": no such path is opened
and the road branch still refuses without a real --docs-dir (own arm).
C2 -- the judge's snippet arm counts only under citation_scope == "narrowed",
as (a) already does (PM decision, P16 s 6.2). P16's reason for (b') being
clean -- snippets are bodies while ref/title live in frontmatter, 0 of 446
n100 bodies -- holds for "Krav 4.1.2-1" but NOT for R761, where a process
number like 12.1 stands in the bodies. Under a whole-base citation list that
mark was "cited" before any model call.
tests: test_inert_identifier_loadbearing.py (7 arms; known positive is P16's
OWN artefact replayed against the base that run was given, known negative is
26 of 26 fasit references still grounding), test_docs_dir_optional_
loadbearing.py (5 arms). test_stress_judge_loadbearing.py's snippet arm split
into narrowed/whole-base -- the pair is the discriminator, same snippet, same
mark, only the scope differs. The grounding tests migrate from str to
Grounding.of (the honest reading of a caller that declared no boundaries).
Verification: uv run pytest -q 1698 passed / 5 skipped (1685 after part A,
strict superset, 0 removed). ruff check + format clean, mypy clean (38
files). Golden demo-transcript.stdout BYTE-UNCHANGED, shasum -a 1 of the
CONTENT = ea8c534773acdbe41ae68f2c55724d69aaf8be4f. No version bump, no push.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
108 lines
4.4 KiB
Python
108 lines
4.4 KiB
Python
"""P18/C1 — ``--docs-dir`` is optional once ``--bundle-dir`` is given.
|
|
|
|
P16 FUNN 2: the documented stress command names the same directory twice
|
|
(``--docs-dir <base> --bundle-dir <base>``), because single-project mode demanded ``--docs-dir``
|
|
even on the bundle path — where it is never read. Retrieval, the chunk tool and the "no citable
|
|
content" check all live in the ROAD branch (``run.py``); the bundle branch builds its citations
|
|
from the navigated base. So the flag was required for a path that ignores it, and the published
|
|
command had to satisfy the requirement by repeating itself.
|
|
|
|
**This is not the "--docs-dir omvei"** (feeding project documents through retrieval INSTEAD of
|
|
ingesting them into a knowledge base), which STATE forbids and this order forbids again. No such
|
|
path is opened: the road branch still refuses without a real ``--docs-dir``, and the value is
|
|
bound ONCE from ``--bundle-dir`` — byte-identically what the README already tells an operator to
|
|
type by hand, so every existing invocation, the two-flag form included, is unchanged.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from portfolio_optimiser import run
|
|
|
|
_FIXTURES = Path(__file__).parent / "fixtures"
|
|
_PRICED = _FIXTURES / "k2-prisskjema-SYNTETISK"
|
|
_IR_PROJECTION = {
|
|
"project_id": "K2",
|
|
"measure": "energy_efficiency",
|
|
"claimed_saving_nok": 1000.0,
|
|
"affected_codes": ["01.1"],
|
|
}
|
|
|
|
|
|
def _runnable(tmp_path: Path) -> str:
|
|
root = tmp_path / "base"
|
|
shutil.copytree(_PRICED, root)
|
|
(root / "validator-input.json").write_text(json.dumps(_IR_PROJECTION), encoding="utf-8")
|
|
return str(root)
|
|
|
|
|
|
def test_a_bundle_run_needs_no_docs_dir(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
|
|
"""(a) The fix. A free dry run on ``--bundle-dir`` alone is ACCEPTED and reaches the bundle
|
|
path — asserted on the run-config the dry run prints, not on rc alone, since rc 0 is also what
|
|
a run that silently took the road path would return."""
|
|
rc = run.main(["K2", "--bundle-dir", _runnable(tmp_path), "--live-dry-run"])
|
|
|
|
assert rc == 0
|
|
assert "LIVE-DRY-RUN OK" in capsys.readouterr().out
|
|
|
|
|
|
def test_the_documented_two_flag_form_still_works(
|
|
tmp_path: Path, capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
"""(b) The CONTROL that this is a widening, not a change. The README's form — the same
|
|
directory twice — must be byte-for-byte as accepted as it was before."""
|
|
base = _runnable(tmp_path)
|
|
rc = run.main(["K2", "--docs-dir", base, "--bundle-dir", base, "--live-dry-run"])
|
|
|
|
assert rc == 0
|
|
assert "LIVE-DRY-RUN OK" in capsys.readouterr().out
|
|
|
|
|
|
def test_neither_flag_is_still_refused_by_name(capsys: pytest.CaptureFixture[str]) -> None:
|
|
"""(c) The half that must NOT be relaxed: the road path has no base to fall back to, so an
|
|
argv naming neither is refused, and the refusal names BOTH doors rather than only the one it
|
|
used to name."""
|
|
rc = run.main(["K2", "--live-dry-run"])
|
|
|
|
assert rc == 1
|
|
err = capsys.readouterr().err
|
|
assert "run refused" in err and "--docs-dir" in err and "--bundle-dir" in err
|
|
|
|
|
|
def test_the_road_path_still_requires_a_real_docs_dir(
|
|
tmp_path: Path, capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
"""(d) The anti-omvei arm. With no bundle, ``--docs-dir`` is still the only door AND it is
|
|
still read: a directory holding nothing citable is refused by the road branch's own check, so
|
|
nothing here turns retrieval into a substitute for ingestion."""
|
|
empty = tmp_path / "tomt"
|
|
empty.mkdir()
|
|
rc = run.main(["P1", "--docs-dir", str(empty), "--live-dry-run"])
|
|
|
|
assert rc == 1
|
|
assert capsys.readouterr().err.strip(), "the road path must say why, not fail silently"
|
|
|
|
|
|
def test_the_bundle_value_is_bound_once_and_reaches_run_project(
|
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
) -> None:
|
|
"""(e) The SEAM. rc 0 above would also be satisfied by a CLI that never forwarded the value, so
|
|
the argument ``run_project`` actually receives is recorded — one binding, both dispatch sites."""
|
|
base = _runnable(tmp_path)
|
|
seen: dict[str, Any] = {}
|
|
|
|
async def _record(project_id: str, profile: Any, **kw: Any) -> Any:
|
|
seen.update(kw)
|
|
raise SystemExit(0)
|
|
|
|
monkeypatch.setattr("portfolio_optimiser.run.run_project", _record)
|
|
with pytest.raises(SystemExit):
|
|
run.main(["K2", "--bundle-dir", base, "--live-dry-run"])
|
|
|
|
assert seen["docs_dir"] == base == seen["bundle_dir"]
|