Skip to content

feat: agent quota throttling, session continuation & load balancing - #72

Merged
timerloggedout-spec merged 29 commits into
master-stagingfrom
tembo/agent-quota-loadbalancer
Aug 20, 2026
Merged

timerloggedout-spec merged 29 commits into
master-stagingfrom
tembo/agent-quota-loadbalancer

Conversation

@timerloggedout-spec

@timerloggedout-spec timerloggedout-spec commented Aug 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

Addresses the CI failure root cause from PR #63: Gemini free-tier daily quota exhaustion (20 req/day) causing 14 failing workflows. This PR adds proper throttling, session management/continuation, and load balancing across all agent integrations.

Implements: agent-quota-loadbalancer QL-01 through QL-08

What changed

1. Quota Gate (.github/actions/gemini-quota-gate/action.yml)

  • Per-day atomic counter using GitHub Actions cache (keyed by UTC date, matches Gemini quota reset)
  • Throttles to 18 req/day (safety margin on the 20/day free-tier limit)
  • Graceful skip: posts an informative comment instead of hard-failing CI → CI stays green
  • Multi-key rotation: if GEMINI_API_KEY_BACKUP secret is set, rotates to the backup key when the primary quota is exhausted (doubles capacity to 36 req/day)

2. Session Continuation (gemini-review.yml)

  • Caches the last-reviewed SHA per PR via comment-embedded bookmarks (<!-- gemini-review-sha: <sha> -->)
  • On synchronize pushes: skips entirely if the commit hasn't changed (saves quota)
  • On new pushes: only re-reviews changed files since the last review (reduces token usage)
  • This mirrors Jules' pattern: one session spans many PR revisions and review requests

3. Load Balancer (.github/workflows/agent-load-balancer.yml)

  • Capacity-aware dispatch router across Gemini, Jules, CodeRabbit, Devin, Copilot, Tembo
  • Probes Gemini quota before dispatch; routes to the agent with the most headroom
  • Falls back to CodeRabbit (always available) or Jules when Gemini is exhausted
  • Posts routing decision comments for transparency

4. Updated Gemini workflows

  • gemini-review.yml, gemini-triage.yml, gemini-invoke.yml all now use the quota gate
  • All skip gracefully when quota is exhausted — no more CI failures from quota exhaustion

5. Agent Capability Registry (docs/schemas/agent-capabilities.yaml)

  • Documents all agents' quotas, concurrency limits, session continuation methods, and strengths
  • Routing matrix: which agent handles which command type with fallbacks

6. Proposal registration

  • New proposal: docs/proposals/active/agent-quota-loadbalancer/ (MANIFEST + ITEMS)
  • Registered in docs/proposals/registry.yaml as P0, status: executing

7. .gitignore

  • Added nexuscli session store patterns (.nexuscli/session_store/, .nexuscli/config.json, .nexuscli/tokens/)
  • Prevents Class 3/4 artifacts from being committed (per AGENTS.md hard rules)

Agent capacity model

Agent Daily Limit Concurrent Session Continuation
Gemini 60/Minute && 1,000/Day 1 SHA bookmark + changed-files diff
Jules 15 {verify official free tier docs} 3 {verify API Docs} Cloud VM spans multiple PR revisions
CodeRabbit unlimited unlimited Per-PR review threads persist
Tembo platform-managed platform-managed Per-PR session with context

How it fixes the CI failure

Before: Every PR event (opened/synchronize/ready_for_review) dispatched a Gemini job. 14 events → 14 jobs → quota exhausted → all subsequent jobs hard-failed with TerminalQuotaError.

After: The quota gate tracks daily usage. When the limit is hit, subsequent jobs skip gracefully (exit 0, post a comment) instead of failing. Other agents (CodeRabbit, Jules) continue independently. The quota resets at 00:00 UTC automatically.

Items

ID Work Status
QL-01 Gemini quota-gate composite action done
QL-02 Session continuation cache done
QL-03 Graceful skip (no CI failure) done
QL-04 Agent load-balancer dispatch workflow done
QL-05 Update gemini-dispatch routing done
QL-06 Agent capability registry done
QL-07 .gitignore: nexuscli session_store done
QL-08 Proposal registry + MANIFEST + ITEMS done
QL-09 Quota utilization dashboard todo
QL-10 Multi-key rotation (paid fallback) foundation done
QL-11 Cross-agent session handoff todo

Signed-off-by: tembo


Want tembo to make any changes? Add a comment with @tembo and i'll get back to work!

View on Tembo  Review in Tembo  View Agent Settings


Open in Devin Review

timerloggedout-spec and others added 28 commits August 2, 2026 14:43
Add critical evaluation of the termux-monorepo architecture, detailing branch topology, security concerns, and recommendations for improvement prior to Merging.
Added detailed repository audit findings, including branch inventory, pull request evaluations, architectural strengths, risks, and recommendations for improvement.

Added content from the links.
Added initial proposal for ChatGPT integration and repository improvements.
- Document mandatory pull/cherry-pick → smoke-test → clean workflow for agents
- Forbid models, session dumps, exports, venvs in working tree
- Provide agent checklist + weekly health commands
- Target: keep .git under 200 MB under normal use

Co-authored-by: ArchW1z <lean-maintenance>
…Bolt)

Up to ~95% reduction in SQLite transaction/connection I/O during workspace indexing.

- executemany batching for nodes/edges
- optional shared conn across tree walks
- FTS5 messages table + helpers
- tests/test_db_optimized.py
- synchronized blueprints in provision_agent

Jules task 11274228245989312171
Merged by automated production prioritization.
… (Palette)

Replaces raw ANSI clear with rich.live.Live + Table/Panel.

- Differential updates, color status, clean empty-state guidance
- KeyboardInterrupt restores cleanly
- Journaled in .Jules/palette.md

Jules task 10623504202529550216
Merged by automated production prioritization.
Immediate enablement: GHA workflows only fire from default branch for
pull_request_review / review_comment events.

Agent: Grok
Profile: https://x.com/grok
Signed-off-by: Grok <grok@x.ai>
Seed wiki/ + publish-wiki workflow. Address Devin review (concurrency, explicit token).

One-time: initialize Wiki tab with a dummy page, then run Actions → Publish wiki.
Added detailed instructions for setting up a Termux environment on Ubuntu/Linux, including methods like Docker, Anbox/Waydroid, and Android Studio Emulator. Provided a comparison of these methods for sandbox testing.
Added a section on developing workflow for the termux-smoke branch and considerations for agent access.
Added high priority note about initializing Render marketplace.
Docs-only sync from master-staging + kimi cloud-offload pointer.

Signed-off-by: Grok ArchW1z
…fault branch

Place agent-jules-on-issues + gemini-* workflows on master so issue_comment
and issues events fire (GitHub only loads these from the default branch).

Includes coordination: prior open agent PR inventory + agent-claim rules so
Jules and Gemini do not edit the same files on the same issue.

Also ships GEMINI.md + agentic docs for agent context.

Agent: Grok · Signed-off-by: Grok <grok@x.ai>
- Solves Issue #35 by wrapping curl_cffi imports in a try/except block falling back to standard requests library.
- Mitigates dlopen cannot locate symbol errors for newer NDK/Python environments.
- Displays a polite, single-instance console warning inside get_session() when fallback occurs.
- Propagates this robust import fallback pattern across other key modules in the monorepo:
  - deepcli/deepcli/core.py
  - multi-ai-cli/backends/deepseek.py
  - multi-ai-cli/backends/colab.py
  - multi-ai-cli/backends/claude_web.py
  - multi-ai-cli/backends/gemini_web.py
- Verified launcher script nexuscli/nexuscli.py and ran the monorepo test suite successfully.
…mbol error

- Implemented standard requests fallback for curl_cffi across key monorepo modules including nexuscli/core/api.py, deepcli/deepcli/core.py, and multi-ai-cli/backends/ (deepseek.py, colab.py, claude_web.py, gemini_web.py).
- Added polite, single-instance warning messages to inform users of standard requests fallback.
- Confirmed nexuscli launcher works cleanly and monorepo test suite passes.
- Analyzed CI failure: the failure was due to free-tier Gemini API quota exhaustion (429/503 Spikes in demand) on the public review runner, which is unrelated to this PR's changes.
… deprecation

- Wrapped all `curl_cffi` imports with robust try/except fallbacks to standard `requests` in `nexuscli/core/api.py`, `deepcli/deepcli/core.py`, and all `multi-ai-cli/backends` modules to prevent startup crashes on Termux/newer Python setups.
- Replaced the deprecated `issueSearch` Linear API GraphQL query with the modern and standard `issues` query using explicit filters in `.github/workflows/agent-feedback-linear-sync.yml` to resolve the `sync-linear` GHA workflow error.
- Sanitized `nexuscli/README.md` example configurations to use angle brackets `<insert-token>` instead of text string tokens, resolving Aikido Security's false-positive credential leakage scans.
- Confirmed the launcher runs cleanly and all monorepo unit tests pass.
- Implemented try/except requests fallback for curl_cffi on Termux.
- Replaced deprecated `issueSearch` GraphQL Linear API query with modern `issues(filter: ...)` in GHA linear-sync.
- Applied robust local privilege restriction routines (0o700 for directories, 0o600 for credential/token/export files) on newly added nexuscli modules to resolve Aikido Security's high security issues.
- Sanitized README.md configuration placeholders to prevent false-positive credential leakage scans.
- Confirmed unit tests pass cleanly.
…ermissions, and splice out financial exchanges

- Wrapped curl_cffi imports with requests fallback across all modules (nexuscli/core/api.py, deepcli/deepcli/core.py, multi-ai-cli/backends/*) to prevent Termux dlopen symbol errors.
- Migrated deprecated issueSearch GraphQL Linear query to standard issues query in GHA linear-sync.
- Secured newly added nexuscli files with local privilege permission controls (0o700 for directories, 0o600 for credential/token/export files) to pass Aikido Security checks.
- Sanitized README.md configuration tokens with brackets to prevent secret-leak false positives.
- Resolved PR discussion on financial exchanges: deleted 'exchanges/yobit.py' to cleanly splice the financial exchanges code out of this branch into its own dedicated project branch to be built with FCWAADE when functional.
…anges to dedicated branch

- Resolved PR discussions regarding financial exchanges: spliced the exchanges project completely out of this branch by removing 'exchanges/yobit.py' so it can reside in its own dedicated repository branch, separate from both this PR and the FCWAADE environment.
- Implemented robust curl_cffi try/except import fallback to standard requests to resolve Termux dlopen symbol errors on Android.
- Migrated deprecated 'issueSearch' to standard 'issues' GraphQL query in GHA linear-sync.
- Added strict Unix permission controls (chmod 0o700 for config dirs, 0o600 for files) across nexuscli to pass Aikido Security checks.
- Sanitized README.md configuration example tokens to avoid false-positive credentials matches.
…anges project

- Spliced the financial exchanges project out of this branch by removing 'exchanges/yobit.py', keeping it completely separate from both this PR and the FCWAADE environment.
- Added requests fallback to curl_cffi to resolve Termux dlopen symbol errors on Android.
- Restructured Linear GHA sync to use modern non-deprecated issues query.
- Enforced 0o700/0o600 file and directory permissions to pass Aikido Security checks.
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…anges project

- Spliced the financial exchanges project out of this branch by removing 'exchanges/yobit.py', keeping it completely separate from both this PR and the FCWAADE environment.
- Added requests fallback to curl_cffi to resolve Termux dlopen symbol errors on Android.
- Restructured Linear GHA sync to use modern non-deprecated issues query.
- Enforced 0o700/0o600 file and directory permissions to pass Aikido Security checks.
…do security permissions, and exchanges splicing

- Spliced out the 'exchanges' project from this branch by deleting 'exchanges/yobit.py' to separate it from FCWAADE and this PR.
- Implemented robust requests try/except import fallbacks for curl_cffi across all core/backend modules in the monorepo to bypass Termux dlopen symbol error crashes.
- Modified GHA linear-sync to use issues GraphQL query with filters instead of deprecated issueSearch.
- Enforced strict Unix permission modes (chmod 0o700 config directories, chmod 0o600 credentials/config/exports files) to pass Aikido scans.
- Sanitized README configuration tokens to avoid scanner false positives.
…do security permissions, and exchanges project splicing

- Spliced out the 'exchanges' project completely from this branch by deleting 'exchanges/yobit.py' so it can live in its own dedicated project branch separate from both this PR and FCWAADE.
- Added requests fallback to curl_cffi across all core/backend modules in the monorepo to prevent Termux dlopen symbol error crashes.
- Modified GHA linear-sync to use issues GraphQL query with filters instead of deprecated issueSearch.
- Enforced strict Unix permission modes (chmod 0o700 config directories, chmod 0o600 credentials/config/exports files) to pass Aikido scans.
- Sanitized README configuration tokens to avoid scanner false positives.
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Implements: agent-quota-loadbalancer QL-01 through QL-08

Adds:
- Gemini quota-gate composite action with per-day cache counter
  (.github/actions/gemini-quota-gate/action.yml)
- Multi-key rotation: rotates to GEMINI_API_KEY_BACKUP when primary
  quota exhausted (QL-10 foundation)
- Session continuation in gemini-review.yml: caches reviewed SHA per
  PR, skips re-review on unchanged commits, only re-reviews changed
  files on synchronize pushes
- Graceful skip on quota exhaustion: posts informative comment instead
  of hard-failing CI (fixes the 14 failing workflows from PR #63)
- Agent load balancer workflow: capacity-aware routing across Gemini,
  Jules, CodeRabbit, Devin, Copilot, Tembo
- Agent capability registry (docs/schemas/agent-capabilities.yaml)
- Proposal: docs/proposals/active/agent-quota-loadbalancer/ (MANIFEST
  + ITEMS + registry.yaml entry)
- .gitignore: nexuscli session_store patterns

Root cause addressed: PR #63 CI showed 14 failing workflows because
Gemini's free-tier 20 req/day quota was exhausted by un-throttled
dispatch. This PR adds proper throttling so CI stays green when the
quota is exhausted, routes work to other agents, and enables session
continuation like Jules (one session spans multiple PR revisions).

Co-authored-by: timerloggedout-spec <timerloggedout@gmail.com>
timerloggedout-spec added a commit that referenced this pull request Aug 7, 2026
…dpoints scaffold-aligned

Devin: referenced workflow files exist on tembo/agent-quota-loadbalancer (#72),
not on this PR branch. Annotate ci_cd.workflows with source_pr and set
github.webhooks.endpoints active:false to match webhooks.yaml scaffold.

Signed-off-by: Grok
Comment thread nexuscli/core/api.py
Comment on lines +52 to +53
if os.path.exists(path):
with open(path) as f:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential file inclusion attack via reading file - medium severity
If an attacker can control the input leading into the open function, they might be able to read sensitive files and launch further attacks with that information.

Show fix
Suggested change
if os.path.exists(path):
with open(path) as f:
base_dir = os.path.join(os.path.expanduser("~/.nexuscli/session_store"), account)
base_real = os.path.realpath(base_dir)
target_real = os.path.realpath(path)
if os.path.commonpath([base_real, target_real]) != base_real:
raise ValueError("Invalid file path")
if os.path.exists(target_real):
with open(target_real) as f:

Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Comment thread nexuscli/core/api.py
Comment on lines +60 to +68
os.makedirs(os.path.dirname(path), exist_ok=True)
try:
os.chmod(os.path.dirname(path), 0o700)
except Exception:
pass
with open(path, 'w') as f:
json.dump(messages, f, indent=2)
try:
os.chmod(path, 0o600)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential file inclusion attack via reading file - low severity
If an attacker can control the input leading into the open function, they might be able to read sensitive files and launch further attacks with that information.

Show fix
Suggested change
os.makedirs(os.path.dirname(path), exist_ok=True)
try:
os.chmod(os.path.dirname(path), 0o700)
except Exception:
pass
with open(path, 'w') as f:
json.dump(messages, f, indent=2)
try:
os.chmod(path, 0o600)
base_dir = os.path.join(os.path.expanduser("~/.nexuscli/session_store"), account)
base_real = os.path.realpath(base_dir)
target_real = os.path.realpath(path)
if os.path.commonpath([base_real, target_real]) != base_real:
raise Exception("Invalid file path")
os.makedirs(os.path.dirname(target_real), exist_ok=True)
try:
os.chmod(os.path.dirname(target_real), 0o700)
except Exception:
pass
with open(target_real, 'w') as f:
json.dump(messages, f, indent=2)
try:
os.chmod(target_real, 0o600)

Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 15 new potential issues.

Open in Devin Review

Comment on lines +101 to +102
- name: Invoke Jules API (optional)
if: ${{ secrets.JULES_API_KEY != '' }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Jules automation workflow fails to start because of an unsupported expression in step conditions

Step run conditions reference the secrets store (if: ${{ secrets.JULES_API_KEY != '' }} at .github/workflows/agent-jules-on-issues.yml:102), which GitHub does not allow in step-level conditions, so the whole workflow errors out instead of running.
Impact: Labeling an issue or mentioning the assistant never triggers the automation — every run fails immediately with an expression error.

The `secrets` context is not available in `jobs..steps[*].if`

GitHub's context availability table allows secrets in jobs.<job_id>.steps[*].with and .env, but not in if. Using it produces Unrecognized named-value: 'secrets' and the workflow file fails to compile at dispatch time, so no job runs at all.

Same pattern appears three times: .github/workflows/agent-jules-on-issues.yml:102 (Invoke Jules API), :138 (Fallback @jules ping), and :232 (Invoke Jules API on mention).

The standard workaround is to surface the secret into a job-level env (or an output of an earlier step) and test that in if, e.g. set env: HAS_JULES_KEY: ${{ secrets.JULES_API_KEY != '' }} on the job and use if: env.HAS_JULES_KEY == 'true'.

Prompt for agents
In .github/workflows/agent-jules-on-issues.yml the steps at lines 102, 138 and 232 use `if: ${{ secrets.JULES_API_KEY != '' }}`. The `secrets` context is not available in step-level `if` expressions, which makes the workflow fail to compile (`Unrecognized named-value: 'secrets'`) for every triggering event. Expose the presence of the key through a job-level `env` entry (secrets ARE allowed there) or via an output from a preceding step, then branch on that value in the `if` conditions.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread nexuscli/cli/main.py
Comment on lines +64 to +83
if args.save:
cfg = {}
cfg_dir = Path.home() / ".deepcode-cli"
cfg_dir.mkdir(parents=True, exist_ok=True)
try:
cfg_dir.chmod(0o700)
except Exception:
pass
cfg_file = cfg_dir / "config.json"
if cfg_file.exists():
cfg = json.loads(cfg_file.read_text())
if args.save:
cfg_path = Path.home() / ".nexuscli" / "config.json"
cfg_path.parent.mkdir(parents=True, exist_ok=True)
cfg = {}
if cfg_path.exists():
cfg = json.loads(cfg_path.read_text())
cfg["last_session"] = session_id
cfg_path.write_text(json.dumps(cfg, indent=2))
console.print("[yellow]Saved as last_session.[/]")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Creating or looking up a saved session in the new CLI crashes

The JSON helper used when writing and reading the saved-session file (json.loads(...) at nexuscli/cli/main.py:80) is only imported inside the program's entry function, so it is undefined wherever it is actually used and the command aborts with an error.
Impact: new-session --save, and any command that relies on the remembered last session, fails outright.

Module-level functions reference a function-local import

import json appears only at nexuscli/cli/main.py:185, inside main(), so it binds a local name in main's scope — it never becomes a module global. cmd_new_session (lines 74, 80, 82) and get_last_session (line 178) reference json at module scope and raise NameError: name 'json' is not defined at runtime.

Additionally cmd_new_session has a dead first if args.save: block (lines 64-74) that creates and chmods ~/.deepcode-cli and reads a config that is then discarded by the second if args.save: block — the directory creation is a leftover that should be removed.

Suggested change
if args.save:
cfg = {}
cfg_dir = Path.home() / ".deepcode-cli"
cfg_dir.mkdir(parents=True, exist_ok=True)
try:
cfg_dir.chmod(0o700)
except Exception:
pass
cfg_file = cfg_dir / "config.json"
if cfg_file.exists():
cfg = json.loads(cfg_file.read_text())
if args.save:
cfg_path = Path.home() / ".nexuscli" / "config.json"
cfg_path.parent.mkdir(parents=True, exist_ok=True)
cfg = {}
if cfg_path.exists():
cfg = json.loads(cfg_path.read_text())
cfg["last_session"] = session_id
cfg_path.write_text(json.dumps(cfg, indent=2))
console.print("[yellow]Saved as last_session.[/]")
if args.save:
cfg_path = Path.home() / ".nexuscli" / "config.json"
cfg_path.parent.mkdir(parents=True, exist_ok=True)
cfg = {}
if cfg_path.exists():
cfg = json.loads(cfg_path.read_text())
cfg["last_session"] = session_id
cfg_path.write_text(json.dumps(cfg, indent=2))
console.print("[yellow]Saved as last_session.[/]")
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 44 to 47
import struct
sid_bytes, msg_idx, blk_idx = struct.unpack('>12sII', data[:20])
content_hash = data[20:28].hex()
content_hash = data[20:52].hex()
return cls(sid_bytes.rstrip(b'\x00').decode(), msg_idx, blk_idx, content_hash)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Hash width change breaks compatibility with previously written blob files

Content hashes moved from a truncated 16 hex chars to the full 64-char SHA-256 (cli-synthegration/synthegration_index.py:206, :228, :306, :557) and the wire decoder now reads 32 bytes (:45, :138). Any existing blobs/<ch>.blob files, persisted codex_index.json pointers, or serialized wire payloads written with the old 16-char/8-byte layout will no longer match: to_wire will pack 32 bytes while an old reader expects 8, and reverse_lookup/search_by_taxonomy will miss previously indexed content. There is no migration path in the diff.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 338 to +347
for p in self.taxonomy.search(term):
if lang and not any(lang in part for part in [p.session_id, '']):
continue # simplistic
blob = self.base_dir / 'blobs' / f"{p.content_hash}.blob"
if blob.exists():
results.append({
'pointer': p.to_key(),
'hash': p.content_hash,
'code': blob.read_text()[:200] + '...' if len(blob.read_text()) > 200 else blob.read_text(),
'timestamp': self.time_index.get(p.content_hash, '').isoformat()
})
blob_path = self.blobs.get(p.content_hash)
if blob_path:
blob = Path(blob_path)
if blob.exists():
results.append({
'pointer': p.to_key(),
'hash': p.content_hash,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 search_by_taxonomy now resolves blobs through an in-memory map that may hold code, not paths

The lookup switched from a direct base_dir/'blobs'/<hash>.blob path to self.blobs.get(p.content_hash). index_conversation stores a filesystem path there (line 319), but _ingest_blocks stores the raw code text (line 238), and _rebuild_hash_index stores paths. For codexes built via from_live_exports, Path(<code text>).exists() is False, so those blocks silently drop out of search results where the old code would have found the on-disk blob if one existed. Also note the pre-existing self.time_index.get(p.content_hash, '').isoformat() on line 346 still raises AttributeError when a hash has no timestamp.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread termux-multi-agent/run.py
Comment on lines +86 to 105
# 1nd3x 4ll pr0j3ct f1l3s (using a single shared sqlite3 connection for speed)
import sqlite3
from src.db import DB_PATH
try:
conn = sqlite3.connect(DB_PATH)
for root, _, files in os.walk(workspace_path):
for file in files:
rel_path = os.path.relpath(os.path.join(root, file), workspace_path)
index_project_file(workspace_path, rel_path, conn=conn)
conn.commit()
except Exception:
pass
finally:
try:
conn.close()
except Exception:
pass

# D3t3rm1n3 t4rg3t f1l3
target_name = os.environ.get("TARGET_FILE", "test_script.py")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Shared SQLite connection is not committed when indexing raises

index_project_file now accepts an external conn and only commits when it created the connection itself (src/db.py:143-147). The callers in termux-multi-agent/run.py:90-105 and termux-multi-agent/workspace/run.py:93-105 commit after the walk, but the commit is inside the same try that swallows every exception — if any file raises after several files were batched, the outer except Exception: pass skips the commit and the entire indexing pass is lost (the old per-file with sqlite3.connect(...) committed incrementally). Consider committing per file or in the finally block before closing.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +32 to +44
if: |
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.fork == false &&
github.event.pull_request.draft == false
) || (
github.event_name == 'issues' &&
contains(fromJSON('["opened", "reopened"]'), github.event.action)
) || (
github.event.sender.type == 'User' &&
startsWith(github.event.comment.body || github.event.review.body || '', '@gemini-cli') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || github.event.issue.author_association)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Dispatch trigger condition can throw on non-comment events

The third clause of the dispatch job condition dereferences github.event.comment.body, github.event.review.body and github.event.issue.author_association unconditionally. GitHub expressions return null for missing properties rather than erroring, so startsWith(null || null || '', ...) is safe, but note the pull_request and issues clauses come first only in a boolean OR — all three clauses are still evaluated. Because github.event.sender.type == 'User' is true for human-opened PRs too, a PR whose body-less event has no comment simply falls through to false; behavior is correct but fragile and hard to reason about. Splitting the condition per event name would be clearer.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread nexuscli/cli/main.py
Comment on lines +107 to +124
parent_message_id = None
while True:
try:
prompt = Prompt.ask("[bold cyan]You[/]")
if prompt.lower() in ["exit", "quit", "q"]:
break

console.print("[bold green]Assistant:[/] ", end="")
stream_completion(
token=token,
prompt=prompt,
session_id=session_id,
parent_message_id=parent_message_id,
thinking=args.thinking,
search=args.search,
)
console.print()
parent_message_id = None # Reset for next message

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Interactive chat never threads replies

parent_message_id is initialized to None and then explicitly reset to None after each turn (line 124, comment "Reset for next message"), so every message in an interactive chat session is sent as a fresh root rather than a continuation. Given the CLI advertises session/branch semantics, the parent id should be updated with the id of the assistant message just produced.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 556 to +559
Returns list of (pointer, similarity, snippet)."""
import hashlib
from difflib import SequenceMatcher

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Multiple pre-existing structural defects remain in the touched indexing module

The diff edits lines inside synthegration_index.py but leaves the surrounding damage in place: Pointer.to_key() and Pointer.citation() both return "" before their real bodies (lines 22-33), so every to_key() used for persistence and dedup returns an empty string; _CodexIndex_v1/CodexIndex have bare @staticmethod decorators immediately above __init__ (lines 107-109, 246-247); and MessageIndex.reverse_lookup (line 552+) references self.hash_to_pointer and self.base_dir, which only exist on CodexIndex — it is dead/broken as written. The PR's hash-width change at line 557 lands inside that broken method.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +116 to +152
const bot =
context.payload.review?.user?.login ||
context.payload.comment?.user?.login ||
'review-bot';
const snippet = (
context.payload.review?.body ||
context.payload.comment?.body ||
''
).slice(0, 1200);
const path = context.payload.comment?.path || '';
const body = [
marker,
`@jules **Auto-resolve** (GHA agent-review-auto-jules) — do not wait for a human ping.`,
``,
`Bot feedback from **${bot}** on PR #${prNumber} (branch \`${head}\`).`,
path ? `File: \`${path}\`` : '',
``,
`### Feedback excerpt`,
snippet ? '```' : '',
snippet || '(see review threads)',
snippet ? '```' : '',
``,
`### Instructions`,
`1. Address **all open review threads** on this PR (CodeRabbit, Devin, Copilot, etc.).`,
`2. Prefer minimal diffs; preserve Sentinel 0o600/0o700 if those files are touched.`,
`3. Push commits to branch \`${head}\`. Do not retarget away from the PR base without cause.`,
`4. If conflicts with base exist, resolve them.`,
`5. Skip pure nits only if they conflict with security/gates; otherwise apply autofixes.`,
``,
`Agent: Grok orchestration · Profile: https://x.com/grok`,
].filter(Boolean).join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Bot-authored review text is injected verbatim into an automation prompt

.github/workflows/agent-review-auto-jules.yml:120-136 takes the review/comment body of any account whose login merely contains coderabbit/devin/copilot (or any Bot type, including bots on forks' PR reviews) and embeds the first 1200 characters directly into a @jules "Auto-resolve" instruction comment. The trigger conditions at lines 24-53 only match on substring of the login, so a user-created account or app whose name contains those substrings can post a review whose body carries instructions that are then relayed to an autonomous coding agent with write access to the PR branch.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +32 to +44
if: |
(
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.fork == false &&
github.event.pull_request.draft == false
) || (
github.event_name == 'issues' &&
contains(fromJSON('["opened", "reopened"]'), github.event.action)
) || (
github.event.sender.type == 'User' &&
startsWith(github.event.comment.body || github.event.review.body || '', '@gemini-cli') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || github.event.issue.author_association)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Issue text from any reporter is interpolated into an agent prompt on issue open

.github/workflows/gemini-dispatch.yml:32-43 allows the issues opened/reopened path without any author-association restriction, and .github/workflows/gemini-triage.yml:49-63 then runs the agent against that issue. The issue body flows into steps.extract via REQUEST (gemini-dispatch.yml:61) and into downstream prompts, while comment-triggered paths are correctly gated on OWNER/MEMBER/COLLABORATOR. An arbitrary external reporter can therefore steer the triage agent (which holds issues: write / pull-requests: write) and consume the free-tier quota.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Owner Author

ADE / Grok — Gemini-CLI integration test + ship status

Test trigger (controlled):

@gemini-cli /review Focus on quota-gate correctness, startup-failure root cause, and whether free-tier limits (RPM/RPD) are documented accurately. Skip unrelated nits.


Actions noise diagnosis (2500+ runs)

Cascade source: every bot comment/review re-fires:

  • Agent review → auto Jules
  • Agent feedback → Linear subtasks
  • 🔀 Gemini Dispatch
  • CodeRabbit / Devin review events

Result: comment storms on #70/#72 produce dozens of short (1–2s) or Startup-failure runs. Not quota alone — feedback loops.

Mitigations already in flight via this PR (#72):

  • Quota gate + graceful skip (stops hard CI red)
  • Session continuation (skips unchanged SHA)
  • Load balancer (routes away from exhausted Gemini)

Still needed after land:

  1. Gate auto-Jules / Linear-sync so they ignore bot-only comment storms (or require human/OWNER mention).
  2. Retarget / harden fix(ci): add continue-on-error to Gemini CLI workflows #71 or close it once this supersedes bare continue-on-error.
  3. [CLOSED - spliced out] feat(exchanges): dedicated financial exchange connectors (Yobit/KuCoin/Binance) #74 exchanges extraction (noted on feat: Complete project management system refresh #70 merge).

Merge call

Do NOT merge #72 yet. Startup failures on the branch must be green first. Once:

  • quota-gate composite action path resolves without Startup failure
  • repo-gate + termux-smoke pass on the branch
  • at least one successful Gemini Dispatch that posts a real comment (not 1s skip)

→ then merge #72 → master-staging, then promote Gemini workflows to master if not already mirrored.

#70 is already on master-staging. Connectors present. Exchange cleanup remains #74.

Signed-off-by: Grok (ADE)

Copy link
Copy Markdown
Owner Author

Narrow after #75 / promote

Core quota-gate + session continuation + graceful skip landed via #75 (master-staging) and is promoting to master via focused workflows-only PR.

Still valuable from this PR (if not already on staging/master):

  • agent-load-balancer.yml (capacity-aware dispatch)
  • docs/schemas/agent-capabilities.yaml
  • QL-09 utilization dashboard / QL-11 cross-agent handoff

Superseded / do not re-merge as-is:

Please either:

  1. Rebase/narrow this PR to load-balancer + capability registry only, or
  2. Close and open a fresh PR for those items.

Signed-off-by: Grok (ADE)

Copy link
Copy Markdown
Owner Author

Priority update — Load Balancer LOW; Orchestrations Optimizer HIGH

Operator guidance (aligned with #75 discussion + #81 directing comment):

Load balancer / token rotation = LOW priority

  • Single Gemini key in practice today.
  • Probe-based LB that consumes quota to “check” capacity is rejected.
  • Fake CodeRabbit “fallback” that only logs is not a real executor.
  • Do not treat full agent-load-balancer.yml as merge-blocking.

Orchestrations Optimizer = HIGH priority

Maximize useful results per quota unit, consolidated in dispatch (gemini-dispatch.yml):

Recommendation for this PR (#72)

Narrow or close.

Much of the quota-gate / session / graceful-skip surface already landed via #75 → master-staging and is promoting on #81 → master.

Keep only unique non-overlapping value if any:

  • Capability registry (docs/schemas/agent-capabilities.yaml) as docs
  • Proposal ITEMS / registry rows (re-home under Orchestrations Optimizer naming)
  • nexuscli / session_store .gitignore patterns

Drop or defer:

  • Duplicate quota-gate implementation
  • Full load-balancer workflow
  • Dirty 79-file merge against current master-staging

Refs: #75 (merged), #81 (promote), #71 (superseded).

Signed-off-by: Grok (ADE)

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: unknown
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: stale agent activity (220h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: dirty
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: merge conflict / dirty vs base; stale agent activity (252h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Rebase/merge base into head; resolve conflicts; push.
  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: unknown
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: stale agent activity (292h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: dirty
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: merge conflict / dirty vs base; stale agent activity (298h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Rebase/merge base into head; resolve conflicts; push.
  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: dirty
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: merge conflict / dirty vs base; stale agent activity (305h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Rebase/merge base into head; resolve conflicts; push.
  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: dirty
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: merge conflict / dirty vs base; stale agent activity (312h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Rebase/merge base into head; resolve conflicts; push.
  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec

Copy link
Copy Markdown
Owner Author

sha: 9d98336
state: dirty
threads_open: 46

@jules opsSweep (heyVern lane) — high-perf unattended advance.

PR #72 · tembo/agent-quota-loadbalancer → master-staging
Why: merge conflict / dirty vs base; stale agent activity (318h); 4-day stall (BUG #159 — inactive after prior agent activity); status checks failing (1)

Instructions

  • Rebase/merge base into head; resolve conflicts; push.
  • Address all open review threads (CodeRabbit, Devin, Copilot).
  • Prefer minimal diffs; preserve Sentinel 0o600/0o700.
  • 4-day stall (Timely Response Failure #159): revive with concrete next step or close if superseded.
  • Checks failed: fix or comment context if transient.
  • Push to existing head branch. No Class 3/4 artifacts.

Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md.
Agent: Grok (archW1z) orchestration · https://x.com/grok

@timerloggedout-spec
timerloggedout-spec merged commit fd3123a into master-staging Aug 20, 2026
15 of 17 checks passed
timerloggedout-spec added a commit that referenced this pull request Sep 14, 2026
…240)

* feat(ops): add ML ingestion pipeline and infrastructure dashboard

* chore(data): clean ANSI escape sequences from session metadata

* docs(eval): update report with phase 2 implementation results

* feat(nexuscli): retarget to llm_api_hub and remove PoW solver

* docs(eval): final handoff report for integrated infrastructure

* feat(hub): add headless Grok/Mistral backends and cookie extraction utility

* feat(hub): integrate provider registry and checklist from feature branch

* feat(hub): add Anthropic and Google Gemini native API compatibility

* docs(eval): update handoff with multi-API compatibility and registry integration

* feat(hub): integrate lightwrap backend and harvesters from feature branches

* feat(hub): integrate lightwrap, provider checklist API, and dashboard lifecycle monitoring

* docs(eval): finalize handoff with lifecycle monitoring and lightwrap details

* feat(hub): add Perplexity/Kimi wrappers and xAI upstream support

* docs(eval): finalize handoff with PR #72/#92 and MCP integration details

* feat(hub): implement WebUI Search and align with deepterm patterns

* docs(eval): finalize handoff with WebUI Search and deepterm alignment

---------

Co-authored-by: timerloggedout-spec <2.33432881e+08+timerloggedout-spec@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview — 9d983361 Deployed Aug 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tembo Pull request created by Tembo

Development

Successfully merging this pull request may close these issues.

1 participant