Compound learning
Senkani mines your own sessions for patterns and surfaces four artifact types: filter rules, context docs, instruction patches, workflow playbooks. Patterns flow .recurring → .staged → .applied.
The lifecycle
Every session's tool calls, outputs, and retries are logged to the session DB. A daily sweep (lazy — runs at session start) looks at the recurring set and promotes any pattern meeting recurrence ≥ 3 AND confidence ≥ 0.7 (Laplace-smoothed) to .staged. You review staged proposals in the Sprint Review pane or via senkani learn review. Accepted proposals move to .applied; applied artifacts take effect on the next session.
Filter rules (H, H+1)
The post-session waste analyzer notices when output from command X gets repeatedly truncated to its first N lines or has a substring stripped. It proposes a filter rule (head(50), stripMatching("progress")) for future invocations. Regression-gated on real commands.output_preview samples — the proposed rule must not break outputs that previously passed through cleanly.
Context docs (H+2b)
Files read across ≥ 3 distinct sessions become priming documents at .senkani/context/<title>.md, injected into the next session's brief as a one-line "Learned:" section. The body is scanned by SecretDetector on every read and write.
Instruction patches (H+2c) — never auto-apply
Tool hints derived from per-session retry patterns. Example: if the agent consistently retries Read after getting an outline when it wanted full content, an instruction patch proposes tweaking the tool's description to clarify the full: true parameter. Never applied automatically from the daily sweep — Schneier constraint forces explicit senkani learn apply <id>. The rationale: instruction drift is a subtle prompt-injection surface; you want a human in the loop.
Workflow playbooks (H+2c)
Named multi-step recipes mined from ordered tool-call pairs within a 60-second window. Applied at .senkani/playbooks/learned/<title>.md — namespace-isolated from shipped skills so the two don't collide.
Prompt-side artifact gate (V.4 round 1)
Skills, hook prompts, MCP tool descriptions, and brief templates land in their own pre-merge gate — PromptArtifactRegressionGate — distinct from the H+1 RegressionGate that scores filter-rule savings. A candidate body is checked against an EvalCorpus of labeled .mustContain / .mustNotContain / .maxLength requirements. Score is (passing, total, cost); cost is the body's utf8 byte count. The gate accepts when candidate.passing ≥ baseline.passing — equal-passing-with-lower-cost is legal because ReflectiveLearningRun retains a Pareto frontier on (passing↑, cost↓) per artifact kind, persisted at .senkani/learn/pareto/<kind>.json. The Propose-step hook CompoundLearning.runReflectiveLearning is operator-triggered, not auto-fired in runPostSession — round 1 is the scaffold; an LLM-driven mutator and a pre-merge CLI surface arrive in V.4-bis.
Session continuity (W.4 round 1)
Long autonomous sessions hit a hard ceiling: the active context window. ContextSaturationGate is a pure decision (.ok / .warn / .block) that reads tokens_in + tokens_out from agent_trace_event and divides by a configurable budgetTokens (defaults: warn 65 %, block 80 %, 200 000-token active window — the Continuous Claude v4.7 pattern). When the gate blocks, PreCompactHandoffWriter lands a structured handoff card under ~/.senkani/handoffs/<sessionId>.json with openFiles, currentIntent, lastValidation (pulled from validation_results), nextActionHint, and the most-recent trace keys for the pane. Writes are atomic — temp file, fsync, rename — so a crash mid-write never leaves a half-card readable. PreCompactHandoffLoader.load(...) / loadLatest(...) reads the card on the next session start and returns nil for missing / corrupt / future-schema files. Round 1 lands the gate, the writer, and the loader; HookRouter PreCompact wiring + a status-bar saturation chip + senkani doctor --handoff are W.4-bis (operator decision pending — needs a review of which hook payload fields the writer should auto-fill).
Annotation evidence (V.6 round 1)
Operator-tagged verdicts on a skill or KB entity feed Analyze as read-only evidence. Each annotation row carries a target_kind (skill / kb-entity), an inclusive byte range, a verdict (works / fails / note), free-text notes, an authored_by handle, and a V.5 AuthorshipTag. Annotations are append-only — a new verdict supersedes by recency, never by mutation — and they survive an artifact rename via renameAnnotationTarget. AnnotationSignalGenerator.analyze rolls evidence up per (kind, target), classifies each as failing / working / mixed, and bumps compound_learning.annotation.observed + per-class counters during runPostSession. Round 1 stops at evidence — no rule mutation, no auto-staging. Operators' fails calls are ground truth, never silently inferred into a learned rule.
Enrichment via Gemma (H+2a)
Gemma 4 optionally enriches the rationale strings that accompany each proposal, via MLX. The enriched text lives in a dedicated enrichedRationale field — never enters FilterPipeline. This is deliberate: the enrichment improves the human review experience; it doesn't alter the runtime behavior.
Cadence
- Sprint review —
senkani learn review [--days 7]. Go through staged proposals weekly. - Quarterly audit —
senkani learn audit [--idle D]. Check applied artifacts for currency; retire stale ones.
KB ↔ learning bridge
High-mention entities from the knowledge base boost compound-learning confidence; applied context docs seed KB entity stubs; rolling back a KB entity cascades to invalidate derived context docs. The two systems are not isolated — they're sources for each other.