BrainOS TODO
A living list of what's deliberately deferred and what's still open, as of
2026-09-01. Detailed incident history belongs in git log (this repo's
commit messages are written as full incident/design writeups on purpose),
not here. Keep it this way: when something here gets fixed, delete the line
instead of turning it into a paragraph.
Still to do
restructure_stalled's oversized-leaf recovery path has no per-module claim lock.advance()'s main path (_decompose_or_defer, and the depth-limitmaterialize_taskcall) now takes a Postgres advisory lock per module before two concurrent autonomy lanes can decompose or materialize it (seeSettings.autonomy_parallel_lanes, added 2026-09-01).restructure_stalled's own oversized-leaf-to-decompose call (_decompose_if_oversized) was deliberately left unprotected: it's a rarer batch-recovery path (only reached whennext_actionablefinds nothing), and a collision there just means one leaf gets decomposed twice - wasteful, not corrupting. Worth closing if it's ever observed live, not urgent enough to hold up the main fix.- Watch whether the new parallel autonomy lanes actually help.
AutonomousLoop.begin_tickandSupervisor.run_onceno longer serialize the whole autonomy loop to one lane (a strict "one AutonomyRun running anywhere" check and an unparameterized global Redis lock both did, despite the underlying task/module selection already being safe for concurrent access via row-level and advisory locking). Confirm live that two lanes actually run concurrently against independent work, that GPU utilization reflects it, and that no advisory-lock contention or DB pool exhaustion shows up under real load before raisingautonomy_parallel_lanespast 2. - Push the paper-focus anchor's remaining research past the planning
stage. The current publication-focus module (
brain model-role-list/ the problem tree will show the live one; as of this writing it compares three ML-fault-localization methods on real ONNX Runtime/PyTorch regressions) has zero implementation started — every child branch is still being broken down into smaller experiment-design tasks, and one sub-branch (designing the pre-registration protocol) has repeatedly stalled during that breakdown. The 45-minute decompose timeout and 3-strikes hosted escalation (see "Local generative models" in README) bound the cost of a stall now; they don't substitute for the literature and experiment-design work itself still being needed. - Observe whether wiring the remaining call sites onto the idle-model
pool changes throughput.
supervisor.py's generic task cycle,purpose.py's opportunity discovery and paper drafting,paper_pipeline.py's worthiness/drafting,workflows.py's memory consolidation, and the research API/CLI now balance across both residents instead of always using one assigned model. Watch whether idle GPU time actually drops and whether previously single-model-bound lanes (e.g. memory consolidation) start completing measurably faster. - Audit SearXNG's remaining default engines. Only
duckduckgo,brave,startpage, andwikidatawere disabled (2026-09-01, confirmed CAPTCHA/rate-limited from this host's shared proxy IP);google cseandwikipediawere confirmed working, but the rest ofuse_default_settings's ~50 engines are unvetted. Revisit if search result quality or latency becomes a recurring complaint. TriageService._prompt(triage.py) still passes a large pre-digested bundle (tree,branch_summary,workspaces,publication_feedbackas curated JSON, distinct from the policy/semantics text that should stay) to a hosted agent with real tool access, unlike the twice-daily review and active-mode coding prompts, which were rewritten to have the agent query the tree/workspaces/database itself. The fix is dropping the four data-dump arguments, not a wholesale rewrite.- Repeat-verify Codex OSS's hardened completion path. It runs prompt-free YOLO with an execution-first contract, rejects actionless/untested results, requires a tool-created completion marker, and gets one corrective pass under the same deadline. Repeatability across models/tasks is still not fully characterized.
- Finish and observe outcome-memory backfill. Automatic planning cycles continue the idempotent backfill from the first bounded batch. Monitor duplicate-reuse audit events, false-positive lexical matches, and whether cross-project repetition actually falls before increasing the comparison window.
- Add a small real-Postgres integration gate. The unit suite still cannot catch transaction-lifecycle and async ORM failures. Cover mutate/commit/reload/serialize, notification deduplication, and concurrent admission against throwaway PostgreSQL.
- Make degraded scheduled results operationally distinct from success.
A benchmark or research stage returning
status=degradedcan still sit inside a completed job run. Propagate degraded status into dashboard/alerts. - Verify backup restore, not just archive creation.
brainos-backup.timeris installed and has been producing a daily snapshot inbackups/runtime/(confirmed current as of this writing); what's still unverified is a full restore drill, not just archive existence. - Attest context consumption, not only availability. Every local generative role runs through Codex OSS with role-relevant durable state assembled into its prompt/workspace bundle. Bundle audits prove availability; add bounded evidence showing which supplied records actually influenced a result, without incentivizing indiscriminate context.
- Remove the stale Ollama systemd drop-in.
/etc/systemd/system/ollama.service.d/20-brainos-concurrency.confstill setsOLLAMA_MAX_LOADED_MODELS=2;brainos.conf(loaded after it alphabetically) sets=3and wins today, so behavior is correct, but the superseded file is confusing leftover config. Root-owned — prepare the removal for the owner to apply per CLAUDE.md rule 9. - Route or retire long-orphaned
proposedtasks with noCodingJobat all. A task inproposedstate with neither a queued coding job nor supervisor eligibility (proposedisn'tready) will never be picked up by anything. Worth a periodic sweep distinguishing genuinely stale/superseded ones from ones that just need re-routing, rather than a one-time list (the specific tasks named in past incidents have long since resolved one way or another).
Known open threads (not yet actionable; watch for recurrence)
- Any caller of
ollama.chat()/chat_raw()that doesn't passmodel=explicitly silently ridesSettings.chat_model's bare default instead of the role it's supposed to use. Found and fixed twice already; worth an audit for a third instance before it's found live again. - A self-generated project branch can narrate a real-world step it has no actual ability to perform (e.g. "conducted usability testing with diverse learners") and nothing distinguishes the resulting fabricated-but- self-consistent numbers from a genuine finding. Not a bug in any single component — a real gap: nothing currently recognizes "this task requires real human/external input BrainOS cannot obtain" and blocks it, reframes it as simulated, or routes it to the owner. Needs a decision, not just a fix.
- Approving a task moves it
AWAITING_APPROVAL → READY, which re-plans from scratch rather than resuming the specific approved action. Less urgent since class 2 no longer routes through approval at all — only class 3 (external) still does, and for that there's still no owner affordance for "I did this by hand, mark it done." Director.plan()has occasionally produced a plan exceedingsupervisor_max_actions(fails cleanly, retried/re-planned — not a crash or data loss) without being root-caused. Worth a closer look if it keeps recurring.- An "idle in transaction" Postgres session from the research pipeline once blocked schema changes and a live job's heartbeat as a side effect of a pending DDL lock queue. Cleared once; the underlying transaction-not-closed path in the research pipeline was never identified. Watch for recurrence.
MemoryConsolidationService.consolidate()'s LLM-driven semantic distillation should be double-checked periodically to confirm it's actually producing consolidated memories in production, not just eligible to.
Deferred by design (explicit decision, not yet started)
Sleep-phase model tuning (LoRA/QLoRA, "fast methods", smaller models)
Owner decision: pushed to the far future, deliberately not scoped as
near-term work. ImprovementCycleService._tuning_readiness() only ever
reports "automatic_training": False — training examples accumulate
(TrainingExample, tuning-export CLI command) but nothing ever launches a
training job, creates an adapter, merges one, or retires one. This host's
two Titan RTX GPUs (48GiB total) are already fully committed at inference
time to keeping two resident models warm; there is no VRAM headroom left to
also run a training job without evicting one of them, and training is far
more VRAM-hungry per parameter than inference even with LoRA/QLoRA. Revisit
only if a second, separate machine is ever dedicated to training. If picked
up, it still needs: a reviewed, reproducible LoRA/QLoRA recipe; a bounded,
cheap "does this look worth it" check before spending GPU time; and a full
adapter lifecycle (create, benchmark, promote/discard, retire).
Implemented but currently dormant
Domain-expert model routing
The planner judges a domain (e.g. "medicine", "law", "physics") per
decomposition candidate in the same structured-output call that already
judges requires_implementation, stored on Module.domain. Routing
(model_registry.resolve_domain_model, CodingCycleService._role_model)
tries a "role:domain"-keyed model_roles row first, falling back to the
plain generalist role whenever none exists or is installed. Wired into the
coding pipeline's implementer role only, not the generic Supervisor/Director
path or research synthesis. This is a routing mechanism only — it never
installs a model, and with no domain-expert models actually installed, every
domain-qualified lookup falls through to the generalist role today.
Open architecture questions (need a decision, not just code)
- Sleep mode is still mostly diagnostic, for everything except memory.
Memory actually gets reorganized (
MemoryConsolidationService); everything elseSleepServicereports (stalled projects, unresolved contradictions, unmeasurable goals) is read-only findings with no automatic action. Decide how much of the rest becomes automatic (reversible only, perPERMISSIONS.mdclass 1) vs. stays a recommendation for the twice-daily external review to act on — which now actually can act on it directly. - Problem-tree restructuring is no longer failure-count-only.
restructure_stalledstill reopens a branch mechanically once every child has technically failed, butTriageService(Codex, 4x/day) separately judges branch quality and mission-alignment directly and can grow or wind down the tree independent of technical failure. The vision's "new evidence invalidates the current plan" trigger still doesn't exist as its own thing, but is largely subsumed by that mission-alignment judgment now happening on every triage pass. - Scoring weights are fixed constants (
ProblemTreeService.score: impact 0.32, probability 0.23, knowledge 0.12, confidence 0.18, resources −0.08, effort −0.07). Reasonable starting weights, not tuned against outcomes. A natural sleep-mode candidate once enough modules complete or get abandoned: does the actual completion/abandonment rate correlate with the scores that were assigned? score()has no concept of evidence vs. support work beyond the narrowrequires_implementationtiebreak scoped to a publication-focus node's own children. Decide whether this should become a first-class, more general scoring dimension (e.g. a small bonus tied torequires_implementationany time a branch is under focus of any kind, not just publication) rather than a one-off tiebreak scoped to a single call site.