Problem
Today the only way to update the baseline is to regenerate it from scratch (--generate-baseline, becoming a generate-baseline command with #648). But regenerating snapshots the entire current state: if new violations were introduced since the baseline was created, regenerating silently legitimizes them. This is the classic baseline trap — every regeneration is an opportunity for architectural debt to grow unnoticed.
#638 made this gap visible: check now detects baseline entries that look fixed and prints a hint — but the only remedy it can suggest is a full regeneration, i.e. exactly the risky operation described above. There is no safe way to say "the baseline should only reflect debt that still exists".
Proposal
A dedicated command with shrink-only semantics — it removes baseline entries that no longer match a current violation, and never adds anything:
phparkitect prune-baseline [filename]
- Runs the analysis, then keeps only the intersection between the existing baseline and the current violations. The baseline can only shrink (ratchet effect).
- By matching entries ignoring line numbers but saving the current matching violations, pruning also refreshes stale line numbers after refactorings — today the only workarounds are
--ignore-baseline-linenumbers or a risky full regeneration.
- Unlike
generate-baseline (a manual, one-off operation), pruning is safe to automate: a scheduled job can keep the baseline tidy as debt gets paid down, with no risk of hiding new violations.
The name follows the git remote prune / docker system prune convention: "remove entries that no longer correspond to anything real". Prior art for the semantics: Psalm's --update-baseline, which only removes fixed issues (vs --set-baseline, which regenerates).
Follow-up on the #638 hint
Once this command exists, the message introduced in #638 should point to it:
💡 3 violations in the baseline look fixed — run `phparkitect prune-baseline` to remove them
Implementation notes
The matching logic already exists: Baseline::applyTo / Violations::remove already compare violations with or without line numbers. Pruning is essentially the complementary operation, followed by Baseline::save.
Related: #648 (promoting baseline generation to a first-class command — together they form a small *-baseline command family).
Problem
Today the only way to update the baseline is to regenerate it from scratch (
--generate-baseline, becoming agenerate-baselinecommand with #648). But regenerating snapshots the entire current state: if new violations were introduced since the baseline was created, regenerating silently legitimizes them. This is the classic baseline trap — every regeneration is an opportunity for architectural debt to grow unnoticed.#638 made this gap visible:
checknow detects baseline entries that look fixed and prints a hint — but the only remedy it can suggest is a full regeneration, i.e. exactly the risky operation described above. There is no safe way to say "the baseline should only reflect debt that still exists".Proposal
A dedicated command with shrink-only semantics — it removes baseline entries that no longer match a current violation, and never adds anything:
--ignore-baseline-linenumbersor a risky full regeneration.generate-baseline(a manual, one-off operation), pruning is safe to automate: a scheduled job can keep the baseline tidy as debt gets paid down, with no risk of hiding new violations.The name follows the
git remote prune/docker system pruneconvention: "remove entries that no longer correspond to anything real". Prior art for the semantics: Psalm's--update-baseline, which only removes fixed issues (vs--set-baseline, which regenerates).Follow-up on the #638 hint
Once this command exists, the message introduced in #638 should point to it:
Implementation notes
The matching logic already exists:
Baseline::applyTo/Violations::removealready compare violations with or without line numbers. Pruning is essentially the complementary operation, followed byBaseline::save.Related: #648 (promoting baseline generation to a first-class command — together they form a small
*-baselinecommand family).