Sleep-driven persona reconstruction: integrate experiences from
session turns, apply forgetting pressure, rewrite SOUL.md.
Blocked on TASKS-2 (orchestration) completion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor handleSessionCommand into subcommand dispatcher (list/graph/fork/reset)
- Add SessionGraphNode type and GetSessionGraph() for Mini App API
- Add /miniapp/api/sessions/graph endpoint with SSE integration
- Add session tree rendering in Mini App frontend
- Mark TASKS-3 fully complete (Phase 0-3)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce SessionRecorder interface to bridge pkg/tools → pkg/session
without circular imports. SubagentManager now records Fork, Turn, and
Completion events in SQLite. processSystemMessage writes TurnReport
directly to the store with AdvanceStored to prevent double-writes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract all unimplemented design plans and tasks from CLAUDE.md into
5 independent todo files, each targeting a separate branch for parallel
implementation:
- TASKS-1: Memory & Performance Optimization
- TASKS-2: Subagent Orchestration (Container Model)
- TASKS-3: Session DAG (SQLite Store)
- TASKS-4: Mini App & Static Serving
- TASKS-5: Heartbeat Worktree Management
CLAUDE.md now retains only implemented references, coding guidelines,
and a summary table linking to each todo file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Append refined design below the initial DAG Migration Plan, based on
SBC performance constraints and design review:
- Session-internal linearity, inter-session DAG (no per-message nodes)
- SQLite single-file backend instead of per-node JSON files
- Subagent reports as user-role turns instead of system-role merge nodes
- Turn-granularity segments with cached linear view
- Concrete Go interfaces (SessionStore, SessionGraph, TurnWriter)
- 4-phase migration path with LegacyAdapter for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design decisions from sub-agent-technical-breakdown session:
- SubagentContainer with goroutine/channel lifecycle model
- 5 presets (scout/analyst/coder/worker/coordinator)
- SandboxConfig with write root, exec allowlist regex, spawn permissions
- npm excluded from all presets (worktree node_modules problem)
- pnpm/bun/uv run added to coder and worker
- Conductor identity and orchestration guidance for system prompt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously workspace/.picoclaw/worktrees/ which created redundant
nesting since workspace is already under ~/.picoclaw/. The dot prefix
hides the directory from normal project listings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Q-1: Annotate that extractMarkdownTables() out slice already has capacity
hint (L834), only tables (L835) needs fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P-1: Add telegram.go extractMarkdownTables() tables slice to Phase 0-2.
Mark toolloop.go as already implemented in B candidate table.
Mark session_tracker.go:121 as excluded (active session count unknown at
call time, static estimate not possible).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
O-1: Fix Phase 1 annotation: add() → push() (actual ring buffer method name
at logger.go L69).
O-2: Add memory.go L567/L663 inline regexp.MustCompile to Phase 0-4 table
— both are identical to existing package variable reTaskLine (L469).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
N-1: Remove session_tracker.go ListActive() → []*SessionEntry (value copy
is the only concurrency safety with lockless Touch(); ~80 byte struct copy
is negligible at UI-request frequency).
N-2: Remove skills/registry.go pointer-to-interface proposal (SkillRegistry
is already an interface; *SkillRegistry is an antipattern; 2-5 × 16-byte
copy is negligible).
M-1: Fix Phase 3-2 scope note — replace GetReviewContext (no Split) with
GetPlanContext/FormatPlanDisplay (actual Split users).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
N-1: session_tracker.go ListActive() returning []*SessionEntry is unsafe.
Touch() mutates *SessionEntry fields directly without per-struct lock.
The current *entry value copy (L125) is the only safety mechanism. Pointer
return exposes live objects to concurrent Touch() writes. Also no meaningful
perf benefit (~80 byte structs, low-frequency UI calls). Remove from Phase 1.
N-2: skills/registry.go registries field is []SkillRegistry (interface type).
"pointer slice" would mean pointer-to-interface, a Go antipattern. Copy cost
is n*16 bytes (n=2-5 typical) — negligible. Remove from Phase 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
M-1: Phase 3-2 "効果範囲の限定" example incorrectly lists GetReviewContext
as a split optimization target — it only does sb.WriteString(content) with
no split helpers. Same for GetInterviewContext. Actual targets are
GetPlanContext and FormatPlanDisplay (already correct in the action section).
No impact on implementation correctness.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- L-1: Phase 3-2 Split target corrected from GetMemoryContext()
(which doesn't call Split helpers directly) to GetPlanContext()
and FormatPlanDisplay() (which both call extractPhaseContent,
extractCommandsSection, extractContextSection)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
L-1: Phase 3-2 incorrectly lists GetMemoryContext() as a strings.Split
optimization target — it doesn't directly call any split helpers after
Phase 3-1. GetPlanContext() is the correct target: it calls
extractPhaseContent, extractCommandsSection, extractContextSection
which all split independently on the same content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- K-1: add currentPhase inline (rePhase.FindStringSubmatch) to
FormatPlanDisplay() snippet — was missing, leaving an extra
ReadLongTerm() call
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
K-1: Phase 3-1 FormatPlanDisplay() snippet omits GetCurrentPhase() L667
inlining — currentPhase is used at L672/L676-680 and ReadLongTerm() would
remain after the fix. Add rePhase.FindStringSubmatch inline to snippet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- J-1: fix Phase 3-1 snippets — split by function, correct status
type ([]string→m[1]), move getPlanPhasesFrom to FormatPlanDisplay
- J-2: add GetPlanContext() L562-563 to Phase 3-1 targets (inline
GetCurrentPhase/GetTotalPhases to avoid 3 extra ReadLongTerm calls)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
J-1: Phase 3-1 snippet has two errors vs actual GetMemoryContext() —
getPlanPhasesFrom is only needed in FormatPlanDisplay, not GetMemoryContext;
reStatus.FindStringSubmatch returns []string not string, needs m[1] extraction.
J-2: GetPlanContext() L562-563 has the same inline-able ReadLongTerm
redundancy (GetCurrentPhase + GetTotalPhases) not addressed in Phase 3-1;
after fix GetMemoryContext would still do 4 reads instead of the implied 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- I-1: simplify Phase 4-1 — remove dirty flag, just delete save()
from RecordUsage/RecordPrompt and add ticker + Close()
- I-2: Phase 3-1 uses inline regex calls (not new private functions)
for HasActivePlan/GetPlanStatus/etc, only GetPlanPhases needs a
private variant
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Most HasActivePlan/GetPlanStatus/GetCurrentPhase/GetTotalPhases calls can
be replaced by inlining the package-level regex vars (L137-145) directly.
Only GetPlanPhases (42 lines) warrants a new private function. Reduce
estimated new function count from 5 down to 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
I-1: add exact line numbers (L61/L77/L90/L111), correct "ONLY writers"
claim (Reset() L103 also calls save()), note Close() doesn't exist yet.
I-2: add line numbers for all public methods (L148/L154/L164/L175/L270),
highlight immediate redundancy in GetMemoryContext() L730 and
FormatPlanDisplay() L658 where ReadLongTerm() result is already in scope,
note extractPhaseContent(content,phase) L231 as existing proof-of-pattern,
correct wrong HasActivePlan() body in code sample.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
I-1: Phase 4-1 dirty flag is unnecessary for stats.Tracker — only two
writers exist so data is always dirty; simplify to timer-only approach.
I-2: Phase 3-1 private helper functions (hasActivePlanFrom, etc.) do not
yet exist and must be created; plan did not make this explicit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The plan's proposed change to AddFullMessage() would reduce zero writes
because AddFullMessage() never called Save() to begin with. Save() is
called explicitly from loop.go at 5 sites; loop.go already controls
persistence timing. Phase 4-2 must be rewritten to target loop.go
Save() calls directly, particularly L996 (per-turn, high frequency).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All G-1~G-4 confirmed resolved. New findings:
H-1 Phase 4-2 misidentifies Save() trigger - it is called from 5
explicit sites in loop.go (not AddFullMessage), with L996 being the
high-frequency per-turn save and L299/836/2339/2568 as semantic
checkpoints needing individual deferral decisions.
H-2 Phase 1 logger.go row has misplaced MarkStep note from Phase 3-2.
H-3 Phase 5 missing ParsedPlan in-memory model item despite Phase 3-2
referencing it as the prerequisite for mutation-path Split fix.
H-4 Phase 3 summary still shows 1 commit; FormatPlanDisplay addition
makes it 2 commits minimum.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>