feat(loop): structured planning system — plan tool, protected state, restart resume, Telegram/WebUI surfaces - #143
Open
jkyberneees wants to merge 3 commits into
Open
feat(loop): structured planning system — plan tool, protected state, restart resume, Telegram/WebUI surfaces#143jkyberneees wants to merge 3 commits into
jkyberneees wants to merge 3 commits into
Conversation
…ate, restart resume
One built-in plan tool (create/update/complete/get) maintains engine-held
PlanState rendered into a protected [Current plan: system message using the
compaction-digest pattern: upsert-in-place, headLen/trimToSurvival protection,
restart resume via strict fail-closed transcript parsing. Safe-classified
(never prompts), untrusted-wrapped with audit ingest recording, config-gated
(planning.{enabled,max_steps,max_render_chars}, --no-planning, ODEK_PLANNING;
project config may only lower caps). Overflow renders with an omission marker
for live context but is rejected on resume; corrupt persisted plans are
dropped in both directions. Reference doc: docs/PLANNING.md.
Reviewed: 7 findings (2 HIGH) fixed and mutation-verified; race-clean; 30+
new tests across loop/config/cmd suites.
…ew, /plan_status, WebUI panel
Observability: additive odek.event/v1 types plan_created/plan_updated emitted
once per effective version-bumping mutation via PlanStore.SetOnChange;
payloads carry counts + version only (never titles/notes). Shared exported
extractor loop.ExtractPlan (newest-parseable-wins, fail-closed) backs both
read-only surfaces:
- GET /api/sessions/{id}/plan — sibling auth/rate-limit path, GET-only,
found:false when absent, 404 unknown session.
- Telegram /plan_status — chat-scoped structured-plan reply (glyphs per
status, MarkdownV2-literal escaping of model-derived fields, rune-safe
truncation, 3800-char bound); coexists with markdown-file /plan.
- WebUI plan panel — drawer tab polling the endpoint every 5s while visible
(runtime events relay to the /api/events ring only; WS transport is a
drop-in swap when it lands), textContent-only rendering pinned by an
innerHTML tripwire test, session-switch/visibility lifecycle covered.
- Emoji: plan → 📋 in both renderers; vestigial todo arm retired.
Docs: PLANNING.md observability + surface sections rewritten as reference,
WEBUI/TELEGRAM/EXTENSIONS/API/CHEATSHEET updated.
Reviewed: APPROVE (0 critical/high); reviewer LOWs fixed in-commit
(MarkdownV2 literal escaping, rune-boundary truncation, cap-drift doc note).
Tests: 24 new Go tests + 19 JS tests; race-clean.
Table-driven behavioral tests for parser internals: header variants, omission-marker semantics (incl. [+0 …] not being an overflow marker), wrapper unwrap rejections and newline artifacts, step-line rejections with exact error strings, number-parsing boundaries, degenerate NewPlanStore caps falling back to defaults, nil-store tool Call guard, blocked-count event payload, UTF-8-boundary render hard-cut. Two remaining uncovered blocks are provably unreachable defensive guards.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
odek | 5902828 | Commit Preview URL Branch Preview URL |
Aug 24 2026, 08:03 PM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a structured planning layer to odek's ReAct loop and exposes it across surfaces. Design spec:
docs/PLANNING.md(rewritten as reference documentation).Core (33a8337)
plantool (create/update/complete/get) maintaining engine-heldPlanState; wholesalecreateis replanning[Current plan:system message using the compaction-digest pattern: survives graduated trimming, survival trim, and process restarts (rides per-step session persistence;odek continuerestores forward state via strict fail-closed transcript parsing)classifyToolCall— never prompts; untrusted-wrapped with audit ingest recording; overflow renders with an omission marker for live context but is rejected on resume; corrupt persisted plans dropped fail-closed in both directionsplanning.{enabled,max_steps,max_render_chars},--no-planning,ODEK_PLANNING=false; project config may only lower caps; disabled ⇒ tool absent, zero plan logicSurfaces (84e9b2e)
odek.event/v1typesplan_created/plan_updated(counts + version only — never titles/notes; pinned by whole-stream marshal-and-scan test)GET /api/sessions/{id}/plan— read-only, sibling auth/rate-limit path, GET-only enforced structurally/plan_status— chat-scoped structured-plan reply; MarkdownV2-literal escaping of model-derived fields; rune-safe truncation; coexists with markdown-file/plan/api/eventsring only; WS transport is a drop-in swap when it lands), textContent-only rendering pinned by an innerHTML tripwire testplan→ 📋 in both renderers; vestigialtodoarm retiredCoverage (5902828)
internal/loop/plan.go: 91.4% → 99.4% statements; every function ≥96.4%, most 100%. Remaining 2 blocks are provably unreachable defensive guards (documented)ui/js/plan.jsat 98.35%How loop performance improves
odek continueresume from an actionable queue instead of transcript archaeology (verified live: kill mid-run at exit 4, resume completed all remaining steps with zero rework)Test plan
go test ./...scoped suites green;-raceclean oninternal/loop;node --test87/87security_report_validation_test.goOut of scope (roadmap in docs/PLANNING.md)
Plan-aware stall-recovery suffix, blocked-step trigger +
plan_blockedsignal, exhaustion remaining-steps blocks, WS event relay for live panel updates.