fix(#4830): re-land #4768's letter-suffix phase-id fix and its lint-phase-id-drift ratchets on current next (#4873)
* fix(#4830): re-land #4768's letter-suffix phase-id fix and its lint-phase-id-drift ratchets on current next Commit740ba0d8a(#4781) removed every change #4768 had merged for #4748: the first-non-digit split at execute-phase.md's two arithmetic sites, the init-emitted `padded_phase` the REVIEW.md lookup binds instead of `printf "%02d"`, the canonical-grammar extractions in autonomous.md and plan-review-convergence.md, the `.changeset/zesty-wolves-tumble.md` fragment, and the three lint-phase-id-drift ratchets with their tests. The guard and the code it guarded left together, so nothing went red. This is a cherry-pick of092d9256bonto current `next`, resolved against the #4683 threat-id fields on execute-phase.md's Parse-JSON line, with the changeset `pr:` reset to the placeholder and the compact-content benchmark baseline regenerated against the current base. (cherry picked from commit092d9256b8) Emitted-Drift-Ack-Growth: autonomous.md — restores #4768's canonical-grammar extraction and its explanatory comment for --from/--to/--only Emitted-Drift-Ack-Growth: execute-phase.md — restores #4768's first-non-digit split at two arithmetic sites and the padded_phase binding for the REVIEW.md lookup Emitted-Drift-Ack-Growth: plan-review-convergence.md — restores #4768's canonical-grammar phase extraction and its comment Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AX7LXxc3uAkGki6iaYiAMP * chore(#4830): set changeset fragment pr to 4873 --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
This commit is contained in:
@@ -1087,6 +1087,34 @@ describe('init commands ROADMAP fallback when phase directory does not exist (#1
|
||||
assert.strictEqual(output.phase_name, 'Foundation Setup');
|
||||
assert.strictEqual(output.phase_slug, 'foundation-setup');
|
||||
assert.strictEqual(output.phase_req_ids, 'R-01, R-02');
|
||||
// #4748: the ROADMAP fallback hands the workflow an UNPADDED number, and
|
||||
// execute-phase.md used to re-pad it with `printf "%02d"` — which cannot
|
||||
// pad a letter id and reads an already-padded `08` as octal. The
|
||||
// normalized form is emitted here, like the plan-phase sibling above.
|
||||
assert.strictEqual(output.padded_phase, '01');
|
||||
});
|
||||
|
||||
test('#4748 — init execute-phase emits padded_phase for a letter-suffixed phase, from a directory and from the ROADMAP fallback', () => {
|
||||
fs.appendFileSync(
|
||||
path.join(tmpDir, '.planning', 'ROADMAP.md'),
|
||||
'\n### Phase 3A: Letter Variant\n**Goal:** On disk\n\n### Phase 4B: Roadmap Only\n**Goal:** No directory yet\n',
|
||||
);
|
||||
seedPhase(tmpDir, '03A-letter-variant', { '03A-01-PLAN.md': '# Plan' });
|
||||
|
||||
const onDisk = JSON.parse(runGsdTools('init execute-phase 3A', tmpDir).output);
|
||||
assert.strictEqual(onDisk.phase_found, true);
|
||||
assert.strictEqual(onDisk.phase_number, '03A');
|
||||
assert.strictEqual(onDisk.padded_phase, '03A');
|
||||
|
||||
const roadmapOnly = JSON.parse(runGsdTools('init execute-phase 4B', tmpDir).output);
|
||||
assert.strictEqual(roadmapOnly.phase_found, true);
|
||||
assert.strictEqual(roadmapOnly.phase_dir, null);
|
||||
assert.strictEqual(roadmapOnly.phase_number, '4B');
|
||||
assert.strictEqual(roadmapOnly.padded_phase, '04B');
|
||||
|
||||
const missing = JSON.parse(runGsdTools('init execute-phase 9Z', tmpDir).output);
|
||||
assert.strictEqual(missing.phase_found, false);
|
||||
assert.strictEqual(missing.padded_phase, null);
|
||||
});
|
||||
|
||||
test('init verify-work falls back to ROADMAP when no phase directory exists', () => {
|
||||
|
||||
Reference in New Issue
Block a user