test(accounting): a document refused whole is never clean (H1, red)
PM's checkpoint of ed8d9d7 measured it: an inbox holding one refused
document and one accepted one gave `clean = 4 of 4`, `refused_whole =
None` and `okf build` exit 0, while three elements of `avvist.html`
were gone unseen. `refused_whole` asks its question only when the
corpus persisted NOTHING, and a refused document's own unit balances
by construction -- every element booked as a coded rejection is u = 0
and d = 0.
Three tests, all red on the claim and not on an import:
- the unit of a document the build refused is not clean, and its note
names the code;
- the same beside a PERSISTED neighbour, which is the ordinary case on
a heterogeneous corpus, with row 3 RED and the source named in the
detail line;
- `okf build`'s own report says how many of M documents it refused
whole -- the exit code belongs to the whole run, so the count has to
stand in the accounting and in `log.md` or the loss is silent.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3b3b8ae0ca
commit
5d1060d467
2 changed files with 64 additions and 2 deletions
|
|
@ -647,7 +647,10 @@ def test_everything_rejected_is_never_clean_for_a_document_the_build_persisted(
|
|||
assert "persisted" in "; ".join(unit.notes)
|
||||
|
||||
|
||||
def test_everything_rejected_is_clean_for_a_document_the_build_refused(tmp_path: Path) -> None:
|
||||
def test_a_document_refused_whole_is_never_clean(tmp_path: Path) -> None:
|
||||
"""H1, measured by PM 2026-09-18: a document the build refused books every
|
||||
element as a coded rejection, so u = 0 and d = 0 and the unit read CLEAN.
|
||||
The fate is honest and the content is gone; the gate has to say both."""
|
||||
declared = _all_carried()
|
||||
declared["documents"][0]["status"] = "rejected"
|
||||
declared["documents"][0]["code"] = "fail_secure"
|
||||
|
|
@ -658,7 +661,47 @@ def test_everything_rejected_is_clean_for_a_document_the_build_refused(tmp_path:
|
|||
unit = gate.account(
|
||||
_inventory(), _build(accounting=declared, sources=set()), _corpus(tmp_path)
|
||||
)[0]
|
||||
assert unit.clean
|
||||
assert not unit.clean
|
||||
assert unit.refused == 3
|
||||
assert "fail_secure" in "; ".join(unit.notes)
|
||||
|
||||
|
||||
def test_a_document_refused_whole_is_not_made_clean_by_the_neighbour(tmp_path: Path) -> None:
|
||||
"""H1 in the shape the po scenario meets it: ONE refused source beside an
|
||||
accepted one. `refused_whole` asks its question only when the corpus
|
||||
persisted NOTHING, so the partial case reached row 3 as `clean = 4 of 4`
|
||||
with `okf build` exiting 0 and three elements gone unseen."""
|
||||
inventory = _inventory()
|
||||
inventory["documents"]["b.md"] = {
|
||||
"suffix": ".md",
|
||||
"elements": {"heading": 1},
|
||||
"texts": {"heading": [["Refused"]]},
|
||||
"images": [],
|
||||
}
|
||||
declared = _all_carried()
|
||||
declared["documents"].append(
|
||||
{
|
||||
"source_file": "b.md",
|
||||
"status": "rejected",
|
||||
"code": "fail_secure",
|
||||
"inventory": {"heading": 1},
|
||||
"fates": {"heading": {"rejected": {"fail_secure": 1}}},
|
||||
}
|
||||
)
|
||||
declared["files"][0]["fate"] = "carried"
|
||||
build = _build(
|
||||
accounting=declared,
|
||||
sources={"a.md"},
|
||||
assets=_assets(_corpus(tmp_path) / "graphics" / "x.png"),
|
||||
)
|
||||
units = gate.account(inventory, build, tmp_path)
|
||||
refused = next(u for u in units if u.name == "b.md")
|
||||
assert gate.refused_whole(inventory["documents"], build) is None, "the corpus is not refused"
|
||||
assert not refused.clean
|
||||
assert (refused.name, refused.refused) == ("b.md", 1)
|
||||
row = gate.row3(units, door=True)
|
||||
assert row.status == gate.RED
|
||||
assert any("b.md" in detail and "fail_secure" in detail for detail in row.details)
|
||||
|
||||
|
||||
def test_a_rejection_code_outside_the_closed_list_is_never_clean(tmp_path: Path) -> None:
|
||||
|
|
|
|||
|
|
@ -281,6 +281,25 @@ def test_a_rejected_documents_elements_carry_its_code(tmp_path: Path) -> None:
|
|||
]
|
||||
|
||||
|
||||
def test_a_partly_refused_corpus_says_how_many_sources_it_lost(tmp_path: Path) -> None:
|
||||
"""H1's other half. The gate judges the report; this pins what the report
|
||||
SAYS. One refused source beside an accepted one exits 0 -- the exit code
|
||||
belongs to the whole run and a corpus with an unreadable file in it is the
|
||||
ordinary case -- so the count has to stand in the accounting and the log,
|
||||
or the loss is silent."""
|
||||
inbox = tmp_path / "inbox"
|
||||
inbox.mkdir()
|
||||
shutil.copy(REJECTED / "avvist.html", inbox / "avvist.html")
|
||||
shutil.copy(CORPUS / "notat.md", inbox / "notat.md")
|
||||
path = tmp_path / "a.json"
|
||||
code, bundle, _ = _build(inbox, tmp_path, "--accounting", str(path))
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
log = (bundle / "log.md").read_text(encoding="utf-8")
|
||||
assert code == 0, "the build persisted a document; the exit code is the run's"
|
||||
assert data["refused"] == 1
|
||||
assert "1 of 2 document(s) refused whole" in log
|
||||
|
||||
|
||||
def test_a_lost_paragraph_is_found_and_fails_the_build(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue