feat(base)!: one budget per person for all their assistants, the effort each takes, the operator's lists by page

A grant now says only which assistant a person may use, and keeps their
agreement; the limits are the person's (assistant_budget): one per UTC
day and month in money and in tokens, each optional, money counting the
assistants with prices, tokens every one (Halkyon Learn's ADR 0021, D58,
D59). assistantOperator.grant gives several people several assistants
with one budget, change sets one person's exactly, revoke takes back
everything; grantees and granteesOf list people with their assistants,
budget and use, 50 at a time. The migration carries each person's grant
limits into a budget: per unit, their sum, a grant without a limit making
it none.

assistants.env gives each assistant a default and a highest effort
(_EFFORT, _MAX_EFFORT; refused at start where the provider takes none);
ask takes one within that range, refusing another (invalidEffort), and
caps the output at its ceiling (D63).

instanceOperator.waiting and accounts come 50 at a time from an offset,
and counts gives the rows of the operator's screen (D62).

BREAKING CHANGE: the offer, the grants and the operator's lists changed
shape; Learn's server now asks for build 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-26 15:07:04 +01:00
commit 24ed63585e
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -58,6 +58,7 @@ Map<String, int> _fillSyncedTables(Database db) {
final path = _id();
final step = _id();
final pdf = _id();
final conversation = _id();
final rows = <String, (String, List<Object?>)>{
'studyset': (
"INSERT INTO studyset (id, spaceId, payload) VALUES (?, 1, x'00')",
@ -164,6 +165,16 @@ Map<String, int> _fillSyncedTables(Database db) {
"sealedKey, createdAt) VALUES (?, 1, 'key', 'studyset', ?, x'00', 0)",
[_id(), studyset],
),
'assistant_conversation': (
'INSERT INTO assistant_conversation (id, spaceId, payload) '
"VALUES (?, 1, x'00')",
[conversation],
),
'assistant_turn': (
'INSERT INTO assistant_turn (id, spaceId, conversationId, payload) '
"VALUES (?, 1, ?, x'00')",
[_id(), conversation],
),
};
final synced = {