Abstimmung: mehrere Agenten pruefen unabhaengig und stimmen blind ab (#702)

A unit can put operations to a blind vote instead of its lead. Not opinions
are counted but independent checks enforced.

- UnitConfig.votes: operations, voters, approveAt, rejectAt, quorum, hours,
  perDay - set only by a human (OrgAdministration.SetVotes).
- Core/Staging/Votes: routes a covered staged call before the lead; one task
  per voter with the frozen call and nothing else; cast_vote needs reasoning
  and evidence. Counted as soon as the result is settled; in between and
  without the quorum a human decides. The proposer does not vote, voters that
  read foreign content get no ballot, changes to agents never go to a vote.
- Escalation tool: list_ballots, cast_vote.
- Approvals view shows each vote with every ballot and the voters' costs;
  organisation view sets the rule and lists the votes held.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-01 12:04:33 +02:00
co-authored by Claude Opus 5.5
parent d834e5ac38
commit a5dd503d9b
23 changed files with 1238 additions and 11 deletions
+10 -1
View File
@@ -347,9 +347,18 @@ internal static class ApiEndpoints
return Unavailable("Keine Freigabestelle in dieser Instanz.");
var pending = await service.ListPendingAsync(ct);
// #702: the vote beside each call it was held on — the human decides with every ballot in view.
var votes = host.Engine?.Votes is Core.Staging.Votes v
? await v.ForCallsAsync(pending.Select(c => c.Id), ct)
: new Dictionary<long, Core.Staging.VoteRecord>();
var liste = new List<StagedCallDto>(pending.Count);
foreach (var call in pending)
liste.Add(call.ToDto(await service.BisherFreigegebenAsync(call, ct), service.KenntDauerfreigaben));
{
var dto = call.ToDto(await service.BisherFreigegebenAsync(call, ct), service.KenntDauerfreigaben);
if (votes.TryGetValue(call.Id, out var vote))
dto = dto with { Vote = await VoteMapping.ToDtoAsync(vote, (Core.Staging.Votes)host.Engine!.Votes!, ct) };
liste.Add(dto);
}
return Results.Ok(liste);
});