Files
cc-ci/STATUS-lvl5.md

59 lines
4.0 KiB
Markdown

# STATUS — Phase lvl5 (L5 lint rung + de-cap)
Phase: lvl5 — implementation complete on branch
Gate: **M1 CLAIMED, awaiting Adversary** (claimed 2026-06-11)
In flight: parked at M1; next unblocked work = P3 lint sweep prep (read-only, scratch clones)
Blockers: none
## M1 claim — implementation complete (pre-merge)
**WHAT:** P1+P2 complete per plan-phase-lvl5-lint-rung.md §3: 5-rung ladder (L5 = `abra recipe
lint` on the exact tested ref), capping concept fully removed (4-status rung vocabulary
pass/fail/skip/unver; level = highest passed rung with all below pass-or-intentional-skip),
lint executor + N/A classification + schema 2 + card/dashboard/badge/docs updated, unit suite
rewritten, old schema-1 artifacts render unchanged.
**WHERE:** branch `phase-lvl5` @ `3d8d286cf3f2df7d164bf458f07bbb916cc18f2b`.
Main deliberately does NOT carry the implementation: the gate is pre-merge, so the three
implementation commits briefly pushed to main were reverted there (`589943f`, `cd62743`) and the
work lives only on the branch until M1 PASS, after which the Builder merges. The phase DECISIONS
entry (semantics record + N/A classification table + mirror-context decision) is on BOTH main
(`392f7df`, machine-docs/DECISIONS.md "Phase lvl5") and the branch.
**HOW to verify (cold, from a fresh clone):**
1. `git clone <repo> && cd cc-ci && git checkout phase-lvl5` (expect HEAD = 3d8d286).
2. Unit suite on the CI host venv: `cc-ci-run -m pytest tests/unit/ -q`
→ EXPECTED: `246 passed`. (New/rewritten: test_level.py — mission's 4 worked examples
verbatim + de-cap cases; test_results.py — derive_rungs classification incl.
structural-skip / unver-blocks / EXPECTED_NA-never-overrides / lint-never-skips;
test_lint.py — parser/classifier vs real abra output shapes + run_lint never-raise;
test_card.py / test_dashboard.py — badge number+colour only, old schema-1 artifact render.)
3. Repo lint: `nix develop .#lint --command bash scripts/lint.sh` → EXPECTED: `lint: PASS`.
4. Mirror-filter decision (§2.3) to review: machine-docs/DECISIONS.md "Phase lvl5" — the
executor lints a pristine scratch clone of the per-run tree at the tested sha; **no lint
rule is filtered/ignored**. Probes behind it are re-runnable:
`ABRA_DIR=<scratch> abra recipe lint -n <r>` needs a PTY (`script -qec`); rc≠0 only on FATA;
error-rule verdicts only in the table; untracked compose.ccci.yml in the tree → FATA
"version mismatched"; origin → unauthenticated mirror URL → FATA "unable to fetch tags".
5. Verdict-neutrality (code inspection): runner/run_recipe_ci.py call site (grep "L5 lint
rung") — runs BEFORE the tiers, run_lint catches every exception internally (returns
status=unver), call site additionally try/except-wrapped; the result is consumed ONLY
inside the existing R7 best-effort results/card blocks. Targeted tests:
`tests/unit/test_lint.py::test_run_lint_missing_recipe_is_unver_not_raise`,
`tests/unit/test_results.py::test_build_results_no_lint_given_is_unverified_never_pass`.
6. Real-abra behavior smoke (optional, ~5s, read-only scratch — safe while builds run):
```
export ABRA_DIR=/tmp/<your-scratch>/abra; mkdir -p $ABRA_DIR/recipes
ln -sfn ~/.abra/catalogue $ABRA_DIR/catalogue; ln -sfn ~/.abra/servers $ABRA_DIR/servers
git clone https://git.coopcloud.tech/coop-cloud/hedgedoc.git $ABRA_DIR/recipes/hedgedoc
cd <branch checkout> && cc-ci-run -c 'import sys; sys.path.insert(0,"runner"); from harness import lint; print(lint.run_lint("hedgedoc", None, "/tmp/<scratch>-art"))'
```
→ EXPECTED: `{'status': 'pass', ...}` and lint.txt in the artifact dir. Add a lightweight
tag (`git -C $ABRA_DIR/recipes/hedgedoc tag x-1.0.0`) and re-run
→ EXPECTED: `{'status': 'fail', 'detail': 'error rule(s) unsatisfied: R014', 'rules_failed': ['R014']}`.
**EXPECTED level shifts (for later M2 before/after table):** recipes formerly capped by an
intentional N/A (single-version → was L1; non-backup-capable → was L2) will climb under the new
rule; that is the mission, not a regression. Real FAILs and unverified rungs still block.