TODO: fill implementation plan — 14 phases from SPEC
Atomic checklists for phases 0–13 so agents can run the AGENTS.md cycle without re-deriving scope from SPEC. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -89,13 +89,173 @@
|
||||
|
||||
## Фазы реализации
|
||||
|
||||
_Пункты чеклиста добавляет владелец репозитория. Агент не заполняет фазы без запроса._
|
||||
| Фаза | Название | Зависимости | Критерии 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 и полировка | 7–11 | §11 |
|
||||
| 13 | Приёмка и документация | 0–12 | §12–13 |
|
||||
|
||||
<!-- Пример структуры (удалить при первом заполнении):
|
||||
**Порядок:** фазы 0→13; внутри фазы — сверху вниз. Параллельно после фазы 0 можно вести 1 и 2; фазы 3 и 4 — независимы друг от друга.
|
||||
|
||||
### Фаза 0 — Каркас
|
||||
---
|
||||
|
||||
- [ ] **package.json** — manifest, devDependencies Pi
|
||||
- [ ] **src/index.ts** — пустой extension, регистрация на session_start
|
||||
### Фаза 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 scripts** — `typecheck`, `test`, `build` (минимально); зачем: единая проверка в каждом пункте
|
||||
- [ ] **src/index.ts shell** — `export default function(pi: ExtensionAPI)`, пустой `session_start`; зачем: smoke `pi -e ./src/index.ts` без логики
|
||||
|
||||
---
|
||||
|
||||
### Фаза 1 — Состояние и персистенция
|
||||
|
||||
- [ ] **state.ts types** — `TrackedSkill`, `ExtensionState` (version 1), `RuntimeFlags`; зачем: единый контракт §6.1
|
||||
- [ ] **state.ts initial** — `createInitialState()`, `createRuntimeFlags()`; зачем: предсказуемый старт сессии
|
||||
- [ ] **state.ts persist** — `saveState(pi, state)` через `appendEntry("skill-reinject:state", …)`; зачем: пережить `/resume` (§6.1)
|
||||
- [ ] **state.ts load** — `loadStateFromBranch(branch)` из последнего custom entry; зачем: восстановление без полного rescan
|
||||
- [ ] **state.ts trackSkill** — upsert по `name`, merge `sources`, preserve insertion order; зачем: дедуп §6.1
|
||||
|
||||
---
|
||||
|
||||
### Фаза 2 — Настройки
|
||||
|
||||
- [ ] **settings.ts types** — `SkillReinjectSettings` + 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 effective** — `effectiveEnabled(sessionOverride, global)`, `effectiveIntegration(...)`; зачем: три слоя §5.1
|
||||
- [ ] **test/settings.test.ts** — defaults, merge write (mock/temp file); зачем: §12.1
|
||||
|
||||
---
|
||||
|
||||
### Фаза 3 — Детекция skills
|
||||
|
||||
- [ ] **detect.ts slash** — `detectSlashSkill(text)` → `/^\/skill:([a-z0-9-]+)/`; зачем: источник `slash` §6.2
|
||||
- [ ] **detect.ts skill-block** — `parseSkillBlocksFromText(text)` (regex как `parseSkillBlock`); зачем: источник `skill-block` §6.2
|
||||
- [ ] **detect.ts read-path** — `matchReadPathToSkill(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 readBody** — `readSkillBody(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 slice** — `getKeptEntries(branch, firstKeptEntryId)` от compaction entry до хвоста; зачем: §6.4
|
||||
- [ ] **kept.ts present** — `skillsPresentInKeptWindow(keptEntries, skillNames)` по `<skill name="…"`; зачем: не дублировать блоки §6.4, критерий §13
|
||||
- [ ] **kept.ts filter** — `filterSkillsNeedingReinject(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 detect** — `detectPiAutoCompact(pi)` через `getCommands()` → `auto-compact`; кэш в `RuntimeFlags`; зачем: §16.4
|
||||
- [ ] **auto-compact.ts deliveryMode** — `resolveDeliveryMode(settings, runtime, sessionIntegrationOverride)` по таблице §6.5.3; зачем: defer vs immediate
|
||||
- [ ] **auto-compact.ts constants** — `PI_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 plan** — `planReinject(state, settings, ctx, compactionEvent)` → имена skills с учётом kept + registration; зачем: §5.2 п.4–5
|
||||
- [ ] **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 streaming** — `willRetry` / streaming → все `deliverAs: "followUp"`; зачем: §5.2, §6.5.2
|
||||
- [ ] **reinject.ts skip missing** — skill удалён с диска → skip + `ui.notify` warning; зачем: §11
|
||||
- [ ] **reinject.ts force now** — `reinjectNow(pi, state, settings)` для `/skill-reinject now`; зачем: §7.1 debug
|
||||
|
||||
---
|
||||
|
||||
### Фаза 8 — Источник compaction
|
||||
|
||||
- [ ] **compaction.ts state machine** — `pendingCompactionSource: "auto" \| "manual" \| null`; зачем: §8
|
||||
- [ ] **compaction.ts input hook** — `text.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:name` → `trackSkill`; зачем: §6.2 #1
|
||||
- [ ] **index.ts message_end** — user messages → skill-block scan; зачем: §6.2 #2
|
||||
- [ ] **index.ts tool read** — `tool_call`/`tool_result` с `read` на `SKILL.md`; зачем: §6.2 #3
|
||||
- [ ] **index.ts persist on track** — `saveState` после изменения skills / session override; зачем: §6.1
|
||||
- [ ] **index.ts session_compact wire** — связать §7–8: 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 reload** — `reason: "reload" \| "resume" \| "switch"` — тот же путь; зачем: §6.3, `/tree` §11
|
||||
- [ ] **index.ts session_shutdown** — flush pending `saveState`; зачем: §11
|
||||
|
||||
---
|
||||
|
||||
### Фаза 11 — Команды и UI
|
||||
|
||||
- [ ] **commands.ts register** — `pi.registerCommand("skill-reinject", handler)`; зачем: §7
|
||||
- [ ] **commands.ts status** — вывод без аргументов по формату §7.2 (enabled layer, delivery, tracked, pending, last compaction)
|
||||
- [ ] **commands.ts session toggle** — `on` / `off` / `reset` → session override + persist; зачем: §5.1, §7.1
|
||||
- [ ] **commands.ts global toggle** — `global on` / `global off` → settings.json; зачем: §7.1, критерий §13
|
||||
- [ ] **commands.ts list clear** — `list` tracked skills; `clear` без сброса toggle; зачем: §7.1
|
||||
- [ ] **commands.ts integration** — `integration 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 line** — `ctx.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
|
||||
|
||||
Reference in New Issue
Block a user