Root cause: decision records have type: decision, but the entity indexer
only accepted type: entity and only scanned entities/. The claim indexer
scanned decisions/ but filtered out non-claim types. Result: decision
records fell through both indexes entirely — invisible to the bot.
Fix: add decisions/ to entity indexer scan paths, accept type: decision
alongside type: entity, include summary/proposer in search aliases.
Remove decisions/ from claim indexer (was silently dropping them anyway).
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
1. handle_research gets silent=True param. RESEARCH: tag triggers use
silent mode — archives tweets but posts no follow-up message.
Prevents "Queued N tweets" after Opus already responded.
2. KB retrieval now searches decisions/ directory alongside domains/,
core/, foundations/. Decision records (Robin Hanson proposal, etc.)
are now findable by the bot.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Article endpoint returns body in "contents" array of typed blocks
(unstyled, header-two, markdown, list-item, blockquote, etc).
Was looking for article.text which is empty. Now parses all block types
into readable text. Also extracts engagement stats (likes, views).
Fixes: "Claude + Obsidian" article returned title but empty text.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Primary path: GET /twitter/tweets?tweet_ids={id} — works for any tweet,
any age, returns full content. Replaces the fragile from:username search
pagination fallback.
Fallback: article endpoint for X long-form articles.
Last resort: placeholder with [Could not fetch] message.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Major changes this session:
- fetch_tweet_by_url: extracts username+ID from X URLs, tries article endpoint,
falls back to from:username search. Tweets injected into Opus prompt.
- Haiku pre-pass: decides if X search needed before Opus responds. 2-3 word queries.
- systemd ProtectSystem paths fixed (ROOT CAUSE of all write failures since day 1)
- Research regex handles Telegram @botname suffix in groups
- Double research message prevented (skip RESEARCH: tag when Haiku already ran)
- Engagement filter dropped to 0 for niche crypto tweets
- Heuristic brevity in prompt (not hard cap)
- DM auto-respond gating (groups: reply-to only, DMs: auto-respond)
- All code now edited in pipeline-v2 repo, not /tmp
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
- Skip RESEARCH: tag when Haiku pre-pass already searched (no double-fire)
- Haiku told to use 2-3 word queries (was generating 6+ word queries that returned 0)
- Engagement filter dropped to 0 (niche crypto tweets have low engagement)
- systemd ProtectSystem paths fixed (root cause of ALL write failures)
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Before Opus responds, Haiku evaluates: "Does this message need an X search?"
If YES, searches X, injects results into Opus prompt, archives as source.
Opus responds with KB knowledge + fresh tweet data combined.
Flow: user asks naturally ("what are people saying about P2P?") → Haiku
decides search needed → X search → results in Opus context → unified response.
~1s latency, ~$0.001 cost per message. Only fires when Haiku says YES.
Explicit /research command still works as direct path.
Also: fixed systemd ProtectSystem paths (Ganymede: root cause of all
write failures). Fixed research regex for Telegram group commands.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Replaced hard rules with judgment heuristics:
- "Does every sentence add something the user doesn't already know?"
- "Earn every paragraph — each needs a distinct insight"
- "Short questions deserve short answers"
Restored max_tokens to 1024. Agent decides length, not a token cap.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
1. Response length: "BREVITY IS YOUR DEFAULT. Most responses 1-3 sentences.
A 4-paragraph response to a simple question is a failure."
max_tokens cut from 1024 to 512.
2. Research trigger: removed natural language regex (caused false positive
on "has accumulated" matching "search"). Only explicit /research command.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Option A: history only contains actual bot-user exchanges, not unaddressed
group messages. Empty bot responses in history confused the model.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Opus decides what to learn. Prompt instructs: append LEARNING: [category] [description]
at end of response when genuinely learning something new. Bot parses the line,
strips it from displayed response, calls _save_learning() to persist.
Zero additional API calls (Rhea's design). The model already has full context.
Categories: factual, communication, structured_data.
Most responses have no LEARNING line — only fires on genuine corrections.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
1. Conversation history now shows compressed context summary first
(tickers, key figures, exchange count) before full log.
"Discussing: $FUTARDIO | Key figures: $0.004, $39.5K | Exchanges: 3"
20 tokens, unmissable. Plus prompt instruction: "NEVER ask a question
your history already answers." (Ganymede: Option C+A)
2. Archive file writes decoupled from worktree lock. File written
unlocked (additive, no coordination needed). Git commit attempted
with lock — deferred on timeout, file persists on disk for next cycle.
Fixes "Read-only file system" archive failures. (Ganymede review)
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Auto-respond stripped from conversation window. Bot only responds to @tag
and reply-to-bot. Window now silently tracks messages for context — when
the user does reply, the bot has full conversation history.
Also: prompt shortened to "1-2 sentences" default. "Do NOT respond to
messages that aren't directed at you."
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
User says "@FutAIrdBot /research P2P.me launch" → bot searches X via twitterapi.io
→ archives all tweets as ONE consolidated source file in inbox/queue/ → batch extract
picks up → claims land in KB.
Features (Ganymede+Rhea+Leo+Rio consensus):
- Regex + natural language intent detection (not CommandHandler)
- One source file per research query (not per-tweet)
- Full tweet metadata: author, followers, engagement, date
- Contributor attribution: proposed_by + contribution_type: research-direction
- Rate limit: 3 searches per user per day
- Min engagement filter (3 interactions)
- Worktree lock on source file write
Phase 2 (not built): domain alignment check before searching.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Learnings file content now passes through sanitize_message() before injection
into the Opus prompt. Prevents prompt injection via crafted "corrections."
Rio UUID 5551F5AF confirmed as current Teleo v4 Rio.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Option D (Rhea+Rio+Leo consensus):
- _load_learnings(): reads agents/rio/learnings.md, injects into prompt before KB context
- _save_learning(): appends correction to learnings.md via worktree lock + direct commit
- Learnings prioritized over KB data when they conflict
- Three categories: communication, factual, structured_data
- Prompt updated: tells agent it can save corrections for future conversations
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
Pre-extraction step: find queue files already in archive, delete them,
commit + push. Runs on main worktree before extraction starts on extract
worktree. Prevents "queue duplicate reappears after reset --hard" problem
that produced 16 stale entries overnight.
Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>
- Claim-shape detector: if YAML has type: claim, force STANDARD minimum (Theseus)
- Random pre-merge promotion: 15% of LIGHT → STANDARD before eval (Rio)
- LIGHT_SKIP_LLM config flag: skip domain+Leo review for LIGHT (Rhea: env var rollback)
- Updated both_approve: domain_verdict=skipped is valid for LIGHT auto-approve
- Cost recording: only charge for reviews that actually ran
- SAMPLE_AUDIT_RATE bumped 0.10 → 0.15, audit model = Opus (Leo: different family from Haiku)
Multi-agent design review: Rio (gaming vectors, model diversity), Theseus (correlated
blindspots, claim-shape guard), Rhea (shadow mode, config flag, deployment), Leo (approval).
Pentagon-Agent: Ganymede <F99EBFA6-547B-4096-BEEA-1D59C3E4028A>
Forgejo returns 200 with HTML content-type on successful merge instead
of JSON. Our API helper threw on resp.json(), causing merge to report
failure even though the PR merged. Now treats non-JSON 200 as success.
This was causing PRs #732 and #789 to show as conflict in our DB while
actually merged on Forgejo, and tripping the merge circuit breaker.
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
Unevaluated PRs (eval_attempts=0) now sort before re-evals in the
eval cycle query. Fresh PRs have a higher chance of passing (~12%)
vs re-evals of already-rejected PRs. Prevents migration-reset PRs
from consuming eval slots that fresh PRs could use.
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
Opus was ignoring the valid tag list and generating custom tags like
schema-enrichment-slug-mismatch, which fall through to 'unknown' in
disposition logic. All three prompts (domain, Leo standard, Leo deep)
now explicitly say "do not invent new tags" alongside the valid tag list.
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
If source_path is NULL, the source requeue silently matches nothing.
Log a warning so we catch orphaned terminations in monitoring.
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
Schema migration v3: adds eval_attempts (INTEGER) and eval_issues (TEXT/JSON)
columns to prs table.
Retry budget logic (Ganymede-approved design):
- Increment eval_attempts on each evaluate_pr() call
- Hard cap: eval_attempts >= 3 → terminal (close PR, tag source needs_human)
- Attempt 1: normal — back to open, wait for fix
- Attempt 2: classify issues as mechanical/substantive
- Mechanical only (schema, wiki links, dedup): keep open for one more try
- Substantive (factual, confidence, scope, title): close PR, requeue source
- Issue tags parsed from reviewer comments, stored in eval_issues column
- SHA-based reset: new commits on PR branch → eval_attempts=0, verdicts reset
- Post-migration stagger: LIMIT 5 for first batch to avoid OpenRouter spike
- Cost recording updated: domain review → OpenRouter, Leo → tier-dependent
Stops the 32-PR infinite loop burning ~$0.03/cycle with no terminal state.
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
- Domain review → GPT-4o (OpenRouter), Leo STANDARD → Sonnet (OpenRouter),
Leo DEEP → Opus (Claude Max). Two model families = no correlated blind spots.
- Opus reserved for DEEP eval only — protects rate limit for overnight research.
- Review prompts calibrated: require per-criterion evidence, blocking-vs-observation
verdict rules. Moved from 100% rubber-stamp approval to 12% pass rate.
- OpenRouter failures classified as openrouter_failed (not rate_limited) to avoid
spurious 15-min Opus backoff.
- merge.py: pre-check PR state before merge API call (prevents 405 on re-merge).
Pentagon-Agent: Leo <294C3CA1-0205-4668-82FA-B984D54F48AD>
- Fix#12: domain_review undefined on resume path — initialize to None,
guard _parse_issues() call. Prevents NameError on PRs resuming after
partial eval (76 PRs in this state right now).
- Fix#11: concurrent eval workers can duplicate reviews — add atomic
UPDATE SET status='reviewing' WHERE status='open' at top of
evaluate_pr(). Check rowcount, skip if already claimed.
- Fix#8: subprocess tracking for graceful shutdown — _active_subprocesses
set in evaluate module, tracked in _claude_cli_call, exposed via
kill_active_subprocesses(). Replaces dead code in teleo-pipeline.py.
- Fix health.py divide-by-zero — guard all metabolic metric reads against
None from NULLIF/empty result set. Prevents TypeError on /health when
no PRs have been evaluated in 24h.
Also includes Leo's existing hot-fixes:
- Rate limit detection checks stdout regardless of exit code
- 15-minute cycle-level backoff on rate limit
Pentagon-Agent: Ganymede <F99EBFA6-547B-4096-BEEA-1D59C3E4028A>