You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- live_view: render cancelled todos (✕, muted+struck) instead of dropping
them from the pinned list, now that "cancelled" is a valid todo status
- wire/server: pop dismissed QuestionRequests from the pending map on steer
so a late client response can't double-resolve a superseded question
- ui/shell: log (don't silently swallow) failures to write the fallback
429 diagnostic, so that diagnostic path stays debuggable
- mcp_resource: add -> None to the public constructors per the annotation
guideline
- tests: drop unused params, remove a duplicate @pytest.mark.asyncio, split
chained assertions; add coverage for the three behavioral fixes above
- tasks/*.md: fix markdownlint blank-line nits
Skipped as stale or out of policy: ruff-format/typos findings already fixed
in earlier commits; an MD037 false positive on snake_case prose; narrowing
the best-effort asyncio-warning catch (would reintroduce a crash path).
FIT: Transfers. Pruning stale tool outputs is backend-only and orthogonal to UI. One caveat: pythinker's append-only JSONL context (context.py) makes in-place part mutation harder than kilo's SQLite part-update model, so the implementation must rewrite the context file (as clear()/revert_to() already do) rather than mutate a part. Manageable, hence effort L.
90
90
91
91
## [ctxmgmt-3] Recall is one-shot injection only; no model-invocable cross-session recall tool
GAP: Pythinker's recall is push-only and fires once: a fact that becomes relevant mid-session (after the single injection) is not re-surfaced until compaction re-arms it, and the model has no way to actively ask 'what did I decide in the session where I set up the CI pipeline?' and read that transcript. Kilo gives the agent agency to retrieve prior-session context on demand, which is exactly what long, resumed coding tasks need.
94
95
ACTION: Add a first-class, model-invocable Recall tool that (a) lists/searches prior sessions by title/recency/relevance and (b) returns ranked excerpts (or the full transcript) of a chosen prior session's context.jsonl on demand — i.e. give the agent agency to pull cross-session context mid-task instead of relying solely on the one-shot push injection. Scope the rec correctly: the underlying data (context.jsonl transcripts + state.json todos under ~/.pythinker/sessions/) is already durably persisted and is technically reachable today via the unsandboxed Shell tool (cat/grep), so this is NOT about making data reachable — it is about replacing a brittle raw-file escape hatch with a designed, semantically-searchable, approval-aware, sanitized affordance (reuse the existing LexicalRetriever BM25 + memory/sanitize.py threat scanning that the push path already uses). Do NOT claim the transcript is currently unreachable by the model; the accurate framing is 'no purpose-built recall tool; only an ungainly shell hatch + one-shot push injection.'
Copy file name to clipboardExpand all lines: tasks/_gap_extract.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -186,6 +186,7 @@ The real gap is in the generic ToolResultBuilder truncation path (tools/utils.py
186
186
- **refined:** Add a cheaper intermediate tier between "do nothing" and full SimpleCompaction. Concretely: (1) introduce a lower trigger threshold below the 0.85/reserved-buffer point that, instead of LLM summarization, walks history and replaces large COMPLETED tool-result message bodies in DEEP history (older than the last N turns) with a short placeholder (e.g. "[tool output elided: 40k chars, ToolName, ts]"), preserving conversational/tool-call structure and ids; (2) only escalate to full SimpleCompaction (compaction.py / pythinkersoul.py:1261) when this fidelity-preserving pruning fails to bring token_count back under the higher threshold. Reuse existing wiring: gate it in the should_auto_compact branch at pythinkersoul.py:1252-1272 and add a `prune_stale_tool_outputs(history)` helper alongside SimpleCompaction. Drop/deprioritize the separate "post-compaction pruning to reclaim subsumed tool outputs" idea — full compaction already clears everything, so that sub-step is only meaningful for the new intermediate tier, where it is the whole point.
187
187
188
188
### [ctxmgmt-3] Recall is one-shot injection only; no model-invocable cross-session recall tool
-**severity:** medium | **verdict:** partial (0.82) | **effort:** M | **risk:** low
191
192
-**pythinker now:** memory/recall.py:218-270 RecallInjectionProvider fires exactly once per context (self._injected guard) and re-arms ONLY on compaction (on_context_compacted) or explicit rearm. It BM25-ranks MEMORY/USER/JOURNAL/scratch + recent-session open todos against the last user message and injects them as a system-reminder. The model cannot proactively pull a *prior session's full transcript* mid-task: there is no recall tool in tools/ (confirmed: tools/ has agent, ask_user, background, dmail, file, memory, plan, scratchpad, shell, skill, think, todo, web — no recall). Cross-session knowledge is limited to (a) durable MEMORY/USER facts and (b) open-todo titles, surfaced passively at injection time.
Copy file name to clipboardExpand all lines: tasks/pythinker-agent-enhancement-plan.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -271,6 +271,7 @@ Phases are ordered by impact×effort and by dependency. Within a phase, items ar
271
271
### Phase 3 — Memory & recall agency
272
272
273
273
#### 3.1 — Model-invocable cross-session `Recall` tool (`memory-1` / `ctxmgmt-3`) · M · med
274
+
274
275
-**Current.** Recall is push-only and fires once; the agent cannot actively ask "what did I decide in the session where I set up CI?" and read that transcript. Distilled JOURNAL recaps lose load-bearing detail (exact commands, paths, rationale). The data *is* durably persisted (`context.jsonl` under the sessions dir) and technically reachable via the unsandboxed Shell — so this replaces a brittle `cat`/`grep` escape hatch with a designed, sanitized, approval-aware affordance.
275
276
-**Target.** The agent has agency to search and read prior sessions on demand.
276
277
-**Change.** Add a root-agent, read-only `Recall` tool (`tools/recall/`) with two modes: (1) **search** prior sessions by topic/file/date over `wire.jsonl`/`context.jsonl` using the existing `LexicalRetriever` BM25+recency (`memory/retriever.py`), scoped to the current `project_memory.project_key`, returning id/title/ts/snippet; (2) **read** a chosen session's transcript span via `Session.list_all` (`session.py:278`) + `wire_file.iter_records`. Cap returned bytes/turns; **sanitize via `memory/sanitize.py`** (a prior transcript is untrusted input → also subject to §1's wrapping). Gate cross-workspace reads behind Approval. Register read-only in `agents/default/agent.yaml`.
0 commit comments