hermes - 💡(How to fix) Fix feat(kanban): max_in_progress should be enforced across all gateways/profiles sharing the same kanban.db

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

In kanban_db.py:4816-4825, the guard is:

if max_in_progress is not None and ready_rows:
    running_count = self._count_running_tasks()
    remaining = max_in_progress - running_count

If a gateway does not set max_in_progress (defaults to None), the guard is skipped entirely — that gateway can claim any number of tasks regardless of what other gateways have configured.

Fix Action

Fix / Workaround

  1. Global max_in_progress store: Store max_in_progress in a metadata table in kanban.db itself instead of per-gateway config, making it a database-level constraint.
  2. SQL-level cap: Use UPDATE ... WHERE status='ready' ... LIMIT <remaining> to atomically limit claims per dispatch cycle.
  3. Config option: Add a global kanban.enforce_max_in_progress: true to config.yaml that applies to all gateways.

Code Example

if max_in_progress is not None and ready_rows:
    running_count = self._count_running_tasks()
    remaining = max_in_progress - running_count
RAW_BUFFERClick to expand / collapse

Problem

max_in_progress is a per-gateway voluntary parameter. When multiple gateways/profiles share the same kanban.db, each gateway can bypass the others' concurrency limits.

Root Cause

In kanban_db.py:4816-4825, the guard is:

if max_in_progress is not None and ready_rows:
    running_count = self._count_running_tasks()
    remaining = max_in_progress - running_count

If a gateway does not set max_in_progress (defaults to None), the guard is skipped entirely — that gateway can claim any number of tasks regardless of what other gateways have configured.

Example Scenario

  • Profile A (annotator): runs a local LLM, sets max_in_progress: 1
  • Profile B (test-engineer): sets no max_in_progress (or a higher value)
  • Both share the same kanban.db
  • Profile B claims 5 tasks simultaneously → all 5 workers hit Profile A's local LLM → timeouts, task pileup, serial execution degraded

Suggested Fixes

  1. Global max_in_progress store: Store max_in_progress in a metadata table in kanban.db itself instead of per-gateway config, making it a database-level constraint.
  2. SQL-level cap: Use UPDATE ... WHERE status='ready' ... LIMIT <remaining> to atomically limit claims per dispatch cycle.
  3. Config option: Add a global kanban.enforce_max_in_progress: true to config.yaml that applies to all gateways.

Reproduction

  1. Set up two profiles sharing kanban.db
  2. Configure max_in_progress: 1 in one profile's config.yaml, leave the other unset
  3. Create enough tasks with matching skills
  4. Start both gateways
  5. Observe: tasks claimed in batches from the unconstrained gateway, bypassing the other's limit

Environment

  • Hermes version: latest (main branch)
  • kanban.db: SQLite shared across profiles
  • OS: Linux

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix feat(kanban): max_in_progress should be enforced across all gateways/profiles sharing the same kanban.db