Skip to content

Commit 3127595

Browse files
committed
fix: stop the portability audit from failing renders over their own tests
The final audit walked the whole build folder and treated any codeplain-tty reference as a violation, on the stated assumption that internal tests live outside it. They do not: a module's build folder carries a conformance_tests/ subtree, and those tests drive the helper because that is what it is for. So CreateDist raised PlatformBoundaryViolation *after* the render succeeded. The build was never copied, run_state.render_generated_code_path stayed empty, and the harness fell back to whatever tree it could find. Run against the cli-password-manager artifact from codeplain-tty-capability-run2, the audit flags four files, all of them conformance tests — which is why that render reported 22 functionalities in 48m54s and delivered a build with no CLI entry point, and why code_retrieval_example scored 0/10 with generated_code=- in the wave2 re-baseline. Two changes: - Internal test trees (conformance_tests, acceptance_tests, dist_conformance_tests) are exempt from the audit. Delivered code beside them is still audited — a test asserted for that explicitly. - The exit summary and the render trailer now report an error whenever there is one, not only when the render failed. A render that completes its functionalities and then raises on the way out printed a success banner, logged no reason at all, and exited 1 — which is exactly how this went unnoticed across a whole benchmark run.
1 parent 801d892 commit 3127595

4 files changed

Lines changed: 55 additions & 6 deletions

File tree

cli_output/render_summary.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ def print_exit_summary(
3535
msg += format_usage_summary(run_state.rendered_functionalities, run_state.render_time_accumulated) + "\n"
3636
console.print(msg)
3737

38-
if not run_state.render_succeeded and error_message:
38+
# Reported whenever there is one. A render can finish its functionalities and still
39+
# raise on the way out — publishing the build, for instance — and that combination
40+
# used to print the success banner and swallow the reason entirely, leaving a caller
41+
# with a tick mark and a non-zero exit code.
42+
if error_message:
3943
console.error(error_message)
4044
console.quiet = True
4145

@@ -70,7 +74,7 @@ def log_render_trailer(
7074
f"generated_code={run_state.render_generated_code_path or '-'} "
7175
f"spec={spec_filename}"
7276
)
73-
if outcome == "failed" and error_message:
77+
if error_message:
7478
logger.error(f"{RENDER_TRAILER_PREFIX} error={error_message}")
7579

7680
# The process may exit immediately after this; an unflushed trailer would defeat the

render_machine/platform_test_audit.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
application must run in a clean environment where none of Codeplain's test tooling
88
exists.
99
10-
Internal conformance and acceptance tests live outside the build folder (in the
11-
module's tests tree), so nothing here needs an allowlist: any hit inside the build
12-
folder is a violation.
10+
Internal conformance and acceptance tests are exempt. They are what the helper exists
11+
for, and they do turn up inside the audited tree — a module's build folder can carry a
12+
`conformance_tests/` subtree, and benchmark renders showed the audit failing them.
13+
Auditing those is not a stricter boundary, it is a false one: it aborts a successful
14+
render over test code that is never delivered.
1315
"""
1416

1517
import os
@@ -22,6 +24,11 @@
2224
# Directories that carry no delivered source and may be large.
2325
SKIPPED_DIRECTORIES = {".git", ".venv", "node_modules", "__pycache__", ".tmp", "dist", "build", "target"}
2426

27+
# Internal test trees, which are allowed to drive the helper and are never delivered.
28+
# Named separately from the above because skipping them is a boundary decision, not a
29+
# performance one.
30+
INTERNAL_TEST_DIRECTORIES = {"conformance_tests", "acceptance_tests", "dist_conformance_tests"}
31+
2532
MAX_AUDITED_FILE_BYTES = 4 * 1024 * 1024 # a delivered source file larger than this is not source
2633

2734

@@ -33,7 +40,9 @@ def find_platform_references(build_folder: str) -> List[str]:
3340
"""Build-folder-relative paths of files referencing the platform test helper."""
3441
violations = []
3542
for root, directories, file_names in os.walk(build_folder):
36-
directories[:] = [name for name in directories if name not in SKIPPED_DIRECTORIES]
43+
directories[:] = [
44+
name for name in directories if name not in SKIPPED_DIRECTORIES and name not in INTERNAL_TEST_DIRECTORIES
45+
]
3746
for file_name in file_names:
3847
path = os.path.join(root, file_name)
3948
relative = os.path.relpath(path, build_folder)

tests/test_platform_test_audit.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,28 @@ def test_vendor_directories_are_not_audited(tmp_path):
4343
(tmp_path / "app.js").write_text("console.log('clean');\n")
4444

4545
audit_build_folder(str(tmp_path)) # does not raise
46+
47+
48+
def test_internal_test_trees_inside_the_build_folder_are_exempt(tmp_path):
49+
"""A module's build folder can carry its conformance tests, and those are what the
50+
helper exists for. Auditing them aborted successful benchmark renders at CreateDist:
51+
the build was never published, `generated_code` stayed empty, and the delivered
52+
artifact was whatever the harness could salvage."""
53+
(tmp_path / "conformance_tests" / "init").mkdir(parents=True)
54+
(tmp_path / "conformance_tests" / "init" / "test_init.py").write_text(
55+
"subprocess.run(['codeplain-tty', 'wait-for', 'Password:'])\n"
56+
)
57+
(tmp_path / "conformance_tests" / "conformance_tests.json").write_text('{"codeplain-tty": true}\n')
58+
(tmp_path / "vault.py").write_text("print('hello')\n")
59+
60+
assert find_platform_references(str(tmp_path)) == []
61+
audit_build_folder(str(tmp_path)) # does not raise
62+
63+
64+
def test_delivered_code_is_still_audited_alongside_them(tmp_path):
65+
"""Exempting the test tree must not exempt the application beside it."""
66+
(tmp_path / "conformance_tests").mkdir()
67+
(tmp_path / "conformance_tests" / "test_init.py").write_text("codeplain-tty wait-for\n")
68+
(tmp_path / "vault.py").write_text("os.environ['CODEPLAIN_TTY_ENDPOINT']\n")
69+
70+
assert find_platform_references(str(tmp_path)) == ["vault.py"]

tests/test_render_trailer.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,14 @@ def test_the_trailer_is_flushed_so_it_survives_an_abrupt_exit():
9999
logger.removeHandler(handler)
100100

101101
assert handler.flush.called
102+
103+
104+
def test_a_completed_render_that_still_raised_reports_the_reason(trailer_lines):
105+
"""A render can finish its functionalities and raise on the way out — publishing the
106+
build, for instance. That combination printed a success banner, logged no reason, and
107+
exited non-zero, which is how a boundary-audit failure went unnoticed across a whole
108+
benchmark run."""
109+
lines = trailer_lines(run_state(succeeded=True), error_message="The generated build references ...")
110+
111+
assert any("outcome=completed" in line for line in lines)
112+
assert any("error=The generated build references ..." in line for line in lines)

0 commit comments

Comments
 (0)