Files
pi-auto-reinject/TODO.md
T

17 KiB
Raw Blame History

TODO: pi-skill-reinject

План реализации extension для Pi Coding Agent. ТЗ — SPEC.md. Workflow агента — AGENTS.md.


Правила ведения TODO.md

Роль файла

  • Единственный источник фаз и чеклистов для цикла «работай по фазе».
  • AGENTS.md — как исполнять пункты; TODO.mdчто делать и в каком порядке.
  • Не дублировать полное ТЗ из SPEC.md; в пунктах — ссылки на разделы SPEC при необходимости.

Структура фазы

Каждая фаза — заголовок ### Фаза N — … и чеклист - [ ] / - [x].

Элемент Правило
Нумерация 0, 1, 2, … — монотонно; не переиспользовать номера
Пункт Одна атомарная мысль = один коммит кода (см. AGENTS.md)
Крупный пункт Разбить на подпункты - [ ] до размера «один коммит»
Статус фазы В конце секции или в таблице в AGENTS.md при необходимости
Зависимости Явно: «после фазы N», «блокируется …»

Формат пункта чеклиста

- [ ] **Краткое имя** — что сделать; зачем в одной фразе; ссылка на SPEC §X при нужде

Хорошо: «state.ts — load/save через appendEntry, dedupe skills by name (SPEC §6.1)».

Плохо: «сделать state» (неатомарно, непонятен scope коммита).

Коммиты и отметки [x]

Действие Когда
Код по пункту Коммит Phase N: …без TODO.md в том же коммите
[x] на пункте В коммите конца фазы TODO: … (или отдельном TODO:), не вместе с кодом пункта
Правки workflow TODO: / AGENTS: — отдельный коммит; оба файла можно в одном
Черновик плана Можно править TODO.md по ходу; финальные галочки — с концом фазы

Добавление и изменение плана

  • Новая фаза — в конец раздела «Фазы реализации», не вставлять между завершёнными без причины.
  • Отменённый пункт — [x] с пометкой «отменено» в тексте или удалить с записью в коммите TODO:.
  • Перенос между фазами — обновить оба файла (TODO.md + при необходимости таблицу статуса в AGENTS.md).

Чего не писать в TODO.md

  • Длинные спецификации (они в SPEC.md).
  • Журнал багов при ручном тесте — в BACKLOG.md.
  • Секреты, пути к личным ~/.pi/… с токенами.

Старт работы агентом

  1. Прочитать AGENTS.md и актуальную фазу в этом файле.
  2. Найти первый - [ ] в запрошенной фазе (или текущей незавершённой).
  3. Выполнить цикл: правки → проверка → review → исправления → коммит → следующий пункт.
  4. В конце фазы — коммит TODO:/AGENTS:, пауза для пользователя (если не сказано иначе).

Контекст

Сейчас Цель
Только SPEC.md + README.md Рабочий extension src/index.ts + тесты
Default off /skill-reinject on / global on
Нет re-inject после compaction Auto compaction → re-inject tracked skills (SPEC §56)

Решения (зафиксировано в SPEC)

Ключевые решения не дублировать здесь — см. SPEC.md §5–8, §16. При расхождении при реализации — сначала обновить SPEC или зафиксировать в «Решения» ниже.

Тема Где
Триггер re-inject session_compact, auto only (§5.2, §8)
Доставка с pi-auto-compact defer + before_agent_start (§6.5, §16)
Персистенция pi.appendEntry("skill-reinject:state", …) (§6.1)
Команды /skill-reinject (§7)

Фазы реализации

Фаза Название Зависимости Критерии SPEC
0 Каркас репозитория §9, §10
1 Состояние и персистенция 0 §6.1
2 Настройки 0 §7.3
3 Детекция skills 1 §6.2, §12.1
4 Expand skill-блоков 0 §5.3, §12.1
5 Kept window 3 §6.4, §12.1
6 pi-auto-compact 2 §16
7 Re-inject оркестрация 1, 4, 5, 6 §5.2, §6.5
8 Источник compaction 1 §8
9 Хуки отслеживания 1, 2, 3 §6.2
10 Восстановление сессии 1, 3, 9 §6.3
11 Команды и UI 1, 2, 6, 7 §7
12 Edge cases и полировка 711 §11
13 Приёмка и документация 012 §1213

Порядок: фазы 0→13; внутри фазы — сверху вниз. Параллельно после фазы 0 можно вести 1 и 2; фазы 3 и 4 — независимы друг от друга.


Фаза 0 — Каркас репозитория

  • package.json — manifest с pi.extensions, devDependencies (@earendil-works/pi-coding-agent, typescript); зачем: загрузка extension через pi -e (SPEC §9.1, §10)
  • tsconfig.json — strict TS, module resolution под Pi extension runtime; зачем: tsc --noEmit в цикле AGENTS
  • npm scriptstypecheck, test, build (минимально); зачем: единая проверка в каждом пункте
  • src/index.ts shellexport default function(pi: ExtensionAPI), пустой session_start; зачем: smoke pi -e ./src/index.ts без логики

Фаза 1 — Состояние и персистенция

  • state.ts typesTrackedSkill, ExtensionState (version 1), RuntimeFlags; зачем: единый контракт §6.1
  • state.ts initialcreateInitialState(), createRuntimeFlags(); зачем: предсказуемый старт сессии
  • state.ts persistsaveState(pi, state) через appendEntry("skill-reinject:state", …); зачем: пережить /resume (§6.1)
  • state.ts loadloadStateFromBranch(branch) из последнего custom entry; зачем: восстановление без полного rescan
  • state.ts trackSkill — upsert по name, merge sources, preserve insertion order; зачем: дедуп §6.1

Фаза 2 — Настройки

  • settings.ts typesSkillReinjectSettings + defaults из §7.3 (enabled, trackReadPaths, triggerTurn, reinjectOnManualCompaction, autoCompactIntegration, suffix)
  • settings.ts read — merge global + project из ctx / Pi settings API; зачем: не читать файл вручную, если API даёт merged view
  • settings.ts writeGlobal — merge в ~/.pi/agent/settings.json без затирания чужих ключей; зачем: /skill-reinject global on
  • settings.ts effectiveeffectiveEnabled(sessionOverride, global), effectiveIntegration(...); зачем: три слоя §5.1
  • test/settings.test.ts — defaults, merge write (mock/temp file); зачем: §12.1

Фаза 3 — Детекция skills

  • detect.ts slashdetectSlashSkill(text)/^\/skill:([a-z0-9-]+)/; зачем: источник slash §6.2
  • detect.ts skill-blockparseSkillBlocksFromText(text) (regex как parseSkillBlock); зачем: источник skill-block §6.2
  • detect.ts read-pathmatchReadPathToSkill(path, skills) по filePath из resourceLoader; зачем: источник read §6.2
  • detect.ts trackReadPaths gate — пропуск read-детекции при trackReadPaths: false; зачем: §6.2, §3
  • test/detect.test.ts — slash, blocks, read match, trackReadPaths off; зачем: §12.1

Фаза 4 — Expand skill-блоков

  • expand.ts readBodyreadSkillBody(filePath) + strip YAML frontmatter; комментарий «mirror agent-session»; зачем: §5.3, §10
  • expand.ts formatBlock — XML <skill name location>…</skill> с baseDir; зачем: повтор _expandSkillCommand §5.3
  • expand.ts suffix — опциональный суффикс из settings.suffix; зачем: §5.3
  • expand.ts expandSkill — публичная функция: skill meta → готовый user text; зачем: reinject + /skill-reinject now
  • test/expand.test.ts — frontmatter strip, paths, suffix; зачем: §12.1

Фаза 5 — Kept window

  • kept.ts slicegetKeptEntries(branch, firstKeptEntryId) от compaction entry до хвоста; зачем: §6.4
  • kept.ts presentskillsPresentInKeptWindow(keptEntries, skillNames) по <skill name="…"; зачем: не дублировать блоки §6.4, критерий §13
  • kept.ts filterfilterSkillsNeedingReinject(tracked, kept, registeredNames); зачем: вход для pendingReinject §5.2
  • test/kept-window.test.ts — in / not in kept, пустой kept; зачем: §12.1

Фаза 6 — pi-auto-compact

  • auto-compact.ts detectdetectPiAutoCompact(pi) через getCommands()auto-compact; кэш в RuntimeFlags; зачем: §16.4
  • auto-compact.ts deliveryModeresolveDeliveryMode(settings, runtime, sessionIntegrationOverride) по таблице §6.5.3; зачем: defer vs immediate
  • auto-compact.ts constantsPI_AUTO_COMPACT_FOLLOW_UP_PREFIXES (документация/тесты, не runtime match); зачем: §16.9
  • auto-compact.ts hint — одноразовый ui.notify при detect Pi default compaction + pi-auto-compact; зачем: §16.7

Фаза 7 — Re-inject оркестрация

  • reinject.ts planplanReinject(state, settings, ctx, compactionEvent) → имена skills с учётом kept + registration; зачем: §5.2 п.45
  • reinject.ts defer enqueue — на session_compact: pendingReinject := plan, без sendUserMessage; зачем: §6.5.1, §16.2
  • reinject.ts defer inject — на before_agent_start: объединённое message со всеми блоками, clear queue; зачем: §5.3, §6.5.1
  • reinject.ts immediate idle — первый skill обычный, остальные followUp; зачем: §6.5.2
  • reinject.ts immediate streamingwillRetry / streaming → все deliverAs: "followUp"; зачем: §5.2, §6.5.2
  • reinject.ts skip missing — skill удалён с диска → skip + ui.notify warning; зачем: §11
  • reinject.ts force nowreinjectNow(pi, state, settings) для /skill-reinject now; зачем: §7.1 debug

Фаза 8 — Источник compaction

  • compaction.ts state machinependingCompactionSource: "auto" \| "manual" \| null; зачем: §8
  • compaction.ts input hooktext.startsWith("/compact") → manual; зачем: §8
  • compaction.ts before_compact — если не manual → auto; зачем: §8
  • compaction.ts shouldReinject — gate: enabled + source + reinjectOnManualCompaction; reset после session_compact; зачем: §5.2, §8, критерий §13

Фаза 9 — Хуки отслеживания

  • index.ts input track — на input: slash /skill:nametrackSkill; зачем: §6.2 #1
  • index.ts message_end — user messages → skill-block scan; зачем: §6.2 #2
  • index.ts tool readtool_call/tool_result с read на SKILL.md; зачем: §6.2 #3
  • index.ts persist on tracksaveState после изменения skills / session override; зачем: §6.1
  • index.ts session_compact wire — связать §78: plan → defer/immediate; зачем: end-to-end trigger

Фаза 10 — Восстановление сессии

  • index.ts session_start load — load state entry + read global settings + detectPiAutoCompact; зачем: §5.1, §16.4
  • index.ts branch rescan — если нет state entry: full rescan user messages в getBranch(); зачем: §6.3
  • index.ts resume reloadreason: "reload" \| "resume" \| "switch" — тот же путь; зачем: §6.3, /tree §11
  • index.ts session_shutdown — flush pending saveState; зачем: §11

Фаза 11 — Команды и UI

  • commands.ts registerpi.registerCommand("skill-reinject", handler); зачем: §7
  • commands.ts status — вывод без аргументов по формату §7.2 (enabled layer, delivery, tracked, pending, last compaction)
  • commands.ts session toggleon / off / reset → session override + persist; зачем: §5.1, §7.1
  • commands.ts global toggleglobal on / global off → settings.json; зачем: §7.1, критерий §13
  • commands.ts list clearlist tracked skills; clear без сброса toggle; зачем: §7.1
  • commands.ts integrationintegration auto|defer|immediate|off session override в config entry; зачем: §7.1, §16.4
  • commands.ts now — делегат в reinjectNow; зачем: §7.1
  • commands.ts aliases — опционально /sr, /skills-reinject; зачем: §7.1
  • commands.ts status linectx.ui.setStatus("skill-reinject", "on·N") на изменениях; зачем: §7.2, критерий §13

Фаза 12 — Edge cases и полировка

  • reinject.ts manual defer clear — на manual compaction: не enqueue (или clear pendingReinject на следующем user prompt при default); зачем: §16.5, §12.3 п.6
  • reinject.ts name collision — два skill с одним name → первый из resourceLoader + warn; зачем: §11
  • reinject.ts maxSkills warn — soft warn при >3 (если maxSkills не задан — unlimited); зачем: §15
  • commands.ts no-ui — RPC / hasUI === false: команды без падения, notify no-op; зачем: §11
  • index.ts double compact — каждый session_compact пересчитывает pendingReinject; зачем: §16.6

Фаза 13 — Приёмка и документация

  • README.md — статус «реализовано», установка pi -e, ссылка на /skill-reinject, coexistence с pi-auto-compact; зачем: §9.1, §16.7
  • Manual E2E standalone — прогон чеклиста §12.2 (записать результат в коммит / BACKLOG при сбоях); зачем: §12.2
  • Manual E2E pi-auto-compact — прогон §12.3 (defer, нет гонки, manual /compact); зачем: критерии §13
  • Критерии §13 — сверка всех 10 пунктов; расхождения → BACKLOG или правка SPEC

После v1 (не блокирует фазы 0–13)

Зафиксировано в SPEC §14 — не включать в чеклист v1, только при отдельном запросе:

  • reinjectOnManualCompaction: true как осознанный default-path
  • custom summary в session_before_compact
  • pi.events протокол с pi-auto-compact
  • npm package (keywords: ["pi-package"])
  • re-inject только последнего активного skill