Files
msd-core/src/phase-id-display.cts
BeeHiggs 0967358b8b enhance(#3638): render bracket phase IDs on progress, stats, manager and statusline surfaces (epic #612 PR-5) (#4111)
* enhance(#3638): render bracket IDs on display surfaces

Gate progress, stats, manager, and statusline projections on the bracket convention; validate phase_id_convention and single-source the convention card.

Forward note: the uat.cts bracket co-change remains deliberately deferred to its owning slice.

* chore(#3638): point the changeset at PR #4111

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(#3638): close bracket display review gaps

* docs(#3638): register phase display modules

* chore(#3638): re-trigger CI after macOS shard SIGTERM

`full test (macos-latest, 24, shard 3/3)` failed on 20ce98cd1 in
`tests/lint-compiled-artifact-sync.test.cjs` — the spawned
`scripts/lint-compiled-artifact-sync.cjs` was killed at 60024ms
(`exited null (signal SIGTERM)`, stdout and stderr both empty), 24ms past
the test's own `TSC_COMPILE_TIMEOUT_MS`. That is the failure mode the
constant's comment already documents ("under CI shard load that compile
can exceed the budget, dying to a SIGTERM with empty piped stdout").

No content change; this empty commit exists only to re-run the matrix,
since re-running a job needs write access on the upstream repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
2026-09-15 04:47:47 -04:00

86 lines
2.8 KiB
TypeScript

/**
* Phase-ID display adapters (#3638 / ADR-612 PR-5).
*
* STATE.md and milestone metadata still expose the legacy `vN.0` marker on
* this stacked base. Display surfaces need to translate that metadata into a
* bracket identity without growing another renderer. These pure adapters do
* only the boundary normalization, then delegate identity parsing/rendering to
* phase-id.cts's canonical pair.
*/
// eslint-disable-next-line @typescript-eslint/no-require-imports
import phaseId = require('./phase-id.cjs');
const { parsePhaseId, renderMilestoneId, renderPhaseId } = phaseId;
function canonicalNumeric(value: string): string {
let offset = 0;
while (offset < value.length - 1 && value[offset] === '0') offset++;
const stripped = value.slice(offset);
return stripped.length < 2 ? stripped.padStart(2, '0') : stripped;
}
function isDigits(value: string): boolean {
return value.length > 0
&& [...value].every(char => char >= '0' && char <= '9');
}
function milestoneToken(value: unknown): string | null {
if (typeof value !== 'string' && typeof value !== 'number') return null;
const raw = String(value).replace(/^v/i, '');
const parts = raw.split('.');
if (parts.length > 2 || parts.some(part => !isDigits(part))) return null;
return canonicalNumeric(parts[0]);
}
function phaseToken(value: unknown): string | null {
if (typeof value !== 'string' && typeof value !== 'number') return null;
const raw = String(value);
const parts = raw.split('.');
if (parts.length > 2 || parts.some(part => !isDigits(part))) return null;
return parts.map(canonicalNumeric).join('.');
}
/**
* Render a bracket phase display from legacy milestone metadata.
* Returns null for incomplete or invalid metadata so cosmetic callers can
* degrade without breaking a command/statusline render.
*/
function renderBracketPhaseDisplay(
milestone: unknown,
phase: unknown,
projectCode: unknown,
): string | null {
const project = typeof projectCode === 'string' ? projectCode : '';
const mm = milestoneToken(milestone);
const pp = phaseToken(phase);
if (!project || mm === null || pp === null) return null;
try {
return renderPhaseId(parsePhaseId(`${project}.${mm}-${pp}`));
} catch {
return null;
}
}
/** Render only the bracket milestone label, still through canonical parsing. */
function renderBracketMilestoneDisplay(
milestone: unknown,
projectCode: unknown,
): string | null {
const project = typeof projectCode === 'string' ? projectCode : '';
const mm = milestoneToken(milestone);
if (!project || mm === null) return null;
try {
// The sentinel phase is a validation vehicle, not a rendering artifact.
return renderMilestoneId(parsePhaseId(`${project}.${mm}-00`));
} catch {
return null;
}
}
export = {
renderBracketPhaseDisplay,
renderBracketMilestoneDisplay,
};