McRogueFace/api/manifest.json

1 line
126 KiB
JSON
Raw Normal View History

test(snippets): the docs site's 130 code samples are now part of the test suite The samples published on mcrogueface.github.io were executed by nothing at all. Each carried a machine-readable header -- objects=[...] verified=0.2.8@b6720f6 status=ok -- and every one of those fields was hand-typed. 130 snippets asserted "status=ok" while no run had ever confirmed it. This is the same failure mode as the 82 rotted tests in 112f357, at a larger scale and with no gate whatsoever. The samples now live here, in the engine repo, so that breaking the API breaks the build. The site pulls them from tests/snippets/ rather than keeping a copy to rot in parallel (build_library.py, site-side). They are display scripts: each builds a scene and stops. They deliberately do NOT call sys.exit(), because they must stay copy-pasteable -- a reader who pastes one into their game should get a running scene, not an interpreter that quits. Since #350 that also makes them un-runnable on their own, so _harness.py is chained as a second --exec to supply the ending the snippet must not have. Chaining rather than exec()-ing the source is deliberate: the snippet travels the same path a real user's script travels, and nothing has to read the file -- which is how the first draft of this harness tripped over #378 and mistook three healthy snippets for broken ones. A snippet passes only if it runs clean AND leaves a scene with something in it. Not raising is not enough: a sample whose body silently no-ops still renders as code on the docs site, and would still be wrong. tools/stamp_snippets.py makes the header a measurement instead of a claim: status comes from an actual run, verified from the engine that ran it, and objects is derived from the source intersected with what the engine exports -- so a snippet that starts using a new type gets tagged for it without anyone remembering to. It immediately found tags the humans had missed (062 uses Transition, Key and InputState; the hand-written header listed none of them). --check is the CI gate. The gate earned its keep on the first run, catching #379 (fixed here): configuring default_transition before the first scene activation made the engine transition FROM the internal "uitest" bootstrap scene, which is not a PyScene and has no Python wrapper -- so mcrfpy.current_scene reported None for the transition's full duration, immediately after the user had assigned it. A transition with nothing meaningful to transition from now changes scene immediately. Scene-to-scene transitions still report the outgoing scene until they complete. Suite: 468/468 (336 + 130 snippets + 2 regressions). closes #379
2026-07-14 18:29:37 -04:00
{"commit":"43a6cc3","dirty":true,"functions":{"bresenham":{"doc_sha":"ee2d0f7a54a664f5","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"bresenham(start, end, include_start=True, include_end=True) -> list[tuple[int, int]]"},"end_benchmark":{"doc_sha":"5d783c5dabb7a4e9","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"end_benchmark() -> str"},"exit":{"doc_sha":"7572d4d6b1a1c8a4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"exit() -> None"},"find":{"doc_sha":"364b95807edcf8b4","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find(name: str, scene: str = None) -> UIDrawable | None"},"find_all":{"doc_sha":"b4a278f16b172131","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"find_all(pattern: str, scene: str = None) -> list"},"get_metrics":{"doc_sha":"a0bbee3858baa4a9","kind":"function","lifecycle":{"modified":{"commit":"464af6a","version":"0.2.8-dev"},"since":"0.2.8"},"signature":"get_metrics() -> dict"},"lock":{"doc_sha":"e42989cabc81d080","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"lock() -> _LockContext"},"log_benchmark":{"doc_sha":"4564bf7321366a0a","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"log_benchmark(message: str) -> None"},"set_dev_console":{"doc_sha":"940ed19ff4f5243f","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_dev_console(enabled: bool) -> None"},"set_scale":{"doc_sha":"b565b441a326af48","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"set_scale(multiplier: float) -> None"},"start_benchmark":{"doc_sha":"783957f3517518fe","kind":"function","lifecycle":{"since":"0.2.8"},"signature":"start_benchmark() -> None"},"step":{"doc_sha":"94e778b7e791028a","kind":"function","lifecycle":{"modified":{"commit":"a7ba486","version":"0.2.8-dev"},"since":"0.2.8"},"signature":"step(dt: float = None) -> float"}},"module_attributes":{"animations":{"doc_sha":"30d25725feac9eb6","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":true},"current_scene":{"doc_sha":"ab496ea99fec2fa8","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":false},"default_transition":{"doc_sha":"73fb568e9cb25540","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":false},"default_transition_duration":{"doc_sha":"ae57530eded49138","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":false},"save_dir":{"doc_sha":"96ffa5a27d178b14","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":true},"scenes":{"doc_sha":"8021c54383d3cb8e","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":true},"timers":{"doc_sha":"48e2aa7747d8f527","kind":"attribute","lifecycle":{"since":"0.2.8-dev"},"readonly":true}},"objects":{"AStarPath":{"doc_sha":"60dd12bb4a54f3dd","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"destination":{"doc_sha":"62a81c7267ad9ed9","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"origin":{"doc_sha":"c7dd130b8d4ef800","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"peek":{"doc_sha":"14054f10b4d9dda0","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"peek() -> Vector"},"remaining":{"doc_sha":"c193adc4bbfa3564","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"walk":{"doc_sha":"3fb64b239109d301","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"walk() -> Vector"}}},"Alignment":{"doc_sha":"77d93d03c8994f84","kind":"class","lifecycle":{"since":"0.2.8"},"members":{"as_integer_ratio":{"doc_sha":"3eb115fab0d0e0ec","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_count":{"doc_sha":"f276da700b5a2e37","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"bit_length":{"doc_sha":"15b29db62fd0fa6c","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"conjugate":{"doc_sha":"6517a002faad7c75","kind":"method","lifecycle":{"since":"0.2.8"},"signature":"($self, /)"},"denominator":{"doc_sha":"5051eb1570768851","kind":"property","lifecycle":{"since":"0.2.8"},"signature":""},"from_bytes":{"doc_sha":"64672607865643a7","kind":"classmethod","lifecycl