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:
13
.githooks/pre-commit
Normal file
13
.githooks/pre-commit
Normal 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
100
README.md
@@ -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,
|
||||
bounds-clamping, pan_enabled toggle, pan_invert, engine-surface presence)
|
||||
via the `engine.test.*` assertion surface. 16 assertions total.
|
||||
Test-lib for `lib-core.camera` (Tests-as-Libs per ADR-0037).
|
||||
|
||||
- Lib-ID: `lib-core.camera-test`
|
||||
- Version: `0.1.0`
|
||||
- Kind: `test-lib` (headless; M.run_tests(ctx) invoked by engine test-runner)
|
||||
- Spec: `meta/docs/superpowers/specs/2026-05-13-p3-5-camera-free-pan-design.md`
|
||||
**Version:** 0.1.0
|
||||
**Lib-ID:** lib-core.camera-test
|
||||
**Requires:** lib-core.camera v>=0.3.0, lib-core.input v>=0.4.0
|
||||
**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
|
||||
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).
|
||||
|
||||
## Coverage Statements (2026-05-16 Fault-Injection Audit)
|
||||
## References
|
||||
|
||||
Verified via deliberate-mutation in fixture-mirror; mutations reverted after observation.
|
||||
|
||||
### Caught Mutations
|
||||
|
||||
| # | 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.
|
||||
- ADR-0037 (Tests-as-Libs Convention)
|
||||
- ADR-0038 (API-Doc-Convention)
|
||||
- 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`
|
||||
|
||||
3
scripts/install-hooks.sh
Normal file
3
scripts/install-hooks.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
git config core.hooksPath .githooks
|
||||
echo "Hooks activated."
|
||||
Reference in New Issue
Block a user