-
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathpalinode.config.yaml.example
More file actions
387 lines (357 loc) · 13.6 KB
/
palinode.config.yaml.example
File metadata and controls
387 lines (357 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# =============================================================================
# Palinode Configuration
# =============================================================================
# Copy this file to `palinode.config.yaml` in your Palinode directory.
# All values shown are defaults — only override what you need.
# -----------------------------------------------------------------------------
# Memory Directory
# -----------------------------------------------------------------------------
# Where Palinode stores markdown memory files and the SQLite-vec index.
# All paths below are relative to this directory unless absolute.
memory_dir: "~/palinode"
# SQLite-vec database location (relative to memory_dir)
db_path: ".palinode.db"
# -----------------------------------------------------------------------------
# Recall (Context Injection)
# -----------------------------------------------------------------------------
# Controls what gets injected into the agent's context each turn.
recall:
enabled: true
# Phase 1: Core memory (files with `core: true` in frontmatter)
core:
# Maximum characters per core file before truncation
max_chars_per_file: 3000
# Maximum total characters for all core files combined
max_total_chars: 8000
# Directories to scan for core files
directories:
- people
- projects
- decisions
- insights
# Tiered injection to save tokens on non-first turns
tiering:
# Turn 1: full core content. Full core re-injected every N turns.
# Primary trigger: full core is always injected on turn 1 AND after
# any session compaction (context was summarized, injection was lost).
# The turn counter is a last-resort fallback if compaction hooks fail.
full_refresh_every_n_turns: 200 # Fallback only — set high, compaction hook is primary
# What to inject on turns between full refreshes:
# "none" — skip core entirely (default). Model has it from turn 1.
# Saves ~200 tokens/turn. Works because context persists until compaction.
# "summary" — inject one-line summaries of core files (~200 tokens).
# "full" — inject full core every turn (~2K tokens). Very expensive.
mid_turn_mode: "none"
# If mid_turn_mode is "summary": skip files without a summary: field
skip_unsummarized: true
# Phase 2: Semantic search based on user's message
search:
enabled: true
# Number of results to inject
top_k: 3
# Maximum characters per search result chunk
max_chars_per_chunk: 500
# Similarity threshold (0.0 = everything, 1.0 = exact match)
threshold: 0.4
# Skip search for messages shorter than this (trivial acks)
min_query_length: 15
# Skip search for these exact messages (case-insensitive)
trivial_patterns:
- "ok"
- "yep"
- "sure"
- "thanks"
- "thx"
- "cool"
- "got it"
- "nice"
- "lol"
- "k"
- "np"
# -----------------------------------------------------------------------------
# Capture (Session-End Extraction)
# -----------------------------------------------------------------------------
capture:
enabled: true
# Session-end extraction
extraction:
# Maximum memories to extract per session
max_items_per_session: 5
# Minimum session turns before extraction fires
min_turns: 3
# Memory types to auto-extract
types:
- Decision
- ProjectSnapshot
- Insight
- PersonMemory
- ActionItem
# Daily notes (session logging)
daily:
enabled: true
# Max recent messages to append to daily notes
max_messages: 10
# Max total characters per session append
max_chars: 2000
# -es quick capture flag
quick_capture:
enabled: true
# Minimum input length for -es to fire
min_chars: 5
# Chars above which text is treated as ResearchRef
long_text_threshold: 500
# -----------------------------------------------------------------------------
# Ingestion Pipeline
# -----------------------------------------------------------------------------
ingestion:
# Inbox directory for dropped files (relative to memory_dir)
inbox_dir: "inbox/raw"
processed_dir: "inbox/processed"
# Maximum characters to extract from PDFs
pdf_max_chars: 10000
# Maximum characters to extract from URLs
url_max_chars: 10000
# Transcriptor API for audio/video files
transcriptor:
url: "http://localhost:8787"
timeout_seconds: 600
# -----------------------------------------------------------------------------
# Embeddings
# -----------------------------------------------------------------------------
embeddings:
# Primary embedding backend (used for all core memory)
primary:
provider: "ollama"
model: "bge-m3"
url: "http://localhost:11434"
dimensions: 1024
# Timeout for first call (model loading)
timeout_seconds: 120
connect_timeout_seconds: 10
# Secondary embedding backend (used for research ingestion)
# Set enabled: false to use primary for everything
research:
enabled: false
provider: "gemini"
model: "gemini-embedding-2-preview"
dimensions: 768
# API key from environment: GEMINI_API_KEY
timeout_seconds: 30
# -----------------------------------------------------------------------------
# Auto-Summary
# -----------------------------------------------------------------------------
auto_summary:
enabled: true
# Model used for generating summaries (should be fast and small)
model: "qwen2.5:14b-instruct"
# Maximum summary length in characters
max_chars: 120
# Minimum content length to trigger summary generation
min_content_chars: 200
# Ollama URL for summary generation (uses embeddings.primary.url if not set)
# ollama_url: "http://localhost:11434"
# -----------------------------------------------------------------------------
# Search Defaults
# -----------------------------------------------------------------------------
search:
# Hybrid search combines vector similarity with BM25 keyword matching.
# This catches exact terms (model names, IDs, code) that vectors miss.
hybrid_enabled: true
# Balance: 0.0 = vector only, 1.0 = BM25 only, 0.5 = equal weight
hybrid_weight: 0.5
# Default threshold for MCP server searches (lower = more results)
mcp_threshold: 0.4
# Default threshold for FastAPI searches (higher = more precision)
api_threshold: 0.6
# Default number of results
default_limit: 10
# Status values to exclude from search results
exclude_status:
- "archived"
# -----------------------------------------------------------------------------
# Consolidation
# -----------------------------------------------------------------------------
# Three-tier memory freshness:
# Tier 1: Session append — free, every session exit (hook or MCP call).
# Appends summary to daily/{date}.md + one-liner to projects/{slug}-status.md.
# Tier 2: Nightly dedup — lightweight LLM pass over today's notes.
# UPDATE/SUPERSEDE only. No restructuring, no archival.
# Tier 3: Weekly deep clean — full compaction with MERGE/ARCHIVE.
# Restructures status files, archives processed daily notes.
#
# HOW TO INSTALL CRON JOBS:
# # Nightly — lightweight dedup of today's sessions (Tier 2)
# 0 11 * * * cd /path/to/palinode && PALINODE_DIR=/path/to/data \
# venv/bin/python -m palinode.consolidation.cron --nightly --days 1 \
# >> /path/to/data/logs/consolidation.log 2>&1
#
# # Weekly — full compaction (Tier 3)
# 0 11 * * 0 cd /path/to/palinode && PALINODE_DIR=/path/to/data \
# venv/bin/python -m palinode.consolidation.cron --days 3 \
# >> /path/to/data/logs/consolidation.log 2>&1
#
# TIMING NOTES:
# - Times above are UTC. Adjust for your timezone (11:00 UTC = 4am PT).
# - Nightly runs daily; weekly runs Sundays. On Sundays both fire —
# nightly first (UPDATE/SUPERSEDE), then weekly (full ops). No conflict.
# - The `schedule` field below is informational only — actual scheduling
# is via crontab, systemd timers, or your preferred scheduler.
#
consolidation:
enabled: true
# Informational — actual schedule lives in crontab (see above)
schedule: "0 11 * * 0" # Sunday 4am PT (11:00 UTC)
# How many days of daily notes to process (weekly full pass)
lookback_days: 7
# Maximum daily files to process per run
max_files: 30
# LLM API for consolidation (any OpenAI-compatible endpoint)
llm_url: "http://localhost:8000" # vLLM, Ollama, etc.
# llm_model: model path or identifier for your LLM backend
# Examples:
# vLLM: "/model" (default path)
# Ollama: "llama3.1:8b" or "qwen2.5:14b-instruct"
llm_model: "/model"
llm_temperature: 0.3
llm_max_tokens: 2000
# Nightly pass configuration (Tier 2)
nightly:
enabled: true
# How many days to look back (1 = today only)
lookback_days: 1
# Restrict to safe, additive operations — no restructuring
allowed_ops: ["UPDATE", "SUPERSEDE"]
# Write-time contradiction check (Tier 2a — ADR-004)
# When enabled, every palinode_save schedules a background LLM check against
# the top-k most similar existing memories. If a contradiction is found, the
# deterministic executor applies an UPDATE/SUPERSEDE op in a separate commit.
# Runs asynchronously — never blocks the save caller.
#
# Default: disabled. Flip to true after validating in a dev environment.
# Sync opt-in: set query param ?sync=true on /save or pass --sync to CLI.
write_time:
enabled: false
queue_max_size: 1000
check_timeout_seconds: 30
pending_dir: ".palinode/pending"
sweep_on_startup: true
# Optional: map project entity refs to keywords for auto-grouping
# daily notes that don't contain explicit `project/foo` entity refs.
# keyword_map:
# "project/my-app": ["my-app", "MyApp", "the app"]
# -----------------------------------------------------------------------------
# Compaction
# -----------------------------------------------------------------------------
compaction:
allowed_ops: ["KEEP", "UPDATE", "MERGE", "SUPERSEDE", "ARCHIVE"]
aggressiveness: "moderate" # conservative | moderate | aggressive
# Layer split heuristics — these keywords classify ## section headings
# into Identity (slow-changing) vs Status (fast-changing) layers.
#
# HOW THESE WERE DETERMINED:
# Initial guesses based on common markdown heading conventions.
# Not scientifically derived — tune them to match your actual file structure.
#
# HOW TO EVOLVE THEM:
# 1. Run: curl -X POST http://localhost:6340/split-layers
# 2. Run: git -C ~/palinode-data diff (see what was classified)
# 3. Add/remove keywords below to correct misclassifications
# 4. Or: add `layer_hint: status` to a file's frontmatter to force-override
#
layer_split:
identity_keywords:
- "architecture"
- "context"
- "people"
- "canon"
- "what this is"
- "key decisions"
- "overview"
- "about"
- "design"
- "stack"
- "key files"
- "follow-up"
- "who"
- "background"
- "principles"
status_keywords:
- "current"
- "status"
- "milestone"
- "active"
- "this week"
- "open"
- "consolidation log"
- "todo"
- "in progress"
- "recent"
- "progress"
- "now"
- "today"
- "next"
- "blocking"
# Fallback: sections with a date like 2026-03-29 → Status
date_pattern: "\\d{4}-\\d{2}-\\d{2}"
# -----------------------------------------------------------------------------
# Temporal Decay
# -----------------------------------------------------------------------------
# Time constants (tau) in days describing how fast memories decay
decay:
enabled: false
# Core unchanging facts
tau_critical: 180
# Significant architectural decisions
tau_decisions: 60
# General insights and observations
tau_insights: 90
# Default standard notes
tau_general: 30
# Weekly statuses and ephemeral updates
tau_status: 7
# Daily logs not meant for long term without consolidation
tau_ephemeral: 1
# -----------------------------------------------------------------------------
# Services
# -----------------------------------------------------------------------------
services:
# FastAPI server
api:
host: "127.0.0.1" # SECURITY: bind to localhost only. Set to 0.0.0.0 only if you need LAN access.
port: 6340
log_level: "INFO"
# File watcher daemon
watcher:
# Debounce: ignore rapid file changes within this window
debounce_seconds: 1.0
# -----------------------------------------------------------------------------
# Security
# -----------------------------------------------------------------------------
security:
# YAML file with regex patterns to scrub before context injection
scrub_patterns_file: "specs/scrub-patterns.yaml"
# If true, never include file paths containing these strings in search results
# (defense in depth — scrub_patterns handles content, this handles file selection)
exclude_paths:
- ".secrets"
- "credentials"
- "passwords"
# -----------------------------------------------------------------------------
# Git Integration
# -----------------------------------------------------------------------------
git:
# Auto-commit after saves
auto_commit: true
# Auto-push after commits (requires remote configured)
auto_push: false
# Commit message prefix
commit_prefix: "palinode"
# -----------------------------------------------------------------------------
# Logging
# -----------------------------------------------------------------------------
logging:
level: "INFO"
# JSONL operation log (relative to memory_dir)
operations_log: "logs/operations.jsonl"
# Log to stdout as well
console: true