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:
@@ -37,9 +37,12 @@ const TIMEOUT = 5000;
|
||||
// site 1/2 (execute-phase.md): source PHASE_NUMBER, prefix PHASE
|
||||
// site 3 (completion-reconciliation.md): source SPOT_PHASE_NUMBER, prefix SPOT_PHASE
|
||||
// site 4 (tdd.md): source PHASE, prefix PHASE
|
||||
// #4748: the split is at the first NON-DIGIT, not the first dot, so a letter
|
||||
// suffix (`03A`, `23A.1.2`) rides through in the rest instead of aborting the
|
||||
// base-10 arithmetic; the rest is `_REST`, no longer only a `_FRAC`.
|
||||
function fixedSnippet(sourceVar, prefix, indent = '') {
|
||||
return `${indent}${prefix}_INT=\${${sourceVar}%%.*}; ${prefix}_FRAC=\${${sourceVar}#"$${prefix}_INT"}\n` +
|
||||
`${indent}${prefix}_N="$((10#$${prefix}_INT))\${${prefix}_FRAC//./\\\\.}"`;
|
||||
return `${indent}${prefix}_INT=\${${sourceVar}%%[!0-9]*}; ${prefix}_REST=\${${sourceVar}#"$${prefix}_INT"}\n` +
|
||||
`${indent}${prefix}_N="$((10#$${prefix}_INT))\${${prefix}_REST//./\\\\.}"`;
|
||||
}
|
||||
|
||||
function runFixed(phaseNumberValue) {
|
||||
@@ -64,6 +67,11 @@ describe('#4619 — execute-phase decimal/N-segment phase-number arithmetic', ()
|
||||
assert.equal(runFixed('01'), '1');
|
||||
});
|
||||
|
||||
test('#4748: a letter-suffixed phase number keeps its letter and zero-strips the digit run (03A -> 3A, 23A.1.2 -> 23A\\.1\\.2)', () => {
|
||||
assert.equal(runFixed('03A'), '3A');
|
||||
assert.equal(runFixed('23A.1.2'), '23A\\.1\\.2');
|
||||
});
|
||||
|
||||
test('failing-first: the OLD $((10#...)) form is a hard shell syntax error on a decimal phase number', () => {
|
||||
assert.throws(() => {
|
||||
execFileSync('bash', ['-c', 'echo $((10#01.1))'], { encoding: 'utf8', timeout: TIMEOUT });
|
||||
@@ -123,13 +131,13 @@ describe('#4619 — execute-phase decimal/N-segment phase-number arithmetic', ()
|
||||
});
|
||||
|
||||
describe('source parity — each of the 4 production sites carries the fixed logic', () => {
|
||||
test('execute-phase.md safe_resume_gate carries the fixed PHASE_NUMBER/PHASE_INT/PHASE_FRAC/PHASE_N logic', () => {
|
||||
test('execute-phase.md safe_resume_gate carries the fixed PHASE_NUMBER/PHASE_INT/PHASE_REST/PHASE_N logic', () => {
|
||||
const w = fs.readFileSync(EXECUTE_PHASE, 'utf8');
|
||||
assert.ok(w.includes(fixedSnippet('PHASE_NUMBER', 'PHASE')),
|
||||
'safe_resume_gate must carry the byte-identical fixed decimal-tolerant snippet');
|
||||
});
|
||||
|
||||
test('execute-phase.md TDD gate carries the fixed PHASE_NUMBER/PHASE_INT/PHASE_FRAC/PHASE_N logic', () => {
|
||||
test('execute-phase.md TDD gate carries the fixed PHASE_NUMBER/PHASE_INT/PHASE_REST/PHASE_N logic', () => {
|
||||
const w = fs.readFileSync(EXECUTE_PHASE, 'utf8');
|
||||
// The TDD gate block is nested one level deeper (4-space indent) than
|
||||
// safe_resume_gate's top-level snippet.
|
||||
|
||||
Reference in New Issue
Block a user