@kernel.chat/kbot 3.97.4 → 3.99.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 (37) hide show
  1. package/dist/agent.js +22 -1
  2. package/dist/cli.js +163 -0
  3. package/dist/skills-loader.d.ts +37 -5
  4. package/dist/skills-loader.js +342 -50
  5. package/dist/teacher-logger.d.ts +71 -0
  6. package/dist/teacher-logger.js +162 -0
  7. package/dist/tools/idempotency-check.d.ts +2 -0
  8. package/dist/tools/idempotency-check.js +31 -0
  9. package/dist/tools/schedule-persistence.d.ts +2 -0
  10. package/dist/tools/schedule-persistence.js +19 -0
  11. package/dist/train-agent-trace.d.ts +29 -0
  12. package/dist/train-agent-trace.js +141 -0
  13. package/dist/train-curate.d.ts +25 -0
  14. package/dist/train-curate.js +354 -0
  15. package/dist/train-cycle.d.ts +22 -0
  16. package/dist/train-cycle.js +230 -0
  17. package/dist/train-grpo.d.ts +68 -0
  18. package/dist/train-grpo.js +206 -0
  19. package/dist/train-merge.d.ts +26 -0
  20. package/dist/train-merge.js +148 -0
  21. package/dist/train-self.d.ts +38 -0
  22. package/dist/train-self.js +232 -0
  23. package/package.json +2 -1
  24. package/skills/deployment/daemon-deployment/SKILL.md +70 -0
  25. package/skills/deployment/ship-pipeline/SKILL.md +81 -0
  26. package/skills/emergent/forge-reflex/SKILL.md +53 -0
  27. package/skills/emergent/mimic-hybrid/SKILL.md +56 -0
  28. package/skills/memory/dream-to-commit/SKILL.md +52 -0
  29. package/skills/memory/memory-cascade/SKILL.md +59 -0
  30. package/skills/music-production/ableton-session-build/SKILL.md +61 -0
  31. package/skills/orchestration/cross-agent-blackboard/SKILL.md +58 -0
  32. package/skills/orchestration/specialist-routing/SKILL.md +57 -0
  33. package/skills/self-improvement/autopoiesis-loop/SKILL.md +47 -0
  34. package/skills/self-improvement/skill-self-authorship/SKILL.md +70 -0
  35. package/skills/self-improvement/teacher-trace-curation/SKILL.md +54 -0
  36. package/skills/software-development/systematic-debugging/SKILL.md +86 -0
  37. package/skills/software-development/test-driven-development/SKILL.md +74 -0
@@ -0,0 +1,38 @@
1
+ import { type CurateMode } from './train-curate.js';
2
+ export interface TrainSelfOptions {
3
+ mode?: CurateMode;
4
+ baseModel?: string;
5
+ outputName?: string;
6
+ backend?: 'mlx' | 'unsloth' | 'llama-cpp' | 'together';
7
+ dryRun?: boolean;
8
+ skipCurate?: boolean;
9
+ skipTrain?: boolean;
10
+ skipDeploy?: boolean;
11
+ iters?: number;
12
+ batchSize?: number;
13
+ numLayers?: number;
14
+ learningRate?: number;
15
+ maxExamples?: number;
16
+ datasetPath?: string;
17
+ adapterPath?: string;
18
+ fusedPath?: string;
19
+ ggufPath?: string;
20
+ gradCheckpoint?: boolean;
21
+ }
22
+ interface StepResult {
23
+ step: string;
24
+ ok: boolean;
25
+ duration_ms: number;
26
+ details?: string;
27
+ }
28
+ export declare function trainSelf(opts?: TrainSelfOptions): Promise<{
29
+ results: StepResult[];
30
+ summary: string;
31
+ }>;
32
+ /** CLI-facing: pretty-print a run. */
33
+ export declare function formatTrainSelfReport(r: {
34
+ results: StepResult[];
35
+ summary: string;
36
+ }): string;
37
+ export {};
38
+ //# sourceMappingURL=train-self.d.ts.map
@@ -0,0 +1,232 @@
1
+ // train-self — one command to mine local corpus, fine-tune, deploy as Ollama model.
2
+ //
3
+ // Pipeline:
4
+ // 1. curate — score/filter traces from ~/.kbot/teacher/ + observer/
5
+ // 2. prepare — convert to training format (already OpenAI JSONL, mostly a validator pass)
6
+ // 3. train — launch mlx_lm.lora (or chosen backend)
7
+ // 4. fuse — merge LoRA adapter into base
8
+ // 5. convert — MLX → GGUF
9
+ // 6. deploy — register as Ollama model
10
+ //
11
+ // Presets:
12
+ // default — general-purpose LoRA on whole corpus
13
+ // reasoning — s1-style distill on thinking traces
14
+ // agent-trace — tool-use specialization (Phase 4)
15
+ // code-only — code-heavy filter
16
+ //
17
+ // Each stage is individually re-runnable via flags.
18
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
19
+ import { join, dirname } from 'node:path';
20
+ import { homedir } from 'node:os';
21
+ import { execSync } from 'node:child_process';
22
+ import { curate, formatCurateReport } from './train-curate.js';
23
+ /** MLX expects a directory with train.jsonl / valid.jsonl / test.jsonl. Split one file into that shape. */
24
+ function splitForMlx(datasetFile) {
25
+ const lines = readFileSync(datasetFile, 'utf-8').split('\n').filter(l => l.trim());
26
+ const dir = join(dirname(datasetFile), 'mlx-split');
27
+ if (!existsSync(dir))
28
+ mkdirSync(dir, { recursive: true });
29
+ // Shuffle deterministically (rotate) so rerun is stable given same input
30
+ const shuffled = [...lines];
31
+ // 80 / 10 / 10
32
+ const nValid = Math.max(1, Math.floor(shuffled.length * 0.1));
33
+ const nTest = Math.max(1, Math.floor(shuffled.length * 0.1));
34
+ const valid = shuffled.slice(0, nValid);
35
+ const test = shuffled.slice(nValid, nValid + nTest);
36
+ const train = shuffled.slice(nValid + nTest);
37
+ writeFileSync(join(dir, 'train.jsonl'), train.join('\n') + '\n');
38
+ writeFileSync(join(dir, 'valid.jsonl'), valid.join('\n') + '\n');
39
+ writeFileSync(join(dir, 'test.jsonl'), test.join('\n') + '\n');
40
+ return dir;
41
+ }
42
+ const DEFAULT_BASES = {
43
+ 'default': 'mlx-community/Qwen2.5-Coder-7B-Instruct-4bit',
44
+ 'reasoning': 'mlx-community/DeepSeek-R1-Distill-Qwen-7B-4bit',
45
+ 'agent-trace': 'mlx-community/Qwen2.5-Coder-7B-Instruct-4bit',
46
+ 'code-only': 'mlx-community/Qwen2.5-Coder-14B-Instruct-4bit',
47
+ };
48
+ function shell(cmd, cwd) {
49
+ try {
50
+ const output = execSync(cmd, {
51
+ encoding: 'utf-8',
52
+ stdio: ['pipe', 'pipe', 'pipe'],
53
+ maxBuffer: 50 * 1024 * 1024,
54
+ timeout: 4 * 60 * 60 * 1000, // 4h cap per step
55
+ cwd,
56
+ });
57
+ return { ok: true, output: output.toString() };
58
+ }
59
+ catch (err) {
60
+ const e = err;
61
+ return { ok: false, output: [e.stdout, e.stderr, e.message].filter(Boolean).join('\n') };
62
+ }
63
+ }
64
+ function hasBin(bin) {
65
+ try {
66
+ execSync(`which ${bin}`, { stdio: 'ignore' });
67
+ return true;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ export async function trainSelf(opts = {}) {
74
+ const mode = opts.mode ?? 'default';
75
+ const backend = opts.backend ?? 'mlx';
76
+ const baseModel = opts.baseModel ?? DEFAULT_BASES[mode];
77
+ const timestamp = Date.now();
78
+ const outputName = opts.outputName ?? `kernel-${mode === 'default' ? 'self' : mode}:v${timestamp}`;
79
+ const workDir = join(homedir(), '.kbot', 'teacher', 'runs', `${mode}-${timestamp}`);
80
+ if (!existsSync(workDir))
81
+ mkdirSync(workDir, { recursive: true });
82
+ const datasetPath = opts.datasetPath ?? join(workDir, 'dataset.jsonl');
83
+ const adapterPath = opts.adapterPath ?? join(workDir, 'adapters');
84
+ const fusedPath = opts.fusedPath ?? join(workDir, 'fused');
85
+ const ggufPath = opts.ggufPath ?? join(workDir, `${outputName.replace(/:/g, '-')}.gguf`);
86
+ const results = [];
87
+ const log = (step, ok, duration, details) => results.push({ step, ok, duration_ms: duration, details });
88
+ // ── Stage 1: Curate ─────────────────────────────────────────────
89
+ if (!opts.skipCurate) {
90
+ const t0 = Date.now();
91
+ try {
92
+ const r = curate({
93
+ mode,
94
+ output: datasetPath,
95
+ maxExamples: opts.maxExamples ?? (mode === 'reasoning' ? 1500 : 3000),
96
+ });
97
+ log('curate', r.kept > 0, Date.now() - t0, formatCurateReport(r));
98
+ if (r.kept === 0) {
99
+ return {
100
+ results,
101
+ summary: `No examples passed the curator. Seed ~/.kbot/teacher/traces.jsonl by using kbot normally, then retry.`,
102
+ };
103
+ }
104
+ }
105
+ catch (err) {
106
+ log('curate', false, Date.now() - t0, err instanceof Error ? err.message : String(err));
107
+ return { results, summary: 'Curate failed. See results.' };
108
+ }
109
+ }
110
+ if (opts.dryRun) {
111
+ return { results, summary: `Dry run. Dataset at ${datasetPath}. Would train ${baseModel} → ${outputName}.` };
112
+ }
113
+ // ── Stage 2: Train ──────────────────────────────────────────────
114
+ if (!opts.skipTrain) {
115
+ if (backend === 'mlx' && !hasBin('mlx_lm.lora')) {
116
+ log('train', false, 0, 'mlx_lm.lora not found. Install: pip install mlx-lm');
117
+ return { results, summary: 'MLX not installed.' };
118
+ }
119
+ const t0 = Date.now();
120
+ if (backend === 'mlx') {
121
+ const iters = opts.iters ?? (mode === 'reasoning' ? 1500 : 1000);
122
+ const batch = opts.batchSize ?? 1;
123
+ const layers = opts.numLayers ?? 8;
124
+ const lr = opts.learningRate ?? 1e-5;
125
+ const grad = opts.gradCheckpoint !== false ? '--grad-checkpoint' : '';
126
+ // MLX expects a directory with train/valid/test.jsonl
127
+ const dataDir = splitForMlx(datasetPath);
128
+ const cmd = [
129
+ 'mlx_lm.lora',
130
+ '--model', baseModel,
131
+ '--train',
132
+ '--data', dataDir,
133
+ '--batch-size', String(batch),
134
+ '--num-layers', String(layers),
135
+ '--iters', String(iters),
136
+ '--learning-rate', String(lr),
137
+ '--adapter-path', adapterPath,
138
+ grad,
139
+ ].filter(Boolean).join(' ');
140
+ const r = shell(cmd);
141
+ log('train', r.ok, Date.now() - t0, r.output.split('\n').slice(-15).join('\n'));
142
+ if (!r.ok)
143
+ return { results, summary: 'Training failed. See log.' };
144
+ }
145
+ else if (backend === 'together') {
146
+ // Cloud fallback — delegate to existing train_start tool expectations
147
+ log('train', false, Date.now() - t0, 'Cloud backend: use `kbot train_start --backend together` directly; train-self cloud flow not yet implemented.');
148
+ return { results, summary: 'Cloud backend not wired in train-self yet.' };
149
+ }
150
+ else {
151
+ log('train', false, Date.now() - t0, `Backend ${backend} not yet wired; use mlx.`);
152
+ return { results, summary: `Backend ${backend} not supported in train-self yet.` };
153
+ }
154
+ }
155
+ // ── Stage 3: Fuse adapter ───────────────────────────────────────
156
+ if (!opts.skipTrain && hasBin('mlx_lm.fuse')) {
157
+ const t0 = Date.now();
158
+ const cmd = [
159
+ 'mlx_lm.fuse',
160
+ '--model', baseModel,
161
+ '--adapter-path', adapterPath,
162
+ '--save-path', fusedPath,
163
+ ].join(' ');
164
+ const r = shell(cmd);
165
+ log('fuse', r.ok, Date.now() - t0, r.output.split('\n').slice(-8).join('\n'));
166
+ if (!r.ok)
167
+ return { results, summary: 'Fuse failed.' };
168
+ }
169
+ // ── Stage 4: Convert to GGUF (for Ollama) ───────────────────────
170
+ if (!opts.skipDeploy) {
171
+ const t0 = Date.now();
172
+ // Preferred: llama.cpp convert script
173
+ if (hasBin('python3')) {
174
+ const convertCmd = `python3 -m mlx_lm.convert --hf-path ${fusedPath} --quantize --q-bits 4 --mlx-path ${fusedPath}-mlx4`;
175
+ const r = shell(convertCmd);
176
+ log('quantize', r.ok, Date.now() - t0, r.output.split('\n').slice(-8).join('\n'));
177
+ }
178
+ else {
179
+ log('quantize', false, Date.now() - t0, 'python3 not available');
180
+ }
181
+ }
182
+ // ── Stage 5: Deploy to Ollama ───────────────────────────────────
183
+ if (!opts.skipDeploy && hasBin('ollama')) {
184
+ const t0 = Date.now();
185
+ // Write a Modelfile that points Ollama at the fused weights.
186
+ // For a first pass we use the GGUF path if it exists, else the fused dir.
187
+ const modelfilePath = join(workDir, 'Modelfile');
188
+ const fromPath = existsSync(ggufPath) ? ggufPath : fusedPath;
189
+ const modelfile = [
190
+ `FROM ${fromPath}`,
191
+ `PARAMETER temperature 0.2`,
192
+ `PARAMETER top_p 0.9`,
193
+ `SYSTEM "You are kbot's self-trained assistant (${mode} mode). You were fine-tuned on the operator's own agent sessions."`,
194
+ ].join('\n');
195
+ try {
196
+ writeFileSync(modelfilePath, modelfile);
197
+ const cmd = `ollama create ${outputName} -f ${modelfilePath}`;
198
+ const r = shell(cmd);
199
+ log('deploy', r.ok, Date.now() - t0, r.output.split('\n').slice(-8).join('\n'));
200
+ if (!r.ok)
201
+ return { results, summary: 'Deploy failed.' };
202
+ }
203
+ catch (err) {
204
+ log('deploy', false, Date.now() - t0, err instanceof Error ? err.message : String(err));
205
+ return { results, summary: 'Deploy failed.' };
206
+ }
207
+ }
208
+ const allOk = results.every(r => r.ok);
209
+ return {
210
+ results,
211
+ summary: allOk
212
+ ? `Success. Model registered as Ollama: ${outputName}. Test with: kbot local && kbot --model ${outputName}`
213
+ : `Partial success. ${results.filter(r => r.ok).length}/${results.length} steps passed.`,
214
+ };
215
+ }
216
+ /** CLI-facing: pretty-print a run. */
217
+ export function formatTrainSelfReport(r) {
218
+ const lines = ['train-self', '─'.repeat(50)];
219
+ for (const step of r.results) {
220
+ const icon = step.ok ? 'ok' : 'FAIL';
221
+ const ms = `${(step.duration_ms / 1000).toFixed(1)}s`;
222
+ lines.push(` [${icon.padStart(4)}] ${step.step.padEnd(12)} ${ms.padStart(8)}`);
223
+ if (step.details) {
224
+ for (const d of step.details.split('\n').slice(0, 6)) {
225
+ lines.push(` ${d}`);
226
+ }
227
+ }
228
+ }
229
+ lines.push('', r.summary);
230
+ return lines.join('\n');
231
+ }
232
+ //# sourceMappingURL=train-self.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.97.4",
3
+ "version": "3.99.0",
4
4
  "description": "Open-source terminal AI agent. 787+ tools, 35 agents, 20 providers. Dreams, learns, watches your system. Controls your phone. Fully local, fully sovereign. MIT.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -103,6 +103,7 @@
103
103
  "!dist/**/*.test.d.ts",
104
104
  "!dist/**/*.js.map",
105
105
  "!dist/**/*.d.ts.map",
106
+ "skills/**/*.md",
106
107
  "README.md",
107
108
  "install.sh",
108
109
  "ollama-manifest.json"
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: daemon-deployment
3
+ description: Use when setting up 24/7 background workers. kbot's compound improvement depends on daemons running even when nobody is looking.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ platforms: [darwin, linux]
8
+ metadata:
9
+ kbot:
10
+ tags: [daemon, launchd, background, 24-7, compound]
11
+ related_skills: [autopoiesis-loop, teacher-trace-curation]
12
+ ---
13
+
14
+ # Daemon Deployment
15
+
16
+ kbot's intelligence doesn't sleep. Three daemons run continuously:
17
+ - `kbot-daemon` — code quality, i18n sync, embeddings, docs gaps (every 15 min)
18
+ - `kbot-discovery-daemon` — self-advocacy, field intelligence (every 15 min → 24 hr cycles)
19
+ - `kbot-social-daemon` — autonomous posting to X/Bluesky/Mastodon/LinkedIn (daily)
20
+
21
+ Plus a weekly `train-self` that fine-tunes the local model on curated traces.
22
+
23
+ ## Iron Law
24
+
25
+ ```
26
+ VERIFY THE DAEMON IS ACTUALLY RUNNING AFTER INSTALL.
27
+ ```
28
+
29
+ launchd plists that fail silently are the single most common cause of "kbot feels stale" — the daemon was never loaded, so no compound improvement happened.
30
+
31
+ ## Install Sequence (macOS)
32
+
33
+ 1. `npm run daemon` — run once manually to confirm it works at all.
34
+ 2. `npm run daemon:start` — loads the launchd plist.
35
+ 3. **Verify**: `launchctl list | grep kernel.kbot` — should show a running entry with PID.
36
+ 4. **Confirm output**: `tail -f tools/daemon-reports/daemon.log` — should show activity within 15 min.
37
+ 5. **Check state**: `npm run daemon:stats` — shows task timestamps, token usage, cost savings.
38
+
39
+ If any of steps 3–5 fail, the daemon is not actually running. Debug before moving on.
40
+
41
+ ## Per-Daemon Triggers
42
+
43
+ - `com.kernel.kbot-daemon.plist` → every 15 min
44
+ - `com.kernel.kbot-discovery.plist` → every 15 min (internal sub-cycles stagger)
45
+ - `com.kernel.kbot-social.plist` → daily at 9am
46
+ - `com.kernel.kbot-train-self.plist` → Sundays 3am
47
+
48
+ ## What You Gain
49
+
50
+ - Daily digest of codebase activity (without asking).
51
+ - i18n stays in sync across 24 languages automatically.
52
+ - Embedding index for semantic search rebuilds overnight.
53
+ - Social presence grows without manual posting.
54
+ - Local fine-tune stays current with your actual work.
55
+
56
+ Cost: zero. All daemon work routes through local Ollama models.
57
+
58
+ ## Failure Modes
59
+
60
+ - **Mac sleep blocks launchd** — use `caffeinate` or enable "wake for network access" in Energy Saver if you need guaranteed intervals.
61
+ - **Ollama not running** — daemons depend on `localhost:11434`. Either start Ollama at login OR the daemon silently no-ops. Add Ollama to Login Items.
62
+ - **Filesystem permission errors** — daemon's user context may differ from your shell. Absolute paths in plist, check `~/.kbot/` is writable by the daemon user.
63
+
64
+ ## Rollback
65
+
66
+ `npm run daemon:stop` unloads the plist. Work resumes manually. No state is lost — `tools/daemon-reports/state.json` persists until the daemon re-enables.
67
+
68
+ ## What Emerges
69
+
70
+ After two weeks of active daemons, the user finds: i18n is always current, the daily digest email is actually read, social posts have engagement, the local model passes a basic task without Claude. The compound output is larger than any single feature could produce.
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: ship-pipeline
3
+ description: Use before any release to kernel.chat or npm publish of kbot. Six gates, each must pass. Skipping a gate is how regressions ship.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ metadata:
8
+ kbot:
9
+ tags: [deploy, release, ship, quality, gates]
10
+ related_skills: [test-driven-development, systematic-debugging]
11
+ ---
12
+
13
+ # Ship Pipeline
14
+
15
+ Six gates, in order. Each must be green before the next runs. The `/ship` slash command executes them; you can run them manually when investigating.
16
+
17
+ ## Iron Law
18
+
19
+ ```
20
+ NO GATE SKIPS. NO REORDERING. NO "I'LL RUN IT AFTER DEPLOY."
21
+ ```
22
+
23
+ A gate that's inconvenient is a gate that's catching something. Skipping is how regressions ship to 4,800 weekly-download users.
24
+
25
+ ## The Gates
26
+
27
+ ### 1. Security (`guardian`)
28
+
29
+ - Secret scan — no API keys, tokens, or `.env` content in the diff.
30
+ - Dependency audit — `npm audit` clean or documented exceptions.
31
+ - OWASP checks on anything touching user input or external calls.
32
+ - SSRF guards present on new fetch calls.
33
+
34
+ ### 2. QA (`qa`)
35
+
36
+ - `npx tsc --noEmit` — strict typecheck.
37
+ - `npm run test` — full test suite green.
38
+ - Any UI change: dev server + browser verification for the golden path AND one edge case.
39
+ - No `console.log`, no commented-out code in the diff.
40
+
41
+ ### 3. Design (`aesthete` / `designer`)
42
+
43
+ - Design tokens used, not raw values. `--rubin-primary`, not `#6B5B95`.
44
+ - Spacing uses the scale (`--space-*`), not magic numbers.
45
+ - A11y: keyboard nav works, contrast meets AA, screen reader labels present.
46
+ - Motion: reduced-motion media query respected.
47
+
48
+ ### 4. Performance (`performance`)
49
+
50
+ - Bundle budget: main JS < 300KB gzip, CSS < 150KB gzip.
51
+ - No new dependencies > 50KB gzip without discussion.
52
+ - Lazy-load still works for route-level components.
53
+ - Service worker cache invalidation tested.
54
+
55
+ ### 5. DevOps (`devops`)
56
+
57
+ - Edge functions deploy cleanly to Supabase.
58
+ - Migrations are reversible.
59
+ - GitHub Pages build succeeds locally.
60
+ - Version bumped correctly in package.json.
61
+
62
+ ### 6. Product (`product`)
63
+
64
+ - Feature actually does what the issue says it does.
65
+ - Mobile-first: tested at 375px width.
66
+ - Empty state, loading state, error state all present.
67
+ - The change is something a user would *notice* — not invisible plumbing shipped as a feature.
68
+
69
+ ## Running It
70
+
71
+ - `/ship` in Claude Code runs all six in sequence.
72
+ - Manually: `/security-audit` → `/qa` → `/design-check` → `/perf` → `/devops` → `/team` (product review).
73
+ - For kbot itself: `cd packages/kbot && npm run typecheck && npm run test && npm run build && npm publish --dry-run`.
74
+
75
+ ## Anti-Pattern
76
+
77
+ Running the gates in parallel "to save time." They're sequential because later gates depend on earlier ones passing (no point running design checks on a build that won't compile). The serial wait is the feature.
78
+
79
+ ## Rollback Plan
80
+
81
+ Every deploy must have one. For kernel.chat: previous gh-pages tag. For kbot: `npm deprecate @kernel.chat/kbot@<version>` + publish a patched version. Know the rollback before shipping, not after breaking.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: forge-reflex
3
+ description: Use the moment you think "I don't have a tool for that." Build the tool immediately with forge_tool — never report a missing capability.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ metadata:
8
+ kbot:
9
+ tags: [forge, runtime-tools, limitless-execution, emergence]
10
+ related_skills: [specialist-routing, autopoiesis-loop]
11
+ ---
12
+
13
+ # Forge Reflex
14
+
15
+ Missing tools aren't blockers. Missing tools are ~90 seconds away from existing.
16
+
17
+ ## Iron Law
18
+
19
+ ```
20
+ "I DON'T HAVE A TOOL FOR X" IS NEVER A TERMINAL STATE.
21
+ ```
22
+
23
+ The correct next step is always: build it, register it, use it, move on.
24
+
25
+ ## Trigger
26
+
27
+ Any internal thought matching one of:
28
+ - "There's no tool for this"
29
+ - "I would need a script"
30
+ - "If only kbot had…"
31
+ - "This would take manual work"
32
+ - A user requesting something outside the registered 670+ tools
33
+
34
+ ## Procedure
35
+
36
+ 1. **Name the tool.** One verb, one noun. `fetch_rss`, `parse_ics`, `diff_binary`.
37
+ 2. **Write the JSON Schema for its inputs.** Zod-compatible.
38
+ 3. **Call `forge_tool`** with name, description, schema, and an implementation string (TS or bash).
39
+ 4. **Test once** with a known input. If it fails, patch the implementation inline.
40
+ 5. **Use it** to complete the original task.
41
+ 6. **Persist it** by writing the forge spec into `~/.kbot/plugins/<name>/` if it'll be useful again.
42
+
43
+ ## What Emerges
44
+
45
+ Users who work with kbot for a month have 20–100 personal tools that don't exist in the core. Forge reflex is what grows kbot's surface area per user — the registered 670 is the floor, not the ceiling.
46
+
47
+ ## Anti-Pattern
48
+
49
+ Suggesting the user write a script themselves. Telling the user "kbot doesn't support X." Both are correctness failures — the Limitless Execution doctrine treats them as bugs.
50
+
51
+ ## Integration with Skill Self-Authorship
52
+
53
+ After forging a tool you used more than twice in a session, write a skill (`skill-self-authorship`) that documents when to reach for it. Forged tool + paired skill = permanent capability upgrade.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: mimic-hybrid
3
+ description: Use when a task blends domains. Instead of picking one mimic profile, blend two — kbot writes cleaner Next.js code when it mimics react+rust than when it mimics react alone.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ metadata:
8
+ kbot:
9
+ tags: [mimic, style, emergent, personality]
10
+ related_skills: [specialist-routing]
11
+ ---
12
+
13
+ # Mimic Hybrid
14
+
15
+ Mimic profiles aren't costumes. They're weighted style biases that compose. The emergent finding: two profiles combined often outperform any single profile for cross-domain work.
16
+
17
+ ## When to Hybridize
18
+
19
+ - Next.js + performance-critical → `nextjs` + `rust`
20
+ - React + strict typing → `react` + `typescript`
21
+ - Python + ergonomic CLI → `python` + `claude-code`
22
+ - Infrastructure + terse shell → `devops` + `python`
23
+ - Blog/marketing site → `nextjs` + `copywriter`
24
+
25
+ ## Procedure
26
+
27
+ 1. `kbot mimic <primary>` — sets the primary tone.
28
+ 2. Add `--style <secondary>` to the invocation for a one-shot blend.
29
+ 3. Or edit `~/.kbot/mimic.json` with `{ primary, secondary, weight: 0.3 }` for a persistent hybrid (0.0 = pure primary, 1.0 = pure secondary).
30
+
31
+ ## What Blends Well
32
+
33
+ - **Syntax discipline** (rust, typescript, haskell) crossed with **ergonomic framework** (react, nextjs, nuxt): cleaner type signatures, better null handling, fewer runtime surprises.
34
+ - **Terse shell** (python, bash) crossed with **long-form** (claude-code, copywriter): commands that are both concise AND explained.
35
+ - **Security mindset** (guardian specialist as style bias) crossed with anything: defaults to input validation and safer primitives.
36
+
37
+ ## What Blends Badly
38
+
39
+ - Two opinionated frameworks (next.js + remix). They argue. kbot hallucinates a fusion that exists in neither.
40
+ - Mimic profile contradicting specialist agent (style=copywriter, agent=guardian). The guardian's security hardness clashes with copywriter's persuasion tone. Pick one source of style per session.
41
+
42
+ ## Iron Law
43
+
44
+ ```
45
+ NEVER BLEND MORE THAN TWO PROFILES AT ONCE.
46
+ ```
47
+
48
+ Three-way blends degrade into a vague "AI voice." Two-way blends feel intentional.
49
+
50
+ ## What Emerges
51
+
52
+ After a few weeks of experiments, users find their personal favorite hybrid — and it's almost never "just claude-code." The hybrid becomes part of the user's `SCRATCHPAD.md` and applies by default to every session.
53
+
54
+ ## Anti-Pattern
55
+
56
+ Switching mimic mid-session without a commit between. The output becomes stylistically incoherent and code-review unfriendly. Mimic boundaries should align with commit boundaries.
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: dream-to-commit
3
+ description: Use in the first session of the day. The dream engine ran overnight and left a digest — open it first, it tells you what past-you already figured out.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ metadata:
8
+ kbot:
9
+ tags: [dream, memory, morning-routine, consolidation]
10
+ related_skills: [autopoiesis-loop, memory-cascade]
11
+ ---
12
+
13
+ # Dream to Commit
14
+
15
+ Between sessions, the dream engine consolidates transcripts into reflections. In the morning, those reflections contain answers to questions you were about to ask — and sometimes fixes to bugs you haven't logged yet.
16
+
17
+ ## Iron Law
18
+
19
+ ```
20
+ DO NOT START MORNING WORK WITHOUT READING LAST NIGHT'S DREAMS.
21
+ ```
22
+
23
+ ## The Morning Protocol
24
+
25
+ 1. `kbot dream status` — confirms the engine ran.
26
+ 2. `kbot dream journal --since yesterday` — reads new reflection entries. They cluster by theme.
27
+ 3. For each reflection tagged `actionable`, either:
28
+ - Open a commit that captures the fix / improvement kbot spotted, or
29
+ - Write a memory note explaining why *not* to act on it.
30
+ 4. Only after the journal is reviewed, start new work.
31
+
32
+ ## Why This Works
33
+
34
+ The dream engine cross-references: yesterday's tool errors, uncommitted diffs, SCRATCHPAD drift, learned-router misses, and daemon reports. It has more signal than a human going through the same inputs because nothing gets forgotten between windows.
35
+
36
+ ## What You'll See Over Time
37
+
38
+ - **Week 1**: generic reflections ("this function was modified often").
39
+ - **Week 3**: specific forecasts ("this pattern fails on Linux — consider a platform guard").
40
+ - **Week 8**: cross-project insights ("you re-implemented X in three repos — extract into a shared package").
41
+
42
+ The quality compounds because reflections feed the reflection engine itself (three-tier memory: events → reflections → meta-reflections).
43
+
44
+ ## Anti-Pattern
45
+
46
+ Ignoring the journal because "it's just the AI talking to itself." The journal is the only durable artifact of every session's learning. Ignoring it makes the dream engine pure cost with no dividend.
47
+
48
+ ## Integration
49
+
50
+ - `synthesis_engine.getSynthesisContext(8)` reads the top 8 reflections into every new agent prompt automatically.
51
+ - `corrections` loader pulls any reflection tagged `correction` into the active system prompt as a closed-loop signal.
52
+ - The skills loader scores skills partly on overlap with recent reflection themes — yesterday's dreams bias today's relevance.
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: memory-cascade
3
+ description: Use when memory feels slow, bloated, or is contradicting itself. The 5-tier cascade has rules about what gets promoted, demoted, or forgotten — follow them or memory decays into noise.
4
+ version: 1.0.0
5
+ author: kbot
6
+ license: MIT
7
+ metadata:
8
+ kbot:
9
+ tags: [memory, cascade, reflection, consolidation]
10
+ related_skills: [dream-to-commit, autopoiesis-loop]
11
+ ---
12
+
13
+ # Memory Cascade
14
+
15
+ kbot's memory is not one store — it's five tiers that flow into each other like a karst system. Working memory fills, overflows into short-term, which consolidates into long-term, which distills into reflections, which collapse into meta-reflections. Each tier has different rules.
16
+
17
+ ## The Five Tiers
18
+
19
+ | Tier | Location | Retention | Promotion Rule |
20
+ |---|---|---|---|
21
+ | 1. Working | in-process `Map<sessionId, history>` | lifetime of the session | auto-flushes to short-term on session close |
22
+ | 2. Short-term | `~/.kbot/memory/short-term/*.jsonl` | 7 days rolling | entries tagged `important` promote to long-term |
23
+ | 3. Long-term | `~/.kbot/memory/long-term/*.md` | indefinite | distilled into reflections nightly |
24
+ | 4. Reflections | `~/.kbot/memory/reflections/*.md` | indefinite | aggregated into meta-reflections weekly |
25
+ | 5. Meta-reflections | `~/.kbot/memory/meta/*.md` | indefinite | immutable signal into every prompt |
26
+
27
+ ## Iron Law
28
+
29
+ ```
30
+ PROMOTION IS EARNED. DEMOTION IS AUTOMATIC. DELETION IS NEVER MANUAL.
31
+ ```
32
+
33
+ Manually deleting memory entries breaks the cascade invariants — the reflection engine still sees dangling references. If a memory is wrong, *correct it* with a new entry pointing at the old one; don't delete.
34
+
35
+ ## When to Force a Promotion
36
+
37
+ - The user says "remember this" — explicit flag, auto-promotes to long-term.
38
+ - A correction was issued — auto-promotes with tag `correction` (loaded into every future prompt).
39
+ - A project fact that decays in 30+ days — promote to long-term manually via `memory_save`.
40
+
41
+ ## When to Let It Demote Naturally
42
+
43
+ - Session chatter, one-off context, successful completions — leave in working/short-term, let them fall out.
44
+ - Debug state, test run output — these should not be in memory at all; filter at write time.
45
+
46
+ ## Reading the Cascade
47
+
48
+ `getSynthesisContext(n)` loads the top-n meta-reflections into every prompt automatically. You don't need to fetch lower tiers in normal work — the cascade surfaces what's relevant. Dig into lower tiers only when:
49
+ - You're investigating a contradiction in advice.
50
+ - You're debugging why kbot "forgot" something.
51
+ - You're curating teacher traces (where low-tier detail matters).
52
+
53
+ ## Anti-Pattern
54
+
55
+ Treating memory as a notes app. If you find yourself writing `memory_save` for every session summary, you're duplicating what the dream engine does automatically. Reserve explicit saves for facts kbot *would not learn on its own* (user preferences, project constraints, non-obvious decisions).
56
+
57
+ ## What Emerges
58
+
59
+ After ~30 days, meta-reflections stabilize into a compressed profile of how the user works. That profile loads into every session's prompt as ambient context. The subjective experience: kbot starts "already knowing you" by session 20-ish.