@stage5/lumine 0.2.32 → 0.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/admin.js CHANGED
@@ -313,13 +313,15 @@ export function resolveOperatorViewFilter({ operation, unviewed, viewed }) {
313
313
  }
314
314
 
315
315
  function adminOperationRequiresRun(operation) {
316
- return ![
317
- "identity.list",
318
- "identity.status",
319
- "identity.use",
320
- "daily-run.start",
321
- "daily-run.status",
322
- ].includes(operation.name);
316
+ return (
317
+ ![
318
+ "identity.list",
319
+ "identity.status",
320
+ "identity.use",
321
+ "daily-run.start",
322
+ "daily-run.status",
323
+ ].includes(operation.name) && !operation.name.startsWith("ai-bucket.")
324
+ );
323
325
  }
324
326
 
325
327
  function noActiveRunError() {
@@ -360,6 +362,31 @@ export function parseAdminOperation(options) {
360
362
  }
361
363
  }
362
364
 
365
+ if (namespace === "ai-bucket" || namespace === "ai-buckets") {
366
+ const bucketId = parseRequiredInteger(
367
+ options.adminBucketId,
368
+ "AI bucket ID",
369
+ 1,
370
+ );
371
+ if (action === "get" || action === "status") {
372
+ return readOperation(
373
+ "ai-bucket.get",
374
+ `/cli/admin/ai-buckets/${bucketId}`,
375
+ );
376
+ }
377
+ if (action === "accounts" && target === "add") {
378
+ return writeOperation(
379
+ "ai-bucket.accounts.add",
380
+ "POST",
381
+ `/cli/admin/ai-buckets/${bucketId}/accounts`,
382
+ {
383
+ userIds: parseAiBucketUserIds(options.adminUserIds),
384
+ note: options.note || undefined,
385
+ },
386
+ );
387
+ }
388
+ }
389
+
363
390
  if (namespace === "daily-run") {
364
391
  if (action === "start") {
365
392
  return writeOperation(
@@ -1010,6 +1037,29 @@ function parseOrderedIds(value) {
1010
1037
  return ids;
1011
1038
  }
1012
1039
 
1040
+ function parseAiBucketUserIds(value) {
1041
+ const raw = String(value || "").trim();
1042
+ if (!raw) {
1043
+ throw cliValidationError(
1044
+ "Pass explicit accounts with --user-ids <id,id,...>.",
1045
+ );
1046
+ }
1047
+ const ids = raw
1048
+ .split(",")
1049
+ .map((part) => part.trim())
1050
+ .filter(Boolean)
1051
+ .map((part) => parseRequiredInteger(part, "AI bucket user ID", 1));
1052
+ if (ids.length > 500) {
1053
+ throw cliValidationError(
1054
+ "An AI bucket batch can contain at most 500 users.",
1055
+ );
1056
+ }
1057
+ if (new Set(ids).size !== ids.length) {
1058
+ throw cliValidationError("AI bucket user IDs must be unique.");
1059
+ }
1060
+ return ids;
1061
+ }
1062
+
1013
1063
  function parseRequiredInteger(
1014
1064
  value,
1015
1065
  label,
@@ -1049,6 +1099,15 @@ function cliValidationError(message) {
1049
1099
 
1050
1100
  function printAdminResult({ operation, result }) {
1051
1101
  const data = result?.data || {};
1102
+ if (data.bucket && Array.isArray(data.memberUserIds)) {
1103
+ const added = Array.isArray(data.accounts)
1104
+ ? `; added ${data.accounts.length} explicit account(s)`
1105
+ : "";
1106
+ console.log(
1107
+ `AI bucket #${data.bucket.id} (${data.bucket.label}): ${data.memberCount} canonical member account(s)${added}.`,
1108
+ );
1109
+ return;
1110
+ }
1052
1111
  if (data.run !== undefined) {
1053
1112
  if (!data.run) {
1054
1113
  console.log("No active delegated administrator daily run.");
package/lib/commands.js CHANGED
@@ -2172,6 +2172,8 @@ export function parseArgs(args) {
2172
2172
  : raw.ids
2173
2173
  ? String(raw.ids)
2174
2174
  : "",
2175
+ adminBucketId: raw.bucketId ? String(raw.bucketId) : "",
2176
+ adminUserIds: raw.userIds ? String(raw.userIds) : "",
2175
2177
  adminType: raw.type ? String(raw.type) : "",
2176
2178
  adminKind: raw.kind ? String(raw.kind) : "",
2177
2179
  adminContentTypes: raw.contentTypes ? String(raw.contentTypes) : "",
@@ -2507,6 +2509,8 @@ export function printHelp() {
2507
2509
  lumine thumbnail generate ["<prompt>"] --model <gpt-image-2|nano-banana>
2508
2510
  lumine doctor runtime-assets
2509
2511
  lumine admin identity list|status|use <zero|ciel|auto> [--json]
2512
+ lumine admin ai-bucket get --bucket-id <id> [--json]
2513
+ lumine admin ai-bucket accounts add --bucket-id <id> --user-ids <id,id,...> [--note <text>] [--json]
2510
2514
  lumine admin daily-run start [--identity zero|ciel|auto] [--comment-mode off|draft|post] [--run-key <key>] [--json]
2511
2515
  lumine admin daily-run status|complete|fail [--reason <text>] [--json]
2512
2516
  lumine admin recommendations list [--content-types comment,dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
@@ -2605,6 +2609,8 @@ Options:
2605
2609
  --idempotency-key <k> Stable retry key for one admin mutation
2606
2610
  --level <1|2|3> Admin subject effort level
2607
2611
  --subject-ids <ids> Complete ordered Featured subject IDs
2612
+ --bucket-id <id> Unbanned AI identity bucket for account consolidation
2613
+ --user-ids <ids> Explicit user IDs for an AI bucket batch (up to 500)
2608
2614
  --type <type> Admin target: subject, comment, aiStory, or dailyReflection
2609
2615
  --kind recommend Admin recommendation queue kind
2610
2616
  --anyone-can-reward Enable canonical reward eligibility
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage5/lumine",
3
- "version": "0.2.32",
3
+ "version": "0.2.33",
4
4
  "description": "Command line tools for launching Lumine builds on Twinkle.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,6 +49,30 @@ Comment mode is stored only on the current run:
49
49
  - `draft`: server-generated drafts, no public comment.
50
50
  - `post`: drafts plus idempotent publication through the ordinary comment path.
51
51
 
52
+ ### Private AI-bucket maintenance
53
+
54
+ AI identity buckets are private operator bookkeeping, not a Zero/Ciel public
55
+ action. They therefore do not require or attach to a delegated daily run:
56
+
57
+ ```bash
58
+ lumine admin ai-bucket get --bucket-id 10 --json
59
+ lumine admin ai-bucket accounts add --bucket-id 10 \
60
+ --user-ids 3127,13037,15410,16288 \
61
+ --note "operator-confirmed account family" --json
62
+ ```
63
+
64
+ `accounts add` accepts 1-500 unique positive user IDs, preflights the complete
65
+ batch before writing, adds the canonical user and durable verified-email rules,
66
+ re-attributes current-day AI usage, and returns the canonical bucket members.
67
+ It is idempotent to retry. The API records the real operator in the private
68
+ Lumine audit log; no public bot identity is involved.
69
+
70
+ This surface intentionally accepts only an existing **unbanned** bucket. It
71
+ cannot ban accounts, block signup, add IP/device/risk-key rules, or infer an
72
+ account family. Identification remains a human/LLM evidence judgment and must
73
+ be explicitly requested by Mikey; routine administrator runs still escalate
74
+ suspected alternate accounts and never auto-enforce.
75
+
52
76
  ## Editorial priorities
53
77
 
54
78
  The CLI enforces none of this — it is the standing instruction for the operator