docs: migrate README to API-Doc-Convention (S2-cascade.libs test-lib)

Restructured per ADR-0038 with Coverage-Statement-Block per Fault-
Injection-Audit-Convention. Topology auto-populated. Pre-commit hook
installed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-05-16 16:47:07 +02:00
parent 563c8e4ae7
commit f04e90b292
3 changed files with 89 additions and 27 deletions

13
.githooks/pre-commit Normal file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
# Sporel API-Doc-Convention pre-commit hook.
SPOREL_EXE="${SPOREL_EXE:-$(command -v Sporel.exe 2>/dev/null || command -v sporel 2>/dev/null)}"
if [ -z "$SPOREL_EXE" ]; then
echo "INFO: Sporel.exe not on PATH. Skipping lint." >&2
exit 0
fi
"$SPOREL_EXE" --lint="$(pwd)" --fix
RC=$?
if git diff --cached --name-only | grep -qx 'README.md'; then
git add README.md
fi
exit $RC

100
README.md
View File

@@ -1,15 +1,74 @@
# sporel-lib-core.camera-test # lib-core.camera-test
P.3.5 test-lib — validates `lib-core.camera` v0.3.0 API contracts (state setters, Test-lib for `lib-core.camera` (Tests-as-Libs per ADR-0037).
bounds-clamping, pan_enabled toggle, pan_invert, engine-surface presence)
via the `engine.test.*` assertion surface. 16 assertions total.
- Lib-ID: `lib-core.camera-test` **Version:** 0.1.0
- Version: `0.1.0` **Lib-ID:** lib-core.camera-test
- Kind: `test-lib` (headless; M.run_tests(ctx) invoked by engine test-runner) **Requires:** lib-core.camera v>=0.3.0, lib-core.input v>=0.4.0
- Spec: `meta/docs/superpowers/specs/2026-05-13-p3-5-camera-free-pan-design.md` **Tags:** test, camera
## Run ## Topology
<!-- topology:start (auto-generated; do not edit) -->
```mermaid
graph LR
this["lib-core.camera-test"]
lib_core_camera["lib-core.camera"]
this --> lib_core_camera
lib_core_input["lib-core.input"]
this --> lib_core_input
engine["engine.*"]
this --> engine
```
<!-- topology:end -->
## Coverage Statement
Per Fault-Injection-Audit-Convention (2026-05-16):
| Section | Assertion-Count | Coverage |
|---|---|---|
| State setters/getters | 3 | `set_target`/`target`, `set_zoom`/`zoom`, `set_pan_speed`/`pan_speed` |
| Bounds-Clamping | 3 | `set_bounds` clamping, `clear_bounds` -> unclamped, immediate-clamp on bounds-shrink |
| pan_enabled state | 6 | Per-source disable (keys/edge/drag), `bind_pan_keys` auto-enable, toggle false/true |
| pan_invert state | 2 | `set_pan_invert(false)`, `set_pan_invert(true)` |
| Engine-Surface existence | 2 | `engine.input.get_mouse_delta`, `engine.window.size` function presence |
| **TOTAL** | **16** | |
### Tested-Surface
- `camera.set_target` / `camera.target` (value + bounds-clamping)
- `camera.set_zoom` / `camera.zoom`
- `camera.set_pan_speed` / `camera.pan_speed`
- `camera.set_bounds`, `camera.clear_bounds`
- `camera.bind_pan_keys` (auto-enable side-effect)
- `camera.set_pan_enabled` / `camera.pan_enabled` (toggle false/true)
- `camera.set_pan_invert` / `camera.pan_invert`
- Engine surface: `engine.input.get_mouse_delta`, `engine.window.size`
### Fault-Injection Audit (2026-05-16)
Verified via deliberate-mutation in fixture-mirror; mutations reverted after observation.
| # | Mutation | Caught by |
|---|---|---|
| M1 | `set_target`: x/y assignments swapped | Assertions 1 (`set_target -> target`) + 4 (`set_target clamped to bounds`) fail |
| M2 | `clear_bounds` made no-op | Assertion 5 (`clear_bounds -> unclamped`) fails |
| M3 | `bind_pan_keys` auto-enable removed | Assertion 10 (`bind_pan_keys auto-enables`) fails |
All 3 mutations caught — no gaps detected.
### Structurally Untestable
- `camera.begin` / `camera.finish` — render-stack side-effects only observable inside a render hook; headless test-runner has no render context.
- `camera.update(dt)` interaction with per-frame mouse-input — requires live `engine.input` polling state.
- `camera.screen_to_world` — requires live window-size from `engine.window.size`, headless returns 0 (deferred).
### Deferred
- `enable_pan_edge`, `bind_pan_drag` runtime behavior (covered indirectly via `pan_enabled` toggles).
- `set_edge_threshold` / `edge_threshold` getter/setter pair.
## Running
Via `--test-libs=lib-core.camera-test` (Smoke P0-S-batch Stage):
```bash ```bash
Sporel.exe --libs-dir=<libs-path> --test-libs=lib-core.camera-test Sporel.exe --libs-dir=<libs-path> --test-libs=lib-core.camera-test
@@ -17,22 +76,9 @@ Sporel.exe --libs-dir=<libs-path> --test-libs=lib-core.camera-test
Output is TAP version 13 on stdout; exit-code = failure-count (0 = all pass). Output is TAP version 13 on stdout; exit-code = failure-count (0 = all pass).
## Coverage Statements (2026-05-16 Fault-Injection Audit) ## References
Verified via deliberate-mutation in fixture-mirror; mutations reverted after observation. - ADR-0037 (Tests-as-Libs Convention)
- ADR-0038 (API-Doc-Convention)
### Caught Mutations - Production-Lib: `~/Projects/Sporel/sporel-libs/lib-core/camera/README.md`
- Spec: `meta/docs/superpowers/specs/2026-05-13-p3-5-camera-free-pan-design.md`
| # | Mutation | Caught by |
|---|---|---|
| M1 | `set_target`: x/y assignments swapped (`target_x = y; target_y = x`) | Assertions 1 ("set_target -> target", `t.x==100 and t.y==200`) and 4 ("set_target clamped to bounds") both fail |
| M2 | `clear_bounds` made no-op (`do return end` as first statement) | Assertion 5 ("clear_bounds -> unclamped") fails — target remains clamped after clear |
| M3 | `bind_pan_keys` auto-enable removed (`pan_enabled_v.keys = true` commented out) | Assertion 10 ("bind_pan_keys auto-enables") fails — `pan_enabled("keys")` returns false |
### Uncaught Mutations (Gaps)
None — all 3 mutations caught.
### Tested Production-Lib Surface
`lib-core.camera` v0.3.0 — Tests cover behavior of: `camera.set_target`/`target` (value + bounds-clamping), `camera.set_zoom`/`zoom`, `camera.set_pan_speed`/`pan_speed`, `camera.set_bounds`, `camera.clear_bounds`, `camera.bind_pan_keys` (auto-enable side-effect), `camera.set_pan_enabled`/`pan_enabled` (toggle false/true), `camera.set_pan_invert`/`pan_invert`. Engine surface: `engine.input.get_mouse_delta`, `engine.window.size` function presence.

3
scripts/install-hooks.sh Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
git config core.hooksPath .githooks
echo "Hooks activated."