# eeebot / tech-tree

integrations96
confirmed integration ratio52.9%
repeat failure rate · scorecard13.6%
old repeat failure rate · keep 7d13.6%
execution failures35 events · 27 tasks · 10.1%
model unavailable (known)0 events · 0 tasks · 0.0%
model call incompleteno data
failure cause unknownno data
self_dedup rejections7 events · 1 tasks · 2.0%
repeat failure rate · new21.7% · новая формула без self_dedup (#1765); не улучшение работы
tokens / integration2.1M
held-out4/4
supplier-paused0 cycle(s) / 0s
Window: 7d (complete)
data: 30s old · generated 22:56 UTC

What this is

eeebot is an autonomous improvement loop that runs bounded cycles on a constrained host (eeepc), editing its own instance repository under a gate. Every change the loop makes to its own capabilities goes through the same bounded gate described below; nothing here bypasses it.

The machine: four repositories

repositoryroleholdsidentifiers on this site
ozand/eeebotharness / productthe runtime code (nanobot/), specs, host deploy tooling, and the fitness function (scorecard, targets, held-out checkers)issue numbers (#NNNN); commit shas for the harness's own history
ozand/eeebot-self-evolvinginstancethe mutable workspace the loop edits (scripts/, surfaces/, tests/, memory/, docs/); checked out on the host beside the state rootcycle ids (cycle-<hex>) mark commits the bridge integrates onto this repo's main; commit shas here are cycle integrations
ozand/eeebot-ops-dashboarddashboard (this repo)the WSGI observability app (dormant, not deployed) and the standalone techtree_viewer.py static-site generator that produces the page you are readingissue numbers (#NNNN) for dashboard-only work; no cycle ids or shas of its own appear on the published site
ozand/eeebot-channel-appchannel appthe home page, privacy policy and terms for the eeebot channel publisher's OAuth clientnot surfaced on this dashboard

The cycle

stagewhat happenswhere the output appears
1. Demand selectiondemand.py scans state and yields items in trust order: priority > defect > goal-gap > hypothesis > decay.the demand kind and target for the current/most recent cycle appear in cycles; hypothesis-kind demand is detailed on hypotheses
2. Proposethe LLM proposer (llm_proposer.py) selects and refines one presented demand item -- it never invents from a bare inventory. No demand means zero LLM calls that cycle.what the proposer/executor is given (charter, derived priorities, skills) is on agent
3. Dedup chaina proposal passes exact-tag replay protection, recent-failure suppression, and an FTS5 existence-index check before any subagent spawns.not yet surfaced as its own section on this site
4. Bounded executorexactly one fresh-context subagent runs and commits on a cycle branch.subagent records and prompts for one cycle are on the per-cycle detail page (linked from cycles)
5. Gatethe bounded smoke gate: py_compile of changed files, the tests they affect, and a small fixed core set -- not the full suite. A mutation-surface violation is a hard block. The gate fails safe: any error, timeout, or missing pytest counts as failure.PASS / BLOCK / unknown badges per cycle are on cycles
6. Integrateonly on a green gate does the bridge merge the cycle onto the instance repo's main (script tier) or, for an operator-approved runtime-slice cycle, land it as a pending promotion candidate for a product PR instead of auto-integrating.merged commits and the direction/lever state after integration are on lineage and now
7. Scorecard + demand feeds the next cyclescorecard.py computes a deterministic, LLM-free 7-day snapshot; demand.py reads it to decide what the loop is offered next, closing the loop.the scorecard-derived KPI strip appears at the top of every page, including now; held-out pass rate is one of its rows

The schedule

unitcadenceproducesappears on
eeepc-self-evolving-subagent-bridgeevery 15 min (OnBootSec=4m, OnUnitActiveSec=15m)one bridge cycle: demand -> propose -> gate -> integratecycles.html, lineage.html
eeebot-reflectorevery 30 min (OnBootSec=25m, OnUnitActiveSec=30m)per-cycle reflections (findings, recommendations) -- the night contour's transcript readernot yet surfaced as its own page
eeebot-knowledge-curatordaily (OnCalendar=daily, i.e. 00:00)curates lessons into the bounded knowledge baselessons.html
eeebot-strategistdaily at 03:00 (OnCalendar=*-*-* 03:00:00)periodic archive reviewnot yet surfaced as its own page
eeepc-promotion-verifierevery 15 min (OnBootSec=5m, OnUnitActiveSec=15m)root-verified re-check of runtime-slice promotion candidatesnot yet surfaced as its own page
eeebot-validator-harnessevery 6 h (OnBootSec=20m, OnUnitActiveSec=6h)runs built validator scripts and records findingsnot yet surfaced as its own page
eeebot-skill-evalsdaily at 04:30 (OnCalendar=*-*-* 04:30:00)harness A/B skill evals, measured with/without deltanot yet surfaced as its own page
eeebot-local-cievery 4 h 15 min (OnCalendar=*-*-* 00/4:15:00)bounded local CI checknot yet surfaced as its own page
eeebot-action-indexdaily at 00:05 (OnCalendar=*-*-* 00:05:00)extracts the durable per-cycle action index before prompt rotationnot yet surfaced as its own page
eeebot-archive-subagent-requestshourly (OnBootSec=10m, OnUnitActiveSec=1h)archives stale subagent requests older than 24hnot yet surfaced as its own page
eeebot-host-metricsevery 6 h (OnBootSec=10min, OnUnitActiveSec=6h)refreshes the host metrics feednot yet surfaced as its own page
eeebot-host-capabilitiesdaily at 01:00 (OnCalendar=*-*-* 01:00:00, plus OnBootSec=10min)refreshes the host capability inventorynot yet surfaced as its own page
eeebot-dashboardalways-on (no timer)the OTHER dashboard -- scripts/eeebot_dashboard.py, port 8080, in ozand/eeebot -- not this repo's WSGI app (dormant) and not the static site this page is part ofn/a (not this site)

eeebot-techtree-publish.service (installed from this repo's systemd/ directory) runs periodically via eeebot-techtree-publish.timer (every 15 minutes, issue #1905) and on completed cycles, digest-gated so an unchanged snapshot does not re-publish.

Confirmed running on the live host but with no corresponding file in the harness repo's host/eeepc/systemd/ as of this page's writing:

The models

rolemodelwhy
executor (the bounded subagent that edits code; telemetry component name: bridge)self-hosted, owned 3090Ti GPU on the LAN (un/qwen3.8-27b-gguf)784/1004 recorded calls on the measured day; 24.30 completion tokens/request-wall-second
proposer, curator, reflector, strategist (the night contour + the proposer)vendor API (an/gemini-3.8-flash-high)nanobot/runtime/model_registry.py's _ROLE_DEFAULTS; the operator preset overrides these per-role in production

Both self-hosted and vendor traffic traverse the same LAN gateway (docs/model-routing-evidence-1362.md): a gateway failure can affect either class. The dashboard's own executor-model-status check (_build_executor_model_item in techtree_viewer.py) flags a fallback when a vendor-class model serves a call the executor/harness role expected to be self-hosted -- the detectable signal, since llm_calls persists only the model that actually served the call, not a separate 'requested' field.

eeepc: Intel Atom N270, i686/32-bit (docs/specs/demo_category_determination.md, #1619 live measurement). RAM is stated inconsistently across harness-repo sources: 1 GB per that same measurement, 2 GB per docs/adr/ADR-013-capability-tiers-probe-and-cost.md and docs/model-routing-evidence-1362.md's operator-verified topology -- not reconciled here. Core count and swap configuration: not documented in the harness repo.

The vocabulary

harness
ozand/eeebot: the product repo. Owns the runtime code, the fitness function, and the deploy tooling. Never edited by the loop itself. (docs/CURRENT_ARCHITECTURE.md)
instance
ozand/eeebot-self-evolving: the mutable workspace the loop edits. The bridge integrates green cycles onto this repo's main. (docs/CURRENT_ARCHITECTURE.md)
cycle
one timer-paced bridge process invocation -- demand selection through integrate-or-not. Identified by a cycle id (cycle-<hex>). (docs/CURRENT_ARCHITECTURE.md)
gate
the bounded smoke gate a cycle's changes must pass before integration: py_compile of changed files, the tests they affect, and a small fixed core set (not the full suite). Fails safe on any error, timeout, or missing pytest. (docs/CURRENT_ARCHITECTURE.md)
integration
the bridge merging a green, script-tier cycle onto the instance repo's main (--no-ff). origin/main never advances on a red gate. (docs/CURRENT_ARCHITECTURE.md)
night contour
the reflector -> curator -> strategist chain: components that see across many cycles, as opposed to the executor, which sees one. ADR-021's subject: the night contour may propose capability changes; it does not commit them directly. (docs/adr/ADR-021-whoever-sees-the-performance-may-change-the-capability.md)
direction
one node in the tech-tree portfolio (nanobot/runtime/tech_tree.py): an improvement domain the loop can invest cycles in, paired with a lever metric and which way that metric should move. (nanobot/runtime/tech_tree.py)
lever
the scorecard metric (section.metric) a tech-tree direction is measured against, e.g. loop.confirmed_integration_ratio. (nanobot/runtime/tech_tree.py)
vector
an operator-set, ordered purpose for the loop. Vector 1 (primary): self-improvement of the agent system. Vector 2 (secondary): operator interface and process transparency. (docs/ACTIVE_GOAL.md)
demand kind
the category of the next thing offered to the proposer, in trust order: priority > defect > goal-gap > hypothesis > decay. (docs/CURRENT_ARCHITECTURE.md)
held-out
sandboxed behavioral checkers run against instance artifacts on the scorecard recompute path; a failure becomes defect demand carrying the checker's evidence, without the instance ever seeing the checker itself. (docs/CURRENT_ARCHITECTURE.md)
scorecard feed
one of the named, freshness-monitored input paths nanobot/runtime/scorecard.py reads to compute its 7-day snapshot. (nanobot/runtime/scorecard.py)
provenance
the citable evidence trail behind a decision or claim -- which source file, ledger row, or scan produced it -- as opposed to an assertion with no traceable origin. (nanobot/runtime/goal_review.py)
present
probe state: the source exists and was read successfully, with real content. (scripts/techtree_viewer.py (read_local_ci_status))
absent
probe state: the source file or directory does not exist at all. (scripts/techtree_viewer.py (read_local_ci_status))
present_uninitialized
probe state: the source exists, but its own content says nothing has run yet (e.g. no rows, targets_missing) -- distinct from absent (nothing to find) and from a read failure. (scripts/techtree_viewer.py (read_local_ci_status))
probe_unavailable
probe state: the source exists but could not be read or parsed (a transient failure) -- distinct from absent (never existed) and present_uninitialized (readable, just empty of activity). (scripts/techtree_viewer.py (read_local_ci_status))