homunculus-code
Advanced tools
@@ -304,2 +304,12 @@ #!/usr/bin/env node | ||
| log(`Extraction failed: ${err.message?.slice(0, 100)}`); | ||
| // When called from a CC hook subprocess, claude --print cannot access | ||
| // Keychain/OAuth tokens and will fail with auth errors. Queue the prompt | ||
| // so the next manual or scheduled run (outside hook context) can process it. | ||
| try { | ||
| ensureDir(REPORTS_DIR); | ||
| const queueFile = path.join(REPORTS_DIR, 'extraction-queue.jsonl'); | ||
| const entry = JSON.stringify({ timestamp: new Date().toISOString(), prompt }); | ||
| fs.appendFileSync(queueFile, entry + '\n'); | ||
| log(`Queued for retry → ${queueFile} (next run outside hook context will process)`); | ||
| } catch {} | ||
| return null; | ||
@@ -309,2 +319,43 @@ } | ||
| // Process any queued extraction prompts (written when called from hook context) | ||
| function processQueue({ existing, todayCount, dynamicLimit }) { | ||
| const queueFile = path.join(REPORTS_DIR, 'extraction-queue.jsonl'); | ||
| if (!fs.existsSync(queueFile)) return { instincts: 0, memory: 0, research: 0 }; | ||
| // Still in hook context — skip, let the next run handle it | ||
| if (process.env.CLAUDECODE) return { instincts: 0, memory: 0, research: 0 }; | ||
| const lines = fs.readFileSync(queueFile, 'utf8').trim().split('\n').filter(Boolean); | ||
| if (!lines.length) return { instincts: 0, memory: 0, research: 0 }; | ||
| log(`Processing ${lines.length} queued extraction(s)...`); | ||
| const stats = { instincts: 0, memory: 0, research: 0 }; | ||
| for (const line of lines) { | ||
| let entry; | ||
| try { entry = JSON.parse(line); } catch { continue; } | ||
| if (!entry.prompt) continue; | ||
| const env = { ...process.env }; | ||
| delete env.CLAUDECODE; | ||
| const model = process.env.HOMUNCULUS_HARVEST_MODEL || 'claude-sonnet-4-6'; | ||
| try { | ||
| const result = execSync( | ||
| `claude --print --model ${model} --max-turns 1 --no-session-persistence`, | ||
| { input: entry.prompt, encoding: 'utf8', timeout: 120000, env, stdio: ['pipe', 'pipe', 'pipe'] } | ||
| ).trim(); | ||
| const s = processResult(result, { existing, todayCount: todayCount + stats.instincts, dynamicLimit }); | ||
| stats.instincts += s.instincts; | ||
| stats.memory += s.memory; | ||
| stats.research += s.research; | ||
| } catch (err) { | ||
| log(`Queue entry failed: ${err.message?.slice(0, 80)}`); | ||
| } | ||
| } | ||
| // Clear processed queue | ||
| try { fs.unlinkSync(queueFile); } catch {} | ||
| log(`Queue done: ${stats.instincts} instincts, ${stats.memory} memory, ${stats.research} research`); | ||
| return stats; | ||
| } | ||
| // Process extraction result — parse JSON lines and route to appropriate handlers | ||
@@ -427,9 +478,18 @@ function processResult(result, { existing, todayCount, dynamicLimit }) { | ||
| // Process any prompts queued from previous hook-context runs | ||
| const queueStats = processQueue({ existing, todayCount, dynamicLimit }); | ||
| const afterQueue = todayCount + queueStats.instincts; | ||
| if (afterQueue >= dynamicLimit) { | ||
| log(`Limit reached after queue processing (${afterQueue}/${dynamicLimit}), skipping current session`); | ||
| if (queueStats.instincts > 0) updateCooldown(afterQueue); | ||
| return; | ||
| } | ||
| log(`Analyzing: ${analysis.total_observations} observations, ${analysis.frequent_tools.length} patterns (limit: ${dynamicLimit})`); | ||
| const result = extractFromSession(analysis); | ||
| const stats = processResult(result, { existing, todayCount, dynamicLimit }); | ||
| const stats = processResult(result, { existing, todayCount: afterQueue, dynamicLimit }); | ||
| if (stats.instincts > 0) { | ||
| updateCooldown(todayCount + stats.instincts); | ||
| if (stats.instincts > 0 || queueStats.instincts > 0) { | ||
| updateCooldown(afterQueue + stats.instincts); | ||
| } | ||
@@ -436,0 +496,0 @@ |
+13
-0
@@ -169,2 +169,15 @@ **语言:** [English](../../README.md) | [繁體中文](../zh-TW/README.md) | [简体中文](README.md) | ||
| ### v0.10.1 — Hook 认证 Fallback (Apr 2026) | ||
| - **Hook context queue fallback** — `evaluate-session.js` 现在能优雅地处理从 CC hook 子进程调用时 `claude --print` 失败的情况(Keychain/OAuth 无法访问)。失败的提取会写入 `homunculus/reports/extraction-queue.jsonl`,下次在 hook context 外执行时(手动调用或 `/hm-night`)自动消费 | ||
| ### v0.10.0 — Durability Gate & Multi-Run Eval (Apr 2026) | ||
| - **Durability Gate** — `durability_score < 0.7` 的 instinct 会被过滤;事件特定模式不再污染系统 | ||
| - **Gaming Gate** — 分数跳升 >5pp 但只改了 ≤3 行的情况标记为 `gaming_suspected` 并丢弃 | ||
| - **Multi-run eval** — `--runs N` 和 `--passes N` 支持多次独立 eval + 多数决,降低 LLM 评判误差 | ||
| - **CLAUDE.md 覆盖率检查** — 已实现的规则注入提取 prompt,避免重复提取既有行为 | ||
| - **Bash 失败断路器** — `observe.sh` 追踪最近 10 次失败,用于进化分析 | ||
| - **文档简化** — 移除对外文档中的 P0/P1A/B/C 内部命名,更清晰的心智模型 | ||
| ### v0.9.0 — 进化引擎升级 (Mar 2026) | ||
@@ -171,0 +184,0 @@ |
+13
-0
@@ -169,2 +169,15 @@ **語言:** [English](../../README.md) | [繁體中文](README.md) | [简体中文](../zh-CN/README.md) | ||
| ### v0.10.1 — Hook 認證 Fallback (Apr 2026) | ||
| - **Hook context queue fallback** — `evaluate-session.js` 現在能優雅地處理從 CC hook 子進程呼叫時 `claude --print` 失敗的情況(Keychain/OAuth 無法存取)。失敗的提取會寫入 `homunculus/reports/extraction-queue.jsonl`,下次在 hook context 外執行時(手動呼叫或 `/hm-night`)自動消費 | ||
| ### v0.10.0 — Durability Gate & Multi-Run Eval (Apr 2026) | ||
| - **Durability Gate** — `durability_score < 0.7` 的 instinct 會被過濾;事件特定模式不再污染系統 | ||
| - **Gaming Gate** — 分數跳升 >5pp 但只改了 ≤3 行的情況標記為 `gaming_suspected` 並丟棄 | ||
| - **Multi-run eval** — `--runs N` 和 `--passes N` 支援多次獨立 eval + 多數決,降低 LLM 評判誤差 | ||
| - **CLAUDE.md 覆蓋率檢查** — 已實作的規則注入提取 prompt,避免重複提取既有行為 | ||
| - **Bash 失敗斷路器** — `observe.sh` 追蹤最近 10 次失敗,用於演化分析 | ||
| - **文件簡化** — 移除對外文件中的 P0/P1A/B/C 內部命名,更清晰的心智模型 | ||
| ### v0.9.0 — Evolution Engine 升級 (Mar 2026) | ||
@@ -171,0 +184,0 @@ |
+1
-1
| { | ||
| "name": "homunculus-code", | ||
| "version": "0.10.0", | ||
| "version": "0.10.1", | ||
| "description": "A self-evolving AI assistant that grows smarter every night", | ||
@@ -5,0 +5,0 @@ "bin": { |
+13
-0
@@ -169,2 +169,15 @@ **Language:** [English](README.md) | [繁體中文](docs/zh-TW/README.md) | [简体中文](docs/zh-CN/README.md) | ||
| ### v0.10.1 — Hook Auth Fallback (Apr 2026) | ||
| - **Queue fallback for hook context** — `evaluate-session.js` now gracefully handles the case where `claude --print` fails from a CC hook subprocess (Keychain/OAuth not accessible). Failed extractions are queued to `homunculus/reports/extraction-queue.jsonl` and automatically processed on the next run outside hook context (e.g. manual call or `/hm-night`) | ||
| ### v0.10.0 — Durability Gate & Multi-Run Eval (Apr 2026) | ||
| - **Durability Gate** — Instincts with `durability_score < 0.7` are filtered out; event-specific patterns no longer pollute the system | ||
| - **Gaming Gate** — Score jumps >5pp with ≤3 net new lines are flagged as `gaming_suspected` and discarded | ||
| - **Multi-run eval** — `--runs N` and `--passes N` flags for multiple independent eval runs and majority vote per scenario, reducing LLM-judge variance | ||
| - **CLAUDE.md coverage check** — Already-implemented rules are injected into the extraction prompt to avoid re-extracting existing behaviors | ||
| - **Bash failure circuit breaker** — `observe.sh` tracks last 10 failures for evolution analysis | ||
| - **Simplified phase pipeline docs** — P0/P1A/B/C internal naming removed from public docs; cleaner mental model | ||
| ### v0.9.0 — Evolution Engine Upgrade (Mar 2026) | ||
@@ -171,0 +184,0 @@ |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
537223
1.17%1476
3.72%665
1.99%21
16.67%