Skip to content

feat(groups): I18 — bid-based task assignment (CNP-lite) - #642

Merged
ginccc merged 3 commits into
mainfrom
feat/group-i18-bidding
Aug 8, 2026
Merged

feat(groups): I18 — bid-based task assignment (CNP-lite)#642
ginccc merged 3 commits into
mainfrom
feat/group-i18-bidding

Conversation

@ginccc

@ginccc ginccc commented Aug 8, 2026

Copy link
Copy Markdown
Member

Summary

Implements I18 — Bid-based task assignment (CNP-lite) from planning/group-collaboration-improvements-plan.md (Wave 3, adopted from the research review and scoped down — the turn-auction extension stays rejected: an extra LLM call per member per turn to decide who talks doubles cost to save cost). The planner cannot know members' actual fit or load; the Contract Net Protocol's announce-bid-award loop maps cleanly onto the existing wave scheduler.

Design (per the plan)

  • assignmentMode = ROLE (default) | BID on TaskDefinition (per task) and GroupTaskConfig (group default), both with backward-compatible constructors. TaskBidEngine.effectiveMode resolves task → group → ROLE, so every pre-I18 config behaves exactly as before.
  • PLAN leaves BID-mode tasks unassigned (pre-configured and LLM-planned paths) — assigning there would preempt the auction with the planner's guess.
  • The wave's bid round (TaskForceEngine.runBidRoundIfNeeded, before each wave's grouping so awards join the same wave): eligible members (non-moderator AGENTs) each get one blind, parallel bid turn. The prompt carries the announced batch and nothing else — no transcript, no peer bids; blindness is what makes the self-assessed confidences comparable — and states the honesty rule to the model ("an inflated confidence wins you work you will fail at, on the record"). Replies land as BID transcript entries — F4's blind-bid visibility rule (peer-hidden while the phase runs) has its first producer.
  • Contract: {"bids": [{"subject", "confidence": 0..1, "estimatedComplexity": "XS|S|M|L", "rationale"}]}; three-tier parse mirroring VoteTallyEngine (FAIL_ON_TRAILING_TOKENS); prose casts no bids; bids on unannounced tasks are dropped; confidence clamped; first-bid-per-task within one reply.
  • Deterministic award, never a stalled wave: highest confidence per task; ties break by speaking order then agent id (identical on every pod); a task nobody bid on falls back to the ROLE path; the auction skips itself with a log (a silent cap reads as coverage) when it cannot beat its own overhead — fewer than 2 eligible bidders, fewer than 2 unassigned tasks, or a turn budget that cannot cover one bid turn per member. Bid turns count toward the turn budget, and their cost flows through the normal member-turn attribution.
  • The award is per-task metadataSharedTaskList.awardedBids[taskId] = AwardedBid{agentId, confidence, estimatedComplexity, rationale} — deliberately not a global DecisionRecord: an award is a scheduling fact about one task, not the discussion's conclusion.

Tests (12 new; 1694 green across engine.internal + configs.groups; checkstyle clean)

TaskBidEngineTest (pure): parse tiers + clamping ([0,1] both ends) + unknown-subject drop + case-insensitive canonical match; award to highest confidence with rationale carried; tie-break determinism (speaking order, then agent id for unordered members); no-bids absence; effective-mode chain; worthwhile-auction caps; blind prompt content.
TaskForceEngineTest (engine, mocked member turns): award to highest confidence with recorded awardedBid, turn accounting, and BID entries on the transcript; blindness asserted on the captured prompts (no peer rationale or confidence leaks); no-bids ROLE fallback assigns every task (never stalls the wave) without fabricating awards; skip-conditions (1 bidder / 1 task) make zero LLM calls yet still assign; ROLE-mode tasks are never auctioned.

Summary by CodeRabbit

  • New Features

    • Added configurable task assignment modes: role-based assignment or blind bidding.
    • Bid-mode tasks are auctioned during execution, with deterministic winner selection and recorded bid details.
    • Supports confidence, complexity, and rationale in bids.
    • Unbid tasks automatically fall back to role-based assignment.
    • Auctions are skipped when participation or task-budget requirements are not met.
  • Documentation

    • Added guidance covering bid configuration, auction behavior, parsing rules, fallbacks, and logging safeguards.
  • Tests

    • Added coverage for bid validation, awards, fallback assignment, auction eligibility, and bid privacy.

The planner cannot know members'' actual fit or load; the Contract
Net Protocol''s announce-bid-award loop maps onto the existing wave
scheduler.

- assignmentMode = ROLE (default) | BID on TaskDefinition (per task)
  and GroupTaskConfig (group default), compat ctors; pre-I18 configs
  resolve to ROLE.
- PLAN leaves BID-mode tasks unassigned; each execution wave announces
  them to eligible members in blind, parallel bid turns - the prompt
  carries the batch and nothing else (no transcript, no peer bids),
  and replies land as peer-hidden BID transcript entries.
- Deterministic award: highest confidence, ties by speaking order then
  agent id; a task nobody bid on falls back to ROLE; the auction skips
  itself (logged) when it cannot beat its own overhead (<2 bidders,
  <2 tasks, or no turn budget). Bid turns count toward the budget.
- The winning bid is per-task metadata (awardedBids on the task list),
  deliberately not a global DecisionRecord.
@ginccc
ginccc requested a review from rolandpickl as a code owner August 8, 2026 01:53
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@ginccc, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40a60ef6-c3db-490e-8e62-a1524b5854a5

📥 Commits

Reviewing files that changed from the base of the PR and between 5537087 and 3953b81.

📒 Files selected for processing (2)
  • docs/changelog.md
  • docs/group-conversations.md
📝 Walkthrough

Walkthrough

Added ROLE/BID assignment configuration, a TaskBidEngine, execution-time blind auctions, deterministic awards, fallback assignment, award persistence, tests, and documentation.

Changes

BID assignment contracts and storage

Layer / File(s) Summary
Assignment contracts and award storage
src/main/java/ai/labs/eddi/configs/groups/model/AgentGroupConfiguration.java, src/main/java/ai/labs/eddi/configs/groups/model/SharedTaskList.java
Added AssignmentMode.ROLE and AssignmentMode.BID, default normalization, backward-compatible constructors, and concurrent per-task AwardedBid storage.

Bid engine

Layer / File(s) Summary
Bid parsing and deterministic awards
src/main/java/ai/labs/eddi/engine/internal/groups/TaskBidEngine.java, src/test/java/ai/labs/eddi/engine/internal/groups/TaskBidEngineTest.java
Added auction thresholds, blind prompts, JSON parsing and validation, confidence clamping, duplicate suppression, deterministic tie-breaking, and unit tests.

Execution auction

Layer / File(s) Summary
Execution-time auction orchestration
src/main/java/ai/labs/eddi/engine/internal/groups/TaskForceEngine.java, src/test/java/ai/labs/eddi/engine/internal/groups/TaskForceEngineTest.java, docs/group-conversations.md, docs/changelog.md
BID tasks remain unassigned during planning. Execution performs blind parallel bidding, records transcripts and awards, handles skipped or failed bids, and applies role-based fallback assignment. Tests and documentation cover the flow.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TaskForceEngine
  participant TaskBidEngine
  participant MemberTurnExecutor
  participant SharedTaskList
  TaskForceEngine->>TaskBidEngine: Build blind bid prompt
  TaskForceEngine->>MemberTurnExecutor: Request parallel member bids
  MemberTurnExecutor-->>TaskForceEngine: Return bid responses
  TaskForceEngine->>TaskBidEngine: Parse and award bids
  TaskBidEngine-->>TaskForceEngine: Return deterministic awards
  TaskForceEngine->>SharedTaskList: Store award metadata
Loading

Possibly related PRs

  • labsai/EDDI#572: Introduces the task orchestration extended here with BID-mode assignment.
  • labsai/EDDI#626: Modifies TaskForceEngine, which this PR extends with auctions and fallback assignment.

Suggested reviewers: rolandpickl

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: implementing bid-based task assignment for groups using CNP-lite.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/group-i18-bidding

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

CodeQL flagged 6 log-injection sites in the I18 bid round; every
caller-influenced value (groupId, task subject, agentIds, exception
messages) now passes through LogSanitizer - 7 sites, the 6 flagged
plus the bid-turn-failure log.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/ai/labs/eddi/engine/internal/groups/TaskForceEngine.java (1)

351-354: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider making the bid round observe the discussion control token.

The wave loop checks activeTokens.get(gc.getId()) at Line 339, then calls runBidRoundIfNeeded. The bid round creates its own MemberTurnCancellation and never consults the control token. A CANCEL_IMMEDIATE that arrives while bidders are in flight is therefore not observed until the parallel batch budget expires at Line 1064. The execute wave avoids this by registering its allOf future on the token at Lines 520-525.

The delay is bounded, so this is a responsiveness gap and not a hang. Passing the token into runBidRoundIfNeeded and calling cancellation.cancel() when it is cancelled would align the bid round with the execute wave.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/ai/labs/eddi/engine/internal/groups/TaskForceEngine.java`
around lines 351 - 354, Update runBidRoundIfNeeded and its caller in the wave
loop to accept the discussion control token from activeTokens, register a
cancellation callback or equivalent that invokes the bid round’s
MemberTurnCancellation when the token is cancelled, and ensure the registration
is cleaned up appropriately. Preserve the existing bid-round behavior while
allowing CANCEL_IMMEDIATE to interrupt in-flight bidders promptly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/changelog.md`:
- Line 29: Correct the test-count summary in the changelog entry to state 13 new
tests, with 8 TaskBidEngineTest tests and 5 TaskForceEngineTest tests; leave the
listed test coverage and remaining counts unchanged.

In `@docs/group-conversations.md`:
- Around line 158-189: Move the entire “### Bid-based assignment (I18,
CNP-lite)” subsection, including its example and bullets, to immediately after
the paragraph beginning “Both caps are enforced independently” in the
agent-filed tasks content. Preserve the subsection’s text unchanged so “Both
caps” continues to refer to maxPerTurn and maxAgentAddedTasksPerDiscussion.

---

Nitpick comments:
In `@src/main/java/ai/labs/eddi/engine/internal/groups/TaskForceEngine.java`:
- Around line 351-354: Update runBidRoundIfNeeded and its caller in the wave
loop to accept the discussion control token from activeTokens, register a
cancellation callback or equivalent that invokes the bid round’s
MemberTurnCancellation when the token is cancelled, and ensure the registration
is cleaned up appropriately. Preserve the existing bid-round behavior while
allowing CANCEL_IMMEDIATE to interrupt in-flight bidders promptly.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 935121b9-feba-4e29-a0e3-4679c0803327

📥 Commits

Reviewing files that changed from the base of the PR and between 22852f0 and 5537087.

📒 Files selected for processing (8)
  • docs/changelog.md
  • docs/group-conversations.md
  • src/main/java/ai/labs/eddi/configs/groups/model/AgentGroupConfiguration.java
  • src/main/java/ai/labs/eddi/configs/groups/model/SharedTaskList.java
  • src/main/java/ai/labs/eddi/engine/internal/groups/TaskBidEngine.java
  • src/main/java/ai/labs/eddi/engine/internal/groups/TaskForceEngine.java
  • src/test/java/ai/labs/eddi/engine/internal/groups/TaskBidEngineTest.java
  • src/test/java/ai/labs/eddi/engine/internal/groups/TaskForceEngineTest.java

Comment thread docs/changelog.md Outdated
Comment thread docs/group-conversations.md
The changelog's test tally is 13 (8 TaskBidEngineTest + 5
TaskForceEngineTest), and the bid-assignment subsection now follows the
agent-task caps paragraph so 'Both caps' keeps its referent.
@ginccc
ginccc merged commit ba64cc8 into main Aug 8, 2026
28 checks passed
@ginccc
ginccc deleted the feat/group-i18-bidding branch August 8, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants