yak(ratchets-deferred-decisions-handoff-practice-ccjp): ratchets, deferred decisions, handoff practice
This commit is contained in:
@@ -142,8 +142,65 @@ failure ride along: if it predates your change, stop and discuss it with the use
|
|||||||
rather than working around it.
|
rather than working around it.
|
||||||
|
|
||||||
Browser tests (`make playwright*`) are *external* verification and are **not**
|
Browser tests (`make playwright*`) are *external* verification and are **not**
|
||||||
part of the Lens pass. Whether they ever join it is an open decision (see the yak
|
part of the Lens pass. Decided 2026-10-28 (human, yak "ratchets, deferred
|
||||||
"ratchets, deferred decisions, handoff practice").
|
decisions, handoff practice"): it stays that way - Playwright is not wired into
|
||||||
|
`make verify` or into either `VERIFY_SENSORS`. The targets need a running
|
||||||
|
Phoenix server or the Docker Chrome container, and a gate that only runs with
|
||||||
|
docker or sudo is not a gate the Lens pass can rely on. Run them as their own
|
||||||
|
loop, by hand, when a change touches the browser surface.
|
||||||
|
|
||||||
|
### Landing the plane
|
||||||
|
|
||||||
|
The Lens pass is what you land with, so it is the last step of every session,
|
||||||
|
not a thing that only happens on push:
|
||||||
|
|
||||||
|
- After any session that changed code, run `make precommit`. It is `make check`
|
||||||
|
under its session-ending name and costs about a second; there is no session
|
||||||
|
where it is not worth running.
|
||||||
|
- Before handing off - to a human, a reviewer, or the next agent - run
|
||||||
|
`make verify`, or push, which fires `.githooks/pre-push` and runs the same
|
||||||
|
pass on the same tree. A hand-off note that says "tests pass" without a Lens
|
||||||
|
pass behind it is a guess, not a hand-off.
|
||||||
|
- A failing Lens pass is triaged into the classes above (see *Triage classes*)
|
||||||
|
and **reported** in the hand-off note, with the class it fell in. A nit gets a
|
||||||
|
yak; it does not get fixed inline mid-build. Never re-run until green.
|
||||||
|
- `git push --no-verify` stays the deliberate override for a branch you know is
|
||||||
|
red. It is never how a session lands.
|
||||||
|
|
||||||
|
## Ratchets
|
||||||
|
|
||||||
|
The coverage threshold in `app/mix.exs` and `blogex/mix.exs` (the `threshold:`
|
||||||
|
inside each `test_coverage/0`) is a **floor**, not a target:
|
||||||
|
|
||||||
|
- After each behavior-test yak lands, re-measure both apps - `make test.coverage`
|
||||||
|
then `make coverage` inside each app - and raise the floor to the new total.
|
||||||
|
The convention is integer truncation of the measurement: a measured 82.61%
|
||||||
|
means a floor of 82. Never above the measurement: a floor that cannot pass is
|
||||||
|
not a ratchet, it is a red gate.
|
||||||
|
- Never lower a floor. A legitimate drop is a conversation, not a config edit.
|
||||||
|
Lowering the number, or adding an `ignore_modules` entry to prop it up, hides
|
||||||
|
the behavior gap the floor exists to surface.
|
||||||
|
- The record of the last measurement and its date is the comment above
|
||||||
|
`test_coverage/0` in that app's `mix.exs`. Update it there, in the same commit
|
||||||
|
as the number. Do not copy the totals into this file: one record, in the
|
||||||
|
place the gate reads, is the whole point.
|
||||||
|
|
||||||
|
Two further health numbers are baselines-to-be; neither is `make verify`'s
|
||||||
|
business yet, and neither is to be invented:
|
||||||
|
|
||||||
|
- **CRAP offender count.** `make crap` in one app is the sensor: a passing run
|
||||||
|
prints `Summary: ... worst_score=...`, a failing run prints `High scores: N`
|
||||||
|
and the offending functions. Both apps sit under the default `--max-score
|
||||||
|
(30)`, and the decision (2026-10-28) not to lower it, plus the baseline
|
||||||
|
offender count, live in the comment above the `crap` target in
|
||||||
|
`app/Makefile` / `blogex/Makefile`.
|
||||||
|
- **Mutation survivor count.** Mutation is a slot comment only in
|
||||||
|
`app/Makefile` and `blogex/Makefile` ("yak: mutation testing with muex - a
|
||||||
|
sensor, not a gate"), and `muex` is a dependency of neither app. Nothing has
|
||||||
|
been mutated, so there is no survivor baseline; do not conjure one from a run
|
||||||
|
that did not happen. When the mutation yak lands, its survivors become the
|
||||||
|
baseline the same way the coverage floor did: measured, dated, recorded where
|
||||||
|
the sensor lives.
|
||||||
|
|
||||||
# Development
|
# Development
|
||||||
Always fix failing tests, credo issues and format isseus.
|
Always fix failing tests, credo issues and format isseus.
|
||||||
|
|||||||
+8
-2
@@ -58,8 +58,14 @@ coverage:
|
|||||||
# report scores that are pessimistic instead of absent - a false failure is
|
# report scores that are pessimistic instead of absent - a false failure is
|
||||||
# less bad than a false pass, but neither is acceptable in the Lens pass.
|
# less bad than a false pass, but neither is acceptable in the Lens pass.
|
||||||
#
|
#
|
||||||
# Threshold is ex_crap's default (30); whether to ratchet it down is an open
|
# Threshold is ex_crap's default (30), kept deliberately: decision 2026-10-28
|
||||||
# decision tracked in the "ratchets, deferred decisions, handoff practice" yak.
|
# (human, yak "ratchets, deferred decisions, handoff practice") is not to
|
||||||
|
# ratchet --max-score down yet - below 30 is a policy change, not a cleanup.
|
||||||
|
# Baseline at that threshold, same date: 0 offenders above 30, worst function
|
||||||
|
# FirehoseWeb.CoreComponents.table/1 at 20.00 ("Summary: files=23 functions=140
|
||||||
|
# scored=140 worst_score=20.00"). A failing run prints "High scores: N" plus the
|
||||||
|
# offending functions; on a passing run read N=0 off the worst score rather than
|
||||||
|
# inventing a count.
|
||||||
crap:
|
crap:
|
||||||
@test -f cover/default.coverdata || { echo "crap: no exported coverage - run 'make test.coverage' first" >&2; exit 1; }
|
@test -f cover/default.coverdata || { echo "crap: no exported coverage - run 'make test.coverage' first" >&2; exit 1; }
|
||||||
MIX_ENV=test $(MISE_EXEC) mix crap
|
MIX_ENV=test $(MISE_EXEC) mix crap
|
||||||
|
|||||||
+8
-2
@@ -54,8 +54,14 @@ coverage:
|
|||||||
# report scores that are pessimistic instead of absent - a false failure is
|
# report scores that are pessimistic instead of absent - a false failure is
|
||||||
# less bad than a false pass, but neither is acceptable in the Lens pass.
|
# less bad than a false pass, but neither is acceptable in the Lens pass.
|
||||||
#
|
#
|
||||||
# Threshold is ex_crap's default (30); whether to ratchet it down is an open
|
# Threshold is ex_crap's default (30), kept deliberately: decision 2026-10-28
|
||||||
# decision tracked in the "ratchets, deferred decisions, handoff practice" yak.
|
# (human, yak "ratchets, deferred decisions, handoff practice") is not to
|
||||||
|
# ratchet --max-score down yet - below 30 is a policy change, not a cleanup.
|
||||||
|
# Baseline at that threshold, same date: 0 offenders above 30, worst functions
|
||||||
|
# Blogex.LinkValidator.validate_link/1 and validate_links/1 at 6.00
|
||||||
|
# ("Summary: files=12 functions=61 scored=61 worst_score=6.00"). A failing run
|
||||||
|
# prints "High scores: N" plus the offending functions; on a passing run read
|
||||||
|
# N=0 off the worst score rather than inventing a count.
|
||||||
crap:
|
crap:
|
||||||
@test -f cover/default.coverdata || { echo "crap: no exported coverage - run 'make test.coverage' first" >&2; exit 1; }
|
@test -f cover/default.coverdata || { echo "crap: no exported coverage - run 'make test.coverage' first" >&2; exit 1; }
|
||||||
MIX_ENV=test $(MISE_EXEC) mix crap
|
MIX_ENV=test $(MISE_EXEC) mix crap
|
||||||
|
|||||||
Reference in New Issue
Block a user