homunculus-code 0.1.0 → 0.2.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.
@@ -0,0 +1,211 @@
1
+ # Architecture: Goal-Tree-Driven Evolution
2
+
3
+ This document explains the design philosophy behind Homunculus.
4
+
5
+ ## The Problem
6
+
7
+ AI assistants are statically configured. You write rules, add skills, configure hooks — but the AI never improves on its own. Every improvement requires human effort:
8
+
9
+ 1. Notice something could be better
10
+ 2. Research the solution
11
+ 3. Implement it (skill, hook, rule, script)
12
+ 4. Test it manually
13
+ 5. Maintain it when things change
14
+
15
+ This doesn't scale. As your system grows, maintenance becomes a full-time job.
16
+
17
+ ## The Solution: Goal Trees
18
+
19
+ Instead of configuring individual behaviors, you define **what you want** in a tree of goals. The system figures out **how to achieve it** — and keeps improving the "how" over time.
20
+
21
+ ### Why a Tree?
22
+
23
+ Goals are naturally hierarchical:
24
+
25
+ ```
26
+ "Ship better software"
27
+ ├── "Write fewer bugs"
28
+ │ ├── "Every change has tests"
29
+ │ └── "Catch issues before merge"
30
+ └── "Move faster"
31
+ ├── "Automate repetitive tasks"
32
+ └── "Debug faster"
33
+ ```
34
+
35
+ A tree structure gives you:
36
+ - **Decomposition** — Break big goals into measurable sub-goals
37
+ - **Priority** — Unhealthy sub-goals bubble up to their parent
38
+ - **Independence** — Each sub-goal can be implemented differently
39
+ - **Replaceability** — Swap implementations without affecting goals
40
+
41
+ ### Goal Node Schema
42
+
43
+ Every node in the tree follows the same schema:
44
+
45
+ ```yaml
46
+ goal_name:
47
+ purpose: "Why this goal exists" # Never changes
48
+ realized_by: path/to/implementation # Changes as system evolves
49
+ metrics:
50
+ - name: metric_name
51
+ source: where to get the data
52
+ healthy: "what healthy looks like" # Defines success
53
+ health_check:
54
+ command: "shell command" # Machine-executable
55
+ expected: "human description" # For readability
56
+ goals:
57
+ sub_goal_1: ... # Recursive
58
+ sub_goal_2: ...
59
+ ```
60
+
61
+ ### The `realized_by` Field
62
+
63
+ This is the key innovation. It decouples **what** (the goal) from **how** (the implementation). The value can be:
64
+
65
+ - A skill: `skills/tdd-workflow.md`
66
+ - An agent: `agents/code-reviewer.md`
67
+ - A hook: `hooks/pre-commit.sh`
68
+ - A script: `scripts/deploy.sh`
69
+ - A cron job: `launchd/nightly.plist`
70
+ - An MCP server: `mcp-servers/github`
71
+ - A rule: `rules/security.md`
72
+ - A slash command: `commands/quality-gate.md`
73
+ - Or anything else
74
+
75
+ The evolution system can **replace** the implementation at any time, as long as the goal's health check still passes. This is what makes the system truly self-improving — it's not locked into any particular approach.
76
+
77
+ ## Evolution Pipeline
78
+
79
+ ### Layer 1: Observation → Instincts
80
+
81
+ ```
82
+ Tool usage → observe.sh (hook) → observations.jsonl
83
+
84
+ evaluate-session.js (SessionEnd)
85
+
86
+
87
+ instincts/personal/*.md
88
+ (confidence-scored patterns)
89
+ ```
90
+
91
+ Instincts are small behavioral patterns with:
92
+ - **Confidence scores** — increase with reinforcement, decay over time
93
+ - **Half-life decay** — unused instincts fade (default: 90 days)
94
+ - **Automatic archival** — `prune-instincts.js` archives low-value ones
95
+
96
+ ### Layer 2: Convergence → Skills
97
+
98
+ ```
99
+ Related instincts (3+) → /evolve → evolved/skills/*.md
100
+
101
+ eval spec (scenarios)
102
+
103
+ /eval-skill → score
104
+
105
+ /improve-skill → iterate
106
+
107
+ 100% pass rate
108
+ ```
109
+
110
+ Skills are:
111
+ - **Tested** — every skill has an eval spec with scenario tests
112
+ - **Versioned** — changes tracked with semver
113
+ - **Quality-gated** — must pass eval before adoption
114
+ - **Regression-protected** — rollback if quality drops
115
+
116
+ ### Layer 3: Goal-Directed Evolution
117
+
118
+ ```
119
+ architecture.yaml
120
+
121
+
122
+ health_check.command → pass/fail per goal
123
+
124
+
125
+ Unhealthy goals get priority
126
+
127
+
128
+ Evolution engine focuses improvement
129
+ on the weakest areas
130
+ ```
131
+
132
+ The goal tree adds **direction** to evolution. Without it, the system learns whatever patterns happen to occur. With it, the system asks: "which goals are failing?" and focuses there.
133
+
134
+ ### Layer 4: Autonomous Operation (Nightly Agent)
135
+
136
+ ```
137
+ launchd/cron → heartbeat.sh (scheduled)
138
+
139
+ ┌───────────────┼───────────────┐
140
+ ▼ ▼ ▼
141
+ Health Check Evolve Pipeline Research
142
+ │ │ │
143
+ ▼ ▼ ▼
144
+ Identify weak eval → improve Scan for better
145
+ goals → prune approaches
146
+ │ │ │
147
+ └───────────────┼───────────────┘
148
+
149
+ Morning Report
150
+ ```
151
+
152
+ The nightly agent closes the loop — no human intervention needed for routine evolution.
153
+
154
+ ### Layer 5: Meta-Evolution
155
+
156
+ The evolution mechanism itself is measured and adjusted:
157
+
158
+ | Metric | What it measures | Action if unhealthy |
159
+ |--------|-----------------|-------------------|
160
+ | `instinct_survival_rate` | % of instincts surviving 14 days | Raise extraction thresholds |
161
+ | `skill_convergence` | Time from first instinct to skill | Adjust aggregation triggers |
162
+ | `eval_discrimination` | % of scenarios that distinguish versions | Add harder boundary scenarios |
163
+
164
+ This prevents the system from degenerating — if it's extracting too many low-quality instincts, it automatically becomes more selective.
165
+
166
+ ## Design Principles
167
+
168
+ ### 1. Goals Over Implementations
169
+
170
+ Never optimize an implementation directly. Always ask: "which goal does this serve?" If there's no goal, the implementation shouldn't exist.
171
+
172
+ ### 2. Measure Everything
173
+
174
+ If you can't measure it, you can't evolve it. Every goal should eventually have a `health_check` or `metrics` entry. Start with approximate metrics and refine them.
175
+
176
+ ### 3. Replaceable Everything
177
+
178
+ No implementation is sacred. A skill can be replaced by a hook. A script can be replaced by an agent. The only constant is the goal tree.
179
+
180
+ ### 4. Safe Evolution
181
+
182
+ - Eval specs prevent regression
183
+ - Experiments run in isolated worktrees
184
+ - Rollback if quality drops
185
+ - Noise tolerance (5pp) prevents chasing statistical artifacts
186
+
187
+ ### 5. Progressive Complexity
188
+
189
+ Start simple:
190
+ 1. Just the goal tree + observation hook
191
+ 2. Let instincts accumulate naturally
192
+ 3. Evolve first skill when you have enough instincts
193
+ 4. Add eval spec for quality control
194
+ 5. Set up nightly agent when you're ready for autonomy
195
+
196
+ Don't try to build the full system on day one. Let it grow.
197
+
198
+ ## Comparison with Other Approaches
199
+
200
+ | Approach | Optimizes | Direction | Quality Control | Autonomous |
201
+ |----------|-----------|-----------|----------------|------------|
202
+ | Manual rules | Individual behaviors | Human-directed | None | No |
203
+ | Claude Memory | Fact recall | Usage-driven | None | No |
204
+ | OpenClaw skills | Skill generation | Human-triggered | None | Partial |
205
+ | **Homunculus** | **Goal achievement** | **Goal-tree-driven** | **Eval specs** | **Yes (nightly)** |
206
+
207
+ ## Further Reading
208
+
209
+ - [README.md](README.md) — Quick start and overview
210
+ - [docs/nightly-agent.md](docs/nightly-agent.md) — Setting up autonomous operation
211
+ - [examples/reference/](examples/reference/) — Real-world system after 15 days
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Homunculus for Claude Code
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/homunculus-code)](https://www.npmjs.com/package/homunculus-code)
3
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
  [![Claude Code](https://img.shields.io/badge/Claude%20Code-v2.1.70+-blue)](https://docs.anthropic.com/en/docs/claude-code)
5
6
  [![Node.js](https://img.shields.io/badge/Node.js-18+-green)](https://nodejs.org)
@@ -169,20 +170,50 @@ The wizard asks you a few questions and sets everything up:
169
170
  Done! Start using Claude Code. Your assistant will evolve.
170
171
  ```
171
172
 
172
- ### 2. Use Claude Code Normally
173
+ ### 2. Run Your First Evolution Cycle
173
174
 
174
- That's it. The system observes, extracts, and evolves in the background. Check progress anytime:
175
+ ```bash
176
+ npx homunculus-code night
177
+ ```
178
+
179
+ Watch the system check your goals, scan for patterns, and generate a report:
180
+
181
+ ```
182
+ 🌙 Homunculus — Evolution Cycle
183
+
184
+ [1/5] Health Check
185
+ code_quality: ○ no data yet
186
+ productivity: ○ no data yet
187
+
188
+ [2/5] Scan Instincts
189
+ ○ No instincts yet — use Claude Code normally, patterns will emerge
190
+
191
+ [3/5] Eval Skills
192
+ ○ No skills yet — instincts converge into skills over time
193
+
194
+ [4/5] Research
195
+ ✓ Claude Code 2.1.81
196
+ △ 0/7 goals have health checks — add more for better evolution
197
+
198
+ [5/5] Report
199
+ ┌────────────────────────────────────────────┐
200
+ │ Evolution Report — 2026-03-22 │
201
+ │ Goals: 7 | Instincts: 0 | Skills: 0 │
202
+ │ Status: Fresh install — ready to evolve │
203
+ └────────────────────────────────────────────┘
204
+ ```
205
+
206
+ ### 3. Use Claude Code Normally
207
+
208
+ The observation hook watches your usage automatically. As patterns emerge, run `night` again to see your system evolve. Or set up the [nightly agent](docs/nightly-agent.md) to do it autonomously while you sleep.
175
209
 
176
210
  ```bash
177
- claude "/eval-skill" # Run skill evaluations
211
+ npx homunculus-code night # Manual evolution cycle
212
+ claude "/eval-skill" # Evaluate a specific skill
178
213
  claude "/improve-skill" # Auto-improve a skill
179
214
  claude "/evolve" # Converge instincts into skills
180
215
  ```
181
216
 
182
- ### 3. Refine Your Goals (Optional)
183
-
184
- As you use the system, refine `architecture.yaml` — add sub-goals, metrics, and health checks. The more specific your goals, the smarter the evolution.
185
-
186
217
  ---
187
218
 
188
219
  ## Key Concepts
package/bin/cli.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ // homunculus-code CLI — entry point
3
+
4
+ const command = process.argv[2];
5
+
6
+ switch (command) {
7
+ case 'init':
8
+ require('./init.js');
9
+ break;
10
+ case 'night':
11
+ require('./night.js');
12
+ break;
13
+ case 'help':
14
+ case '--help':
15
+ case '-h':
16
+ case undefined:
17
+ console.log('');
18
+ console.log(' \x1b[1mHomunculus\x1b[0m — Self-evolving AI Assistant for Claude Code');
19
+ console.log('');
20
+ console.log(' Usage:');
21
+ console.log(' npx homunculus-code <command>');
22
+ console.log('');
23
+ console.log(' Commands:');
24
+ console.log(' init Set up Homunculus in your project');
25
+ console.log(' night Run one evolution cycle (health check → evolve → report)');
26
+ console.log(' help Show this help message');
27
+ console.log('');
28
+ console.log(' After init, use Claude Code normally. Evolution happens automatically.');
29
+ console.log(' Run "night" anytime to trigger a manual evolution cycle.');
30
+ console.log('');
31
+ break;
32
+ default:
33
+ console.error(` Unknown command: ${command}`);
34
+ console.error(' Run "npx homunculus-code help" for available commands.');
35
+ process.exit(1);
36
+ }
package/bin/night.js ADDED
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env node
2
+ // homunculus night — Run one evolution cycle
3
+ // Simulates what the nightly agent does: health check → evolve → research → report
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+
9
+ const projectDir = process.cwd();
10
+ const HOMUNCULUS_DIR = path.join(projectDir, 'homunculus');
11
+ const ARCH_FILE = path.join(projectDir, 'architecture.yaml');
12
+ const INSTINCTS_DIR = path.join(HOMUNCULUS_DIR, 'instincts', 'personal');
13
+ const ARCHIVED_DIR = path.join(HOMUNCULUS_DIR, 'instincts', 'archived');
14
+ const SKILLS_DIR = path.join(HOMUNCULUS_DIR, 'evolved', 'skills');
15
+ const EVALS_DIR = path.join(HOMUNCULUS_DIR, 'evolved', 'evals');
16
+ const OBS_FILE = path.join(HOMUNCULUS_DIR, 'observations.jsonl');
17
+ const SCRIPTS_DIR = path.join(projectDir, 'scripts');
18
+
19
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
20
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
21
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
22
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
23
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
24
+ const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
25
+
26
+ function countFiles(dir, ext = '.md') {
27
+ try {
28
+ return fs.readdirSync(dir).filter(f => f.endsWith(ext)).length;
29
+ } catch { return 0; }
30
+ }
31
+
32
+ function countLines(file) {
33
+ try {
34
+ return fs.readFileSync(file, 'utf8').trim().split('\n').filter(Boolean).length;
35
+ } catch { return 0; }
36
+ }
37
+
38
+ function sleep(ms) {
39
+ return new Promise(resolve => setTimeout(resolve, ms));
40
+ }
41
+
42
+ function parseGoals(yamlContent) {
43
+ const goals = [];
44
+ const lines = yamlContent.split('\n');
45
+ let currentGoal = null;
46
+ let indent = 0;
47
+
48
+ for (const line of lines) {
49
+ // Match top-level goals (direct children of "goals:")
50
+ const goalMatch = line.match(/^ (\w+):$/);
51
+ if (goalMatch && !line.includes('purpose') && !line.includes('metrics') &&
52
+ !line.includes('health_check') && !line.includes('realized_by') &&
53
+ !line.includes('goals:') && !line.includes('command') &&
54
+ !line.includes('expected') && !line.includes('healthy') &&
55
+ !line.includes('name:') && !line.includes('source')) {
56
+ currentGoal = goalMatch[1];
57
+ }
58
+
59
+ const purposeMatch = line.match(/purpose:\s*"(.+)"/);
60
+ if (purposeMatch && currentGoal) {
61
+ goals.push({ name: currentGoal, purpose: purposeMatch[1] });
62
+ currentGoal = null;
63
+ }
64
+ }
65
+ return goals;
66
+ }
67
+
68
+ async function main() {
69
+ console.log('');
70
+ console.log(` ${bold('🌙 Homunculus — Evolution Cycle')}`);
71
+ console.log(` ${dim(new Date().toISOString().replace('T', ' ').slice(0, 19))}`);
72
+ console.log('');
73
+
74
+ // Check if initialized
75
+ if (!fs.existsSync(HOMUNCULUS_DIR)) {
76
+ console.log(` ${red('✗')} Not initialized. Run ${bold('npx homunculus-code init')} first.`);
77
+ process.exit(1);
78
+ }
79
+
80
+ // ─────────────────────────────────────────
81
+ // Phase 1: Health Check
82
+ // ─────────────────────────────────────────
83
+ console.log(` ${bold('[1/5] Health Check')}`);
84
+ await sleep(300);
85
+
86
+ if (fs.existsSync(ARCH_FILE)) {
87
+ const yaml = fs.readFileSync(ARCH_FILE, 'utf8');
88
+ const goals = parseGoals(yaml);
89
+
90
+ if (goals.length > 0) {
91
+ for (const goal of goals) {
92
+ // Simple heuristic: if realized_by exists and points to real file = healthy
93
+ const status = yellow('○ no data yet');
94
+ console.log(` ${goal.name}: ${status}`);
95
+ console.log(` ${dim(goal.purpose)}`);
96
+ }
97
+ } else {
98
+ console.log(` ${yellow('○')} No goals defined in architecture.yaml`);
99
+ }
100
+ } else {
101
+ console.log(` ${red('✗')} architecture.yaml not found`);
102
+ }
103
+
104
+ console.log('');
105
+ await sleep(200);
106
+
107
+ // ─────────────────────────────────────────
108
+ // Phase 2: Scan Instincts
109
+ // ─────────────────────────────────────────
110
+ console.log(` ${bold('[2/5] Scan Instincts')}`);
111
+ await sleep(300);
112
+
113
+ const activeInstincts = countFiles(INSTINCTS_DIR);
114
+ const archivedInstincts = countFiles(ARCHIVED_DIR);
115
+ const observations = countLines(OBS_FILE);
116
+
117
+ if (activeInstincts > 0) {
118
+ console.log(` ${green('✓')} ${activeInstincts} active instincts (${archivedInstincts} archived)`);
119
+
120
+ // Run prune check
121
+ try {
122
+ const pruneScript = path.join(SCRIPTS_DIR, 'prune-instincts.js');
123
+ if (fs.existsSync(pruneScript)) {
124
+ const result = execSync(`node "${pruneScript}"`, {
125
+ encoding: 'utf8', timeout: 10000, cwd: projectDir
126
+ });
127
+ const candidateMatch = result.match(/Candidates:\s*(\d+)/);
128
+ if (candidateMatch && parseInt(candidateMatch[1]) > 0) {
129
+ console.log(` ${yellow('△')} ${candidateMatch[1]} instincts eligible for archival`);
130
+ }
131
+ }
132
+ } catch {}
133
+ } else if (observations > 0) {
134
+ console.log(` ${yellow('○')} ${observations} observations recorded, no instincts extracted yet`);
135
+ console.log(` ${dim('Tip: instincts are extracted at session end when enough patterns emerge')}`);
136
+ } else {
137
+ console.log(` ${yellow('○')} No instincts yet — use Claude Code normally, patterns will emerge`);
138
+ console.log(` ${dim('The observation hook is watching. Keep using Claude Code.')}`);
139
+ }
140
+
141
+ console.log('');
142
+ await sleep(200);
143
+
144
+ // ─────────────────────────────────────────
145
+ // Phase 3: Eval Skills
146
+ // ─────────────────────────────────────────
147
+ console.log(` ${bold('[3/5] Eval Skills')}`);
148
+ await sleep(300);
149
+
150
+ const skillCount = countFiles(SKILLS_DIR);
151
+ const evalCount = countFiles(EVALS_DIR, '.yaml');
152
+
153
+ if (skillCount > 0) {
154
+ console.log(` ${green('✓')} ${skillCount} evolved skills found`);
155
+
156
+ // List skills
157
+ try {
158
+ const skills = fs.readdirSync(SKILLS_DIR).filter(f => f.endsWith('.md'));
159
+ for (const skill of skills) {
160
+ const name = skill.replace('.md', '');
161
+ const hasEval = fs.existsSync(path.join(EVALS_DIR, `${name}.eval.yaml`));
162
+ if (hasEval) {
163
+ console.log(` ${green('✓')} ${name} — has eval spec`);
164
+ } else {
165
+ console.log(` ${yellow('○')} ${name} — no eval spec yet`);
166
+ }
167
+ }
168
+ } catch {}
169
+
170
+ if (evalCount > 0) {
171
+ console.log(` ${dim(`Run 'claude "/eval-skill"' to evaluate, or let the nightly agent handle it`)}`);
172
+ }
173
+ } else {
174
+ console.log(` ${yellow('○')} No skills yet — instincts converge into skills over time`);
175
+ console.log(` ${dim(`Once you have 3+ related instincts, run 'claude "/evolve"'`)}`);
176
+ }
177
+
178
+ console.log('');
179
+ await sleep(200);
180
+
181
+ // ─────────────────────────────────────────
182
+ // Phase 4: Research
183
+ // ─────────────────────────────────────────
184
+ console.log(` ${bold('[4/5] Research')}`);
185
+ await sleep(300);
186
+
187
+ // Check Claude Code version
188
+ try {
189
+ const version = execSync('claude --version 2>/dev/null', {
190
+ encoding: 'utf8', timeout: 5000
191
+ }).trim();
192
+ console.log(` ${green('✓')} Claude Code ${version}`);
193
+ } catch {
194
+ console.log(` ${yellow('○')} Claude Code version check skipped`);
195
+ }
196
+
197
+ // Check Node version
198
+ const nodeVersion = process.version;
199
+ console.log(` ${green('✓')} Node.js ${nodeVersion}`);
200
+
201
+ // Check architecture health
202
+ if (fs.existsSync(ARCH_FILE)) {
203
+ const yaml = fs.readFileSync(ARCH_FILE, 'utf8');
204
+ const goalCount = (yaml.match(/purpose:/g) || []).length;
205
+ const healthChecks = (yaml.match(/health_check:/g) || []).length;
206
+ const realizedBy = (yaml.match(/realized_by:/g) || []).length;
207
+
208
+ if (healthChecks < goalCount / 2) {
209
+ console.log(` ${yellow('△')} ${healthChecks}/${goalCount} goals have health checks — add more for better evolution`);
210
+ }
211
+ if (realizedBy < goalCount / 2) {
212
+ console.log(` ${yellow('△')} ${realizedBy}/${goalCount} goals have implementations — some are waiting to evolve`);
213
+ }
214
+ }
215
+
216
+ console.log('');
217
+ await sleep(200);
218
+
219
+ // ─────────────────────────────────────────
220
+ // Phase 5: Report
221
+ // ─────────────────────────────────────────
222
+ console.log(` ${bold('[5/5] Report')}`);
223
+ await sleep(300);
224
+
225
+ const reportDate = new Date().toISOString().slice(0, 10);
226
+ const reportLines = [];
227
+
228
+ console.log('');
229
+ console.log(` ┌${'─'.repeat(52)}┐`);
230
+ console.log(` │ ${bold(` Evolution Report — ${reportDate}`)} │`);
231
+ console.log(` ├${'─'.repeat(52)}┤`);
232
+
233
+ // Summary
234
+ const goalCount = fs.existsSync(ARCH_FILE)
235
+ ? (fs.readFileSync(ARCH_FILE, 'utf8').match(/purpose:/g) || []).length
236
+ : 0;
237
+
238
+ console.log(` │ │`);
239
+ console.log(` │ ${cyan('Goals:')} ${String(goalCount).padStart(3)} │`);
240
+ console.log(` │ ${cyan('Instincts:')} ${String(activeInstincts).padStart(3)} active / ${String(archivedInstincts).padStart(3)} archived │`);
241
+ console.log(` │ ${cyan('Skills:')} ${String(skillCount).padStart(3)} (${evalCount} with eval specs) │`);
242
+ console.log(` │ ${cyan('Observations:')} ${String(observations).padStart(5)} │`);
243
+ console.log(` │ │`);
244
+
245
+ if (activeInstincts === 0 && skillCount === 0) {
246
+ console.log(` │ ${bold('Status:')} Fresh install — ready to evolve │`);
247
+ console.log(` │ │`);
248
+ console.log(` │ ${dim('Next steps:')} │`);
249
+ console.log(` │ ${dim('1. Use Claude Code on your project')} │`);
250
+ console.log(` │ ${dim('2. Patterns will be auto-extracted')} │`);
251
+ console.log(` │ ${dim('3. Run this command again to see progress')} │`);
252
+ } else if (skillCount === 0) {
253
+ console.log(` │ ${bold('Status:')} Collecting patterns... │`);
254
+ console.log(` │ │`);
255
+ console.log(` │ ${dim('You have instincts! When 3+ are related,')} │`);
256
+ console.log(` │ ${dim('run claude "/evolve" to create your first skill.')} │`);
257
+ } else {
258
+ console.log(` │ ${bold('Status:')} ${green('Evolving')} │`);
259
+ console.log(` │ │`);
260
+ console.log(` │ ${dim('Run claude "/eval-skill" to check quality,')} │`);
261
+ console.log(` │ ${dim('or set up the nightly agent for autonomy.')} │`);
262
+ }
263
+
264
+ console.log(` │ │`);
265
+ console.log(` └${'─'.repeat(52)}┘`);
266
+ console.log('');
267
+
268
+ // Save report to file
269
+ const reportDir = path.join(HOMUNCULUS_DIR, 'reports');
270
+ if (!fs.existsSync(reportDir)) fs.mkdirSync(reportDir, { recursive: true });
271
+
272
+ const reportContent = [
273
+ `# Evolution Report — ${reportDate}`,
274
+ '',
275
+ '## Summary',
276
+ `- Goals: ${goalCount}`,
277
+ `- Instincts: ${activeInstincts} active / ${archivedInstincts} archived`,
278
+ `- Skills: ${skillCount} (${evalCount} with eval specs)`,
279
+ `- Observations: ${observations}`,
280
+ '',
281
+ `Generated by \`npx homunculus-code night\``,
282
+ ].join('\n');
283
+
284
+ fs.writeFileSync(path.join(reportDir, `${reportDate}.md`), reportContent + '\n');
285
+ console.log(` ${dim(`Report saved to homunculus/reports/${reportDate}.md`)}`);
286
+ console.log('');
287
+ }
288
+
289
+ main().catch(err => {
290
+ console.error('Error:', err.message);
291
+ process.exit(1);
292
+ });
@@ -10,7 +10,19 @@ reference/
10
10
  ├── evolved-skills/ # 7 evolved skills (all 100% eval pass)
11
11
  │ ├── api-system-diagnosis.md
12
12
  │ ├── assistant-system-management.md
13
- │ ├── claude-code-reference.md
13
+ │ ├── claude-code-reference/ # Split into index + 11 chapters (95% context reduction)
14
+ │ │ ├── index.md # Routing table — loads chapters on demand
15
+ │ │ ├── ch01-extensions.md
16
+ │ │ ├── ch02-agents.md
17
+ │ │ ├── ch03-hooks.md
18
+ │ │ ├── ch04-mcp.md
19
+ │ │ ├── ch05-ui.md
20
+ │ │ ├── ch06-rules-security.md
21
+ │ │ ├── ch07-model-memory.md
22
+ │ │ ├── ch08-workflows.md
23
+ │ │ ├── ch09-integrations.md
24
+ │ │ ├── ch10-cli-sdk.md
25
+ │ │ └── ch11-output-versions.md
14
26
  │ ├── development-verification-patterns.md
15
27
  │ ├── multi-agent-design-patterns.md
16
28
  │ ├── shell-automation-patterns.md