feat(propose): --outline-run selects Arm D, default 0 is off

This commit is contained in:
Kjell Tore Guttormsen 2026-09-07 01:34:59 +02:00
commit 6e2238454c
2 changed files with 146 additions and 0 deletions

View file

@ -929,3 +929,126 @@ def test_the_outline_rule_is_off_at_the_function_level_by_default() -> None:
assert default == explicit_zero == []
# The known-positive control: the same text DOES produce candidates when asked.
assert len(okf_propose_segments.find_candidates(ALL_THREE_INTEGER_FORMS, outline_run=3)) == 3
# --- Arm D: the CLI flag ---------------------------------------------------
def propose_arm_d(tmp_path: Path, text: str, run_length: int, name: str = "arm-d.md") -> dict:
source = write(tmp_path, text, name)
out = tmp_path / "arm-d-cli.json"
code = okf_propose_segments.main(
[str(source), "--out", str(out), "--outline-run", str(run_length)]
)
assert code == 0, f"proposer exited {code}"
return json.loads(out.read_text(encoding="utf-8"))
def test_outline_run_zero_is_byte_identical_to_the_flag_being_absent(tmp_path: Path) -> None:
"""The default profile is a promise; 0 must not be a different code path."""
source = write(tmp_path, ALL_THREE_INTEGER_FORMS, "same.md")
without = tmp_path / "without.json"
with_zero = tmp_path / "with-zero.json"
assert okf_propose_segments.main([str(source), "--out", str(without)]) == 1
assert (
okf_propose_segments.main([str(source), "--out", str(with_zero), "--outline-run", "0"]) == 1
)
# Exit 1 both times: this text has no Arm B boundary at all, so neither run
# writes an artifact. The known-positive control that the text is not inert:
assert (
okf_propose_segments.main(
[str(source), "--out", str(tmp_path / "on.json"), "--outline-run", "3"]
)
== 0
)
def test_the_two_arms_are_independent(tmp_path: Path) -> None:
"""`--outline-run 0` leaves Arm C's artifact untouched, and vice versa."""
source = write(tmp_path, STRUCTURED_WITH_A_LONG_TAIL, "both.md")
arm_c_only = tmp_path / "c.json"
arm_c_and_zero = tmp_path / "cz.json"
assert (
okf_propose_segments.main(
[str(source), "--out", str(arm_c_only), "--max-segment-chars", "2000"]
)
== 0
)
assert (
okf_propose_segments.main(
[
str(source),
"--out",
str(arm_c_and_zero),
"--max-segment-chars",
"2000",
"--outline-run",
"0",
]
)
== 0
)
assert arm_c_only.read_bytes() == arm_c_and_zero.read_bytes()
def test_a_negative_outline_run_is_refused_by_the_tool_not_by_argparse(
tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""Exit 2 alone cannot separate the two refusals -- argparse exits 2 too.
`FAILED` is the tool's own two-line failure form, so asserting it is what
proves the refusal came from `run` and not from the parser.
"""
source = write(tmp_path, ALL_THREE_INTEGER_FORMS)
code = okf_propose_segments.main(
[str(source), "--out", str(tmp_path / "x.json"), "--outline-run", "-1"]
)
assert code == 2
err = capsys.readouterr().err
assert "FAILED" in err
assert "outline-run" in err
def test_a_non_integer_outline_run_is_refused_by_argparse(
tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
"""The other exit-2 path, so the two cannot be satisfied by one branch."""
source = write(tmp_path, ALL_THREE_INTEGER_FORMS)
with pytest.raises(SystemExit) as exit_info:
okf_propose_segments.main(
[str(source), "--out", str(tmp_path / "x.json"), "--outline-run", "three"]
)
assert exit_info.value.code == 2
assert "usage:" in capsys.readouterr().err
def test_the_help_attributes_arm_d_inside_its_own_option_chunk(
capsys: pytest.CaptureFixture[str],
) -> None:
"""The attribution must sit in the `--outline-run` help, not merely in the file.
Sliced between option headers on purpose: a whole-output grep would be
satisfied by adding the literal to Arm C's block, which would attribute the
wrong rule. And the squeeze is `tr -s '[:space:]'`, not a newline swap --
argparse wraps its help, so a newline-only normalisation leaves the run of
spaces behind and the literal stays unfindable.
"""
with pytest.raises(SystemExit) as exit_info:
okf_propose_segments.main(["--help"])
assert exit_info.value.code == 0
squeezed = " ".join(capsys.readouterr().out.split())
# Drop the usage line: it repeats every option name, so slicing the whole
# output would find two `outline-run` chunks and neither would be the help.
assert "options:" in squeezed
options = squeezed.split("options:", 1)[1]
chunks = options.split(" --")
outline_chunk = [c for c in chunks if c.startswith("outline-run")]
assert len(outline_chunk) == 1, f"expected exactly one chunk, got {len(outline_chunk)}"
assert "not defined upstream" in outline_chunk[0]
# The negative half: Arm C's chunk must NOT carry the literal, or the
# attribution would name the wrong rule while the grep still passed.
arm_c_chunk = [c for c in chunks if c.startswith("max-segment-chars")]
assert len(arm_c_chunk) == 1
assert "not defined upstream" not in arm_c_chunk[0]
# The whole-output count must also be 1: the literal belongs to Arm D alone.
assert squeezed.count("not defined upstream") == 1