renumber insert corrupts phase directories when the highest phase is a decimal #36
Labels
No labels
already-shipped
bug
documentation
duplicate
enhancement
good first issue
help wanted
in progress
invalid
needs-decision
proposal
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: crenshawdev/cadence#36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Severity: high · Area: renumber · surfaced in the post-v1.2.0 cross-model review sweep (reproduced with a fixture)
What happens
renumber insertrenames the.planning/phases/directories from the top down to make room for the new phase. It computes "the top" as the highest phase number — but that maximum includes decimal insertion phases like2.1. When a decimal is the highest phase, the countdown runs on fractional values and never lands on the integer directories it was supposed to move, while it does move the decimal directory, which by design must stay put. The command reports success the whole time, leaving every integer phase's directory pointing at the wrong phase number.This is the operation
cad-phaseexists to get right, broken precisely for repos that use decimal insertions — the case that most needs a reliable renumber.Mechanism (verified against source)
const maxN = Math.max(...phases.map((p) => p.n))(cadence-core/bin/planning.mjs:586) takes the max over all phases, decimals included.for (let k = maxN; k >= at; k--)(planning.mjs:604) therefore starts at a fractional ceiling. With phases1, 2, 2.1and--at 1:kruns2.1,1.1and stops.existingDir(2.1)matches →phases/2.1is pushed to move tophases/3.1;existingDir(1.1)does not exist → skipped. The integer directoriesphases/1andphases/2are never visited.shiftPhaseTokens(called at:616) correctly leaves decimal phases alone in the ROADMAP, so the ROADMAP renumbers to Phase 2 / Phase 3 while the directories still read 1 / 2 — a silent desync.planning.mjs:606) starts at the integerat + 1and increments, sokstays integer and remove is unaffected.Reproduction
ROADMAP phases
1, 2, 2.1, thenrenumber insert --at 1:phases/1andphases/2unchanged (wrong),phases/2.1renamed tophases/3.1(wrong — decimals must never move).ok:true.Fix direction
Compute the dir-move ceiling from integer phases only (e.g.
Math.maxoverphases.filter((p) => Number.isInteger(p.n))). Then the insert loop visits only integer directories and leaves decimals untouched, matching the design contract already stated atplanning.mjs:590-593and enforced byshiftPhaseTokens.