feat(harness): declare intentional N/A tiers + custom-html-tiny functional test #6
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/expected-na-and-tiny-functional"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Two operator-requested changes, after noticing
custom-html-tinyPR #6 had neither backup/restore nor functional coverage:1. Declare intentional N/A tiers (vs. accidentally-missing coverage)
A recipe can now declare in
recipe_meta.py:results.jsongainslevel_cap_intent("intentional · <reason>") and annablock classifying every N/A rung asdeclaredvsundeclared.backup_restore,functional) is surfaced as a possible coverage gap; a staleEXPECTED_NA(declared N/A but the tier actually ran) is surfaced too. Structurally-optional rungs (upgrade/integration/recipe_local) are recorded but never flagged.⚠ coverage:/⚠ stale EXPECTED_NA:lines.results.classify_na/cap_intentare pure + unit-tested.custom-html-tinydeclaresbackup_restoreintentionally N/A (nobackupbot.backuplabel — it serves an ephemeral, harness-seeded content volume with no persistent data).2.
custom-html-tinyfunctional testWrites a random file into the served
contentvolume (via the volume mountpoint, likeinstall_steps.sh, since the static-web-server image is shell-less), asserts exact-byte round-trip + a real 404 on a missing path — proving it actually serves the volume, not a 200-everything fallback.Verification
cc-ci-run -m pytest tests/unit/test_results.py tests/unit/test_level.py tests/unit/test_card.py -q→ 41 passed cold.install,custom) oncustom-html-tiny: install + the new functional test PASS;results.jsoncorrectly classifiesbackup_restoreasintent: declared,gaps: [],stale_declared: [].NEVER merges — operator review. @notplants
🤖 Generated with Claude Code
The level badge gains a third segment derived from level_cap_intent: - amber 'gap?' when the climb was capped by an UNDECLARED gap-sensitive N/A (backup_restore / functional) — a likely-missing test (unexpected skip) - muted 'expected' when capped by a DECLARED intentional N/A (reviewed, nothing to fix) - nothing extra for a clean cap, a full climb, or a real failure. Font-safe text labels (no emoji) so the SVG renders headless/anywhere. Badge never inflates — it only annotates the cap the level already reflects. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Per operator: drop the gap-sensitivity / cap-intent-clause / stale-detection machinery. Model is now dead simple — recipe_meta.EXPECTED_NA = {rung: reason} lists the rungs a recipe intentionally skips; ANY rung skipped (N/A) and not in that list is unintentional. results.json: replace the 'na' block + level_cap_intent with skips: { intentional: {rung: reason}, unintentional: [rung] } plus level_cap_rung (which rung capped). Badge/card derive intentional-vs- unintentional from whether the capping rung is in the intentional list. Skips still cap the level (never inflate). custom-html-tiny lists all three rungs it intentionally skips (backup_restore, integration, recipe_local). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>New level badge — intentional vs unintentional skip
Live comparison (rendered from this branch's code): https://report.ci.commoninternet.net/badge-preview/index.html
Same recipe (
custom-html-tiny), same level-2 cap onbackup_restore— the only difference is whether the skip is declared inrecipe_meta.EXPECTED_NA:cc-ci │ level 2 │ expected(muted)L3 backup/restore N/A · intentional: stateless static file server…cc-ci │ level 2 │ gap?(amber)L3 backup/restore N/A · unintentional skip (no EXPECTED_NA — add a test or declare it)The level itself is unchanged in both cases — a skip always caps the climb (the harness never claims a rung it didn't verify). The third badge segment + card clause only label why the cap happened, derived from the simple rule: a skipped rung is intentional iff it's listed in
EXPECTED_NA, otherwise it's an unintentional gap.Design as it now stands (supersedes the earlier comments)
After operator review the model was simplified considerably:
Level ladder = four essential rungs:
install · upgrade · backup/restore · functional(top = L4).upgradeis essential. integration (SSO/OIDC) and recipe-local are OPTIONAL — they are no longer level rungs, never cap the level, and don't render as skip rows. (SSO is still enforced for the run verdict inrun_recipe_ci.py; it just no longer affects the level.)Intentional vs unintentional skips: a recipe lists the rungs it intentionally skips, with reasons, in
recipe_meta.EXPECTED_NA = {rung: reason}. Any essential rung skipped (N/A) and not in that list is unintentional. A skip always caps the level (the harness never claims a rung it didn't verify) — this only labels why. results.json carriesskips: {intentional:{rung:reason}, unintentional:[rung]}+level_cap_rung.Display (live: https://report.ci.commoninternet.net/badge-preview/index.html):
expected(muted) for an intentional cap,gap?(amber) for an unintentional one.custom-html-tiny: declares only
backup_restoreintentionally skipped (stateless static server); gets install + upgrade + the new functional serve test; caps at L2.41 → 49 unit tests pass cold. NEVER merges by the harness — @notplants.