#!/usr/bin/env node /** * step-pointer — указатель шага плана как ДЕРЕВО (волны D6/OQ1). Заменяет линейный * счётчик Машины 2, когда шаг раскрывается в под-план. СТЕНДОВЫЙ модуль: построен и * оттестирован, но в живой enforce-supreme-gate.main() НЕ врезается в этой сессии * (см. журнал вопросов — отдельный шаг). Линейный режим обратно совместим. */ /** Указатель = стек уровней [{index, length}]; верхний — текущий под-план. */ export function createPointer({ length }) { return { stack: [{ index: 0, length }], indexAtRoot: 0 }; } /** Текущий путь — индексы по уровням стека. */ export function currentPath(p) { return p.stack.map((l) => l.index); } /** Индекс на корневом уровне (обратная совместимость с линейным счётчиком). */ function rootIndex(p) { return p.stack[0].index; } /** Продвинуть указатель на текущем (верхнем) уровне. */ export function advance(p) { const stack = p.stack.map((l) => ({ ...l })); stack[stack.length - 1].index += 1; const np = { stack }; np.indexAtRoot = rootIndex(np); return np; } /** Текущий шаг раскрылся в под-план длины length → углубляемся. */ export function enterSubPlan(p, { length }) { const stack = p.stack.map((l) => ({ ...l })); stack.push({ index: 0, length }); const np = { stack }; np.indexAtRoot = rootIndex(np); return np; } /** Под-план исчерпан → возвращаемся к родителю (на его текущем шаге). */ export function exitSubPlan(p) { if (p.stack.length <= 1) return p; const stack = p.stack.slice(0, -1).map((l) => ({ ...l })); const np = { stack }; np.indexAtRoot = rootIndex(np); return np; } /** Готово, когда корневой уровень исчерпан. */ export function isDone(p) { const root = p.stack[0]; return p.stack.length === 1 && root.index >= root.length; }