@oyasmi/pipiclaw 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +43 -5
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +156 -57
  4. package/dist/agent.js.map +1 -1
  5. package/dist/context.d.ts +18 -0
  6. package/dist/context.d.ts.map +1 -1
  7. package/dist/context.js +26 -0
  8. package/dist/context.js.map +1 -1
  9. package/dist/index.d.ts +7 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +6 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/llm-json.d.ts +7 -0
  14. package/dist/llm-json.d.ts.map +1 -0
  15. package/dist/llm-json.js +77 -0
  16. package/dist/llm-json.js.map +1 -0
  17. package/dist/markdown-sections.d.ts +6 -0
  18. package/dist/markdown-sections.d.ts.map +1 -0
  19. package/dist/markdown-sections.js +34 -0
  20. package/dist/markdown-sections.js.map +1 -0
  21. package/dist/memory-candidates.d.ts +21 -0
  22. package/dist/memory-candidates.d.ts.map +1 -0
  23. package/dist/memory-candidates.js +126 -0
  24. package/dist/memory-candidates.js.map +1 -0
  25. package/dist/memory-consolidation.d.ts.map +1 -1
  26. package/dist/memory-consolidation.js +28 -49
  27. package/dist/memory-consolidation.js.map +1 -1
  28. package/dist/memory-files.d.ts +3 -0
  29. package/dist/memory-files.d.ts.map +1 -1
  30. package/dist/memory-files.js +51 -0
  31. package/dist/memory-files.js.map +1 -1
  32. package/dist/memory-lifecycle.d.ts +9 -0
  33. package/dist/memory-lifecycle.d.ts.map +1 -1
  34. package/dist/memory-lifecycle.js +66 -0
  35. package/dist/memory-lifecycle.js.map +1 -1
  36. package/dist/memory-recall.d.ts +29 -0
  37. package/dist/memory-recall.d.ts.map +1 -0
  38. package/dist/memory-recall.js +218 -0
  39. package/dist/memory-recall.js.map +1 -0
  40. package/dist/prompt-builder.d.ts.map +1 -1
  41. package/dist/prompt-builder.js +7 -2
  42. package/dist/prompt-builder.js.map +1 -1
  43. package/dist/session-memory-files.d.ts +2 -0
  44. package/dist/session-memory-files.d.ts.map +1 -0
  45. package/dist/session-memory-files.js +2 -0
  46. package/dist/session-memory-files.js.map +1 -0
  47. package/dist/session-memory.d.ts +22 -0
  48. package/dist/session-memory.d.ts.map +1 -0
  49. package/dist/session-memory.js +274 -0
  50. package/dist/session-memory.js.map +1 -0
  51. package/dist/sidecar-worker.d.ts +27 -0
  52. package/dist/sidecar-worker.d.ts.map +1 -0
  53. package/dist/sidecar-worker.js +105 -0
  54. package/dist/sidecar-worker.js.map +1 -0
  55. package/dist/sub-agents.d.ts +10 -0
  56. package/dist/sub-agents.d.ts.map +1 -1
  57. package/dist/sub-agents.js +90 -0
  58. package/dist/sub-agents.js.map +1 -1
  59. package/dist/tools/index.d.ts +3 -0
  60. package/dist/tools/index.d.ts.map +1 -1
  61. package/dist/tools/index.js +2 -0
  62. package/dist/tools/index.js.map +1 -1
  63. package/dist/tools/subagent.d.ts +6 -0
  64. package/dist/tools/subagent.d.ts.map +1 -1
  65. package/dist/tools/subagent.js +127 -12
  66. package/dist/tools/subagent.js.map +1 -1
  67. package/docs/improve-memory/design.md +537 -0
  68. package/docs/improve-memory/interfaces-and-tests.md +473 -0
  69. package/docs/improve-memory/spec.md +357 -0
  70. package/docs/memory-rfc.md +7 -1
  71. package/docs/proj-review.md +188 -0
  72. package/docs/test-supplementation-plan.md +553 -0
  73. package/package.json +3 -1
@@ -0,0 +1,473 @@
1
+ # Pipiclaw Context Upgrade Interfaces And Test Plan
2
+
3
+ ## Purpose
4
+
5
+ This document turns the context-upgrade design into an implementation map:
6
+
7
+ 1. interfaces
8
+ 2. directory and file layout
9
+ 3. phased rollout plan
10
+ 4. test checklist
11
+
12
+ ## Proposed Files
13
+
14
+ ### New Files
15
+
16
+ - `src/memory-candidates.ts`
17
+ - `src/memory-recall.ts`
18
+ - `src/session-memory-files.ts`
19
+ - `src/session-memory.ts`
20
+ - `src/sidecar-worker.ts`
21
+ - `src/skill-hooks.ts`
22
+
23
+ ### Existing Files To Modify
24
+
25
+ - [src/agent.ts](/Users/oyasmi/projects/pipiclaw/src/agent.ts)
26
+ - [src/context.ts](/Users/oyasmi/projects/pipiclaw/src/context.ts)
27
+ - [src/prompt-builder.ts](/Users/oyasmi/projects/pipiclaw/src/prompt-builder.ts)
28
+ - [src/memory-files.ts](/Users/oyasmi/projects/pipiclaw/src/memory-files.ts)
29
+ - [src/memory-consolidation.ts](/Users/oyasmi/projects/pipiclaw/src/memory-consolidation.ts)
30
+ - [src/memory-lifecycle.ts](/Users/oyasmi/projects/pipiclaw/src/memory-lifecycle.ts)
31
+ - [src/sub-agents.ts](/Users/oyasmi/projects/pipiclaw/src/sub-agents.ts)
32
+ - [src/tools/subagent.ts](/Users/oyasmi/projects/pipiclaw/src/tools/subagent.ts)
33
+ - [src/config-loader.ts](/Users/oyasmi/projects/pipiclaw/src/config-loader.ts)
34
+ - [src/command-extension.ts](/Users/oyasmi/projects/pipiclaw/src/command-extension.ts)
35
+ - [src/main.ts](/Users/oyasmi/projects/pipiclaw/src/main.ts)
36
+
37
+ ## Directory Layout
38
+
39
+ ### Channel Workspace
40
+
41
+ Target layout:
42
+
43
+ ```text
44
+ <channel>/
45
+ ├── MEMORY.md
46
+ ├── SESSION.md
47
+ ├── HISTORY.md
48
+ ├── log.jsonl
49
+ ├── context.jsonl
50
+ ├── scratch/
51
+ └── skills/
52
+ ```
53
+
54
+ ### Workspace Root
55
+
56
+ Unchanged plus richer semantics:
57
+
58
+ ```text
59
+ workspace/
60
+ ├── SOUL.md
61
+ ├── AGENTS.md
62
+ ├── MEMORY.md
63
+ ├── sub-agents/
64
+ ├── skills/
65
+ └── events/
66
+ ```
67
+
68
+ ## Interface Sketches
69
+
70
+ ### 1. Memory Candidates
71
+
72
+ ```ts
73
+ export interface MemoryCandidate {
74
+ id: string;
75
+ source: "workspace-memory" | "channel-memory" | "channel-session" | "channel-history";
76
+ path: string;
77
+ title: string;
78
+ content: string;
79
+ timestamp?: string;
80
+ sectionKind?: string;
81
+ priority: number;
82
+ }
83
+
84
+ export interface BuildMemoryCandidatesOptions {
85
+ workspaceDir: string;
86
+ channelDir: string;
87
+ }
88
+
89
+ export async function buildMemoryCandidates(
90
+ options: BuildMemoryCandidatesOptions,
91
+ ): Promise<MemoryCandidate[]>;
92
+ ```
93
+
94
+ Responsibilities:
95
+
96
+ 1. read the relevant files
97
+ 2. split them into sections/blocks
98
+ 3. normalize titles and timestamps
99
+ 4. assign coarse priority hints
100
+
101
+ ### 2. Memory Recall
102
+
103
+ ```ts
104
+ export interface RecallRequest {
105
+ query: string;
106
+ workspaceDir: string;
107
+ channelDir: string;
108
+ maxCandidates: number;
109
+ maxInjected: number;
110
+ maxChars: number;
111
+ rerankWithModel: boolean;
112
+ model: Model<Api>;
113
+ resolveApiKey: (model: Model<Api>) => Promise<string>;
114
+ }
115
+
116
+ export interface RecalledMemory {
117
+ source: MemoryCandidate["source"];
118
+ path: string;
119
+ title: string;
120
+ content: string;
121
+ score: number;
122
+ }
123
+
124
+ export interface RecallResult {
125
+ items: RecalledMemory[];
126
+ renderedText: string;
127
+ }
128
+
129
+ export async function recallRelevantMemory(
130
+ request: RecallRequest,
131
+ ): Promise<RecallResult>;
132
+ ```
133
+
134
+ Responsibilities:
135
+
136
+ 1. score candidates locally
137
+ 2. optionally rerank
138
+ 3. apply caps
139
+ 4. return rendered prompt block
140
+
141
+ ### 3. SESSION.md File Helpers
142
+
143
+ ```ts
144
+ export function getChannelSessionPath(channelDir: string): string;
145
+ export async function ensureChannelSessionFile(channelDir: string): Promise<void>;
146
+ export function ensureChannelSessionFileSync(channelDir: string): void;
147
+ export async function readChannelSession(channelDir: string): Promise<string>;
148
+ export async function rewriteChannelSession(channelDir: string, content: string): Promise<void>;
149
+ ```
150
+
151
+ These should mirror existing `memory-files.ts` conventions.
152
+
153
+ ### 4. Session Memory Structure
154
+
155
+ ```ts
156
+ export interface SessionMemoryState {
157
+ title: string;
158
+ currentState: string[];
159
+ userIntent: string[];
160
+ activeFiles: string[];
161
+ decisions: string[];
162
+ constraints: string[];
163
+ errorsAndCorrections: string[];
164
+ nextSteps: string[];
165
+ worklog: string[];
166
+ }
167
+
168
+ export interface SessionMemoryUpdateOptions {
169
+ channelDir: string;
170
+ messages: AgentMessage[];
171
+ model: Model<Api>;
172
+ resolveApiKey: (model: Model<Api>) => Promise<string>;
173
+ }
174
+
175
+ export async function updateChannelSessionMemory(
176
+ options: SessionMemoryUpdateOptions,
177
+ ): Promise<SessionMemoryState>;
178
+
179
+ export function renderSessionMemory(state: SessionMemoryState): string;
180
+ ```
181
+
182
+ ### 5. Sidecar Worker
183
+
184
+ ```ts
185
+ export interface SidecarTask<T> {
186
+ name: string;
187
+ model: Model<Api>;
188
+ resolveApiKey: (model: Model<Api>) => Promise<string>;
189
+ systemPrompt: string;
190
+ prompt: string;
191
+ parse: (text: string) => T;
192
+ }
193
+
194
+ export interface SidecarResult<T> {
195
+ output: T;
196
+ rawText: string;
197
+ }
198
+
199
+ export async function runSidecarTask<T>(task: SidecarTask<T>): Promise<SidecarResult<T>>;
200
+ ```
201
+
202
+ ### 6. Settings
203
+
204
+ Extend [src/context.ts](/Users/oyasmi/projects/pipiclaw/src/context.ts) settings:
205
+
206
+ ```ts
207
+ export interface PipiclawMemoryRecallSettings {
208
+ enabled: boolean;
209
+ maxCandidates: number;
210
+ maxInjected: number;
211
+ maxChars: number;
212
+ rerankWithModel: boolean;
213
+ }
214
+
215
+ export interface PipiclawSessionMemorySettings {
216
+ enabled: boolean;
217
+ minTurnsBetweenUpdate: number;
218
+ minToolCallsBetweenUpdate: number;
219
+ forceRefreshBeforeCompact: boolean;
220
+ forceRefreshBeforeNewSession: boolean;
221
+ }
222
+ ```
223
+
224
+ ### 7. Sub-Agent Frontmatter Extensions
225
+
226
+ Extend [src/sub-agents.ts](/Users/oyasmi/projects/pipiclaw/src/sub-agents.ts):
227
+
228
+ ```ts
229
+ export interface SubAgentConfig {
230
+ // existing fields...
231
+ contextMode?: "isolated" | "contextual";
232
+ memory?: "none" | "relevant" | "session" | "channel";
233
+ paths?: string[];
234
+ thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high";
235
+ }
236
+ ```
237
+
238
+ Behavior:
239
+
240
+ 1. preserve current behavior when omitted
241
+ 2. only enrich context when explicitly configured
242
+
243
+ ### 8. Skill Frontmatter Extensions
244
+
245
+ Introduce parsing support for:
246
+
247
+ ```ts
248
+ export interface PipiclawSkillMeta {
249
+ name?: string;
250
+ description?: string;
251
+ whenToUse?: string;
252
+ allowedTools?: string[];
253
+ paths?: string[];
254
+ hooks?: {
255
+ before_prompt?: string[];
256
+ after_response?: string[];
257
+ before_compact?: string[];
258
+ after_subagent?: string[];
259
+ };
260
+ memoryScope?: "none" | "relevant" | "session";
261
+ }
262
+ ```
263
+
264
+ ## Integration Map
265
+
266
+ ### ChannelRunner
267
+
268
+ Update [src/agent.ts](/Users/oyasmi/projects/pipiclaw/src/agent.ts):
269
+
270
+ 1. before `session.prompt()`, call `recallRelevantMemory()`
271
+ 2. inject `renderedText` into the prompt if non-empty
272
+ 3. after final turn, queue `SESSION.md` maintenance when thresholds are met
273
+ 4. before session resource reload or switches, ensure session-memory hooks are respected
274
+
275
+ ### MemoryLifecycle
276
+
277
+ Update [src/memory-lifecycle.ts](/Users/oyasmi/projects/pipiclaw/src/memory-lifecycle.ts):
278
+
279
+ 1. before compact, refresh `SESSION.md`, then durable consolidation
280
+ 2. before new-session switch, refresh `SESSION.md`, then durable consolidation
281
+ 3. background maintenance expands to:
282
+ - cleanup `MEMORY.md`
283
+ - fold `HISTORY.md`
284
+ - optionally trim stale `SESSION.md` sections
285
+
286
+ ### Memory Consolidation
287
+
288
+ Update [src/memory-consolidation.ts](/Users/oyasmi/projects/pipiclaw/src/memory-consolidation.ts):
289
+
290
+ 1. read current `SESSION.md` as an additional input
291
+ 2. use it when deciding what belongs in durable memory versus active session state
292
+ 3. keep append-first behavior for `MEMORY.md`, but allow cleanup to remove transient state
293
+
294
+ ### Memory File Bootstrap
295
+
296
+ Update [src/memory-files.ts](/Users/oyasmi/projects/pipiclaw/src/memory-files.ts) and [src/main.ts](/Users/oyasmi/projects/pipiclaw/src/main.ts):
297
+
298
+ 1. ensure `SESSION.md` exists wherever channel memory files are created
299
+ 2. document it in the bootstrap-generated workspace model
300
+ 3. preserve compatibility for channel dirs created before this upgrade
301
+
302
+ ### Prompt Builder
303
+
304
+ Update [src/prompt-builder.ts](/Users/oyasmi/projects/pipiclaw/src/prompt-builder.ts):
305
+
306
+ 1. include `SESSION.md` in workspace layout and memory rules
307
+ 2. explain that memory files are not preloaded wholesale
308
+ 3. explain that runtime may inject relevant memory snippets automatically
309
+
310
+ ## Phased Rollout
311
+
312
+ ### Phase 0: Relevant Memory Recall
313
+
314
+ Deliverables:
315
+
316
+ 1. candidate builder
317
+ 2. recall scoring
318
+ 3. injected runtime context block
319
+ 4. settings toggles
320
+
321
+ Success criteria:
322
+
323
+ 1. turns involving prior channel context use the right memory more often
324
+ 2. no noticeable latency spike for common turns
325
+ 3. no huge prompt bloat
326
+
327
+ ### Phase 1: SESSION.md
328
+
329
+ Deliverables:
330
+
331
+ 1. `SESSION.md` file lifecycle
332
+ 2. session updater
333
+ 3. background thresholds
334
+ 4. prompt-builder documentation
335
+
336
+ Success criteria:
337
+
338
+ 1. current work state survives `/new`
339
+ 2. current work state survives compaction better
340
+ 3. `MEMORY.md` stops absorbing excessive transient detail
341
+
342
+ ### Phase 1.5: Compaction Bridge
343
+
344
+ Deliverables:
345
+
346
+ 1. pre-compaction session refresh
347
+ 2. durable consolidation informed by `SESSION.md`
348
+ 3. fallback semantics
349
+
350
+ Success criteria:
351
+
352
+ 1. fewer "forgot what we were doing" failures after compaction
353
+ 2. no brittle dependency on background maintenance
354
+
355
+ ### Phase 2: Contextual Sub-Agents
356
+
357
+ Deliverables:
358
+
359
+ 1. `contextMode`
360
+ 2. `memory` scope
361
+ 3. recall-aware task preamble for sub-agents
362
+
363
+ Success criteria:
364
+
365
+ 1. sub-agents require less hand-written context
366
+ 2. review and research agents produce better results on long-running channels
367
+
368
+ ### Phase 3: Skill Metadata And Hooks
369
+
370
+ Deliverables:
371
+
372
+ 1. richer frontmatter
373
+ 2. lightweight lifecycle hooks
374
+ 3. optional memory scope shaping
375
+
376
+ Success criteria:
377
+
378
+ 1. skills become better aligned with channel context
379
+ 2. skill-triggered behavior remains understandable and debuggable
380
+
381
+ ## Test Plan
382
+
383
+ ### Phase 0 Unit Tests
384
+
385
+ 1. splits `MEMORY.md`, `SESSION.md`, and `HISTORY.md` into stable candidates
386
+ 2. ranks session-current-state above old history for matching queries
387
+ 3. respects max item and max char budgets
388
+ 4. produces empty injection when nothing is relevant
389
+ 5. handles malformed or missing files gracefully
390
+
391
+ ### Phase 0 Integration Tests
392
+
393
+ 1. injected memory block appears before the user message in debug prompt output
394
+ 2. unrelated turns do not receive noisy memory injection
395
+ 3. recall remains stable when channel files are empty
396
+
397
+ ### Phase 1 Unit Tests
398
+
399
+ 1. `ensureChannelSessionFile*()` creates the default template
400
+ 2. `renderSessionMemory()` is deterministic
401
+ 3. updater preserves section boundaries
402
+ 4. updater truncates oversized sections
403
+ 5. updater can render an effectively empty but valid session file
404
+
405
+ ### Phase 1 Integration Tests
406
+
407
+ 1. a normal coding turn updates `SESSION.md`
408
+ 2. a steer/follow-up updates `SESSION.md`
409
+ 3. `/new` keeps `SESSION.md` intact for the channel
410
+ 4. existing `MEMORY.md` / `HISTORY.md` behavior continues to work
411
+ 5. an old channel directory without `SESSION.md` is repaired automatically
412
+
413
+ ### Phase 1.5 Unit Tests
414
+
415
+ 1. pre-compaction refresh is invoked before durable consolidation
416
+ 2. durable consolidation receives `SESSION.md` as input
417
+ 3. fallback uses last persisted `SESSION.md` when refresh fails
418
+ 4. cleanup can remove transient content from `MEMORY.md`
419
+
420
+ ### Phase 1.5 Integration Tests
421
+
422
+ 1. compaction followed by another turn still remembers current work
423
+ 2. new session after compaction still recovers current state
424
+ 3. failure in the updater does not crash the run loop
425
+ 4. fallback works when `SESSION.md` was missing before the first compaction
426
+
427
+ ### Phase 2 Unit Tests
428
+
429
+ 1. sub-agent config parses `contextMode` and `memory`
430
+ 2. isolated sub-agents retain current behavior
431
+ 3. contextual sub-agents receive bounded relevant memory preamble
432
+
433
+ ### Phase 2 Integration Tests
434
+
435
+ 1. reviewer sub-agent sees the right open loop without the parent hand-copying it
436
+ 2. simple sub-agents do not get unnecessary memory noise
437
+
438
+ ### Phase 3 Unit Tests
439
+
440
+ 1. skill frontmatter parsing handles new fields
441
+ 2. invalid hook declarations are rejected cleanly
442
+ 3. hook registration stays session-scoped
443
+
444
+ ### Phase 3 Integration Tests
445
+
446
+ 1. a skill with `before_compact` hook runs in the expected lifecycle
447
+ 2. a skill with `memoryScope=relevant` shapes prompt preparation predictably
448
+
449
+ ## Manual Validation Checklist
450
+
451
+ 1. Start a fresh channel and confirm `SESSION.md` is created.
452
+ 2. Run a multi-step coding task and confirm `SESSION.md` tracks active files and next steps.
453
+ 3. Trigger `/compact` and confirm current work state survives.
454
+ 4. Trigger `/new` and confirm channel working state survives but raw session history resets as expected.
455
+ 5. Use a contextual sub-agent and verify it inherits relevant channel state without seeing the full parent transcript.
456
+ 6. Confirm `MEMORY.md` remains concise and durable after repeated work cycles.
457
+ 7. Confirm `HISTORY.md` remains chronological and non-transcript-like.
458
+ 8. Restart the process mid-task and confirm the next turn recovers state primarily from `SESSION.md`.
459
+ 9. Test an older pre-upgrade channel directory and confirm migration is silent and non-destructive.
460
+
461
+ ## Open Questions To Resolve During Implementation
462
+
463
+ 1. Should `SESSION.md` keep blank stable sections, or omit empty sections for brevity?
464
+ 2. Should recall injection be visible in `last_prompt.json` as a separate field for debugging?
465
+ 3. Should `SESSION.md` cleanup run only during background maintenance, or also during forced refresh?
466
+ 4. At what point should `MEMORY.md` cleanup become allowed to remove historical transient content aggressively?
467
+
468
+ The recommended default is:
469
+
470
+ 1. deterministic rendering
471
+ 2. visible debug output
472
+ 3. cleanup in background plus light normalization in forced refresh
473
+ 4. conservative cleanup first, then more aggressive pruning only after observing real channels