@stage5/lumine 0.2.50 → 0.2.51

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/README.md CHANGED
@@ -267,7 +267,8 @@ lumine admin post recommend comment:456 --anyone-can-reward --reward-twinkles 3
267
267
  lumine admin post reward comment:456 --twinkles 3 --json
268
268
  lumine admin post skip-batch --target-file skipped.json --checkpoint skip-progress.json --json
269
269
  lumine admin comment draft build:884 --file comment.md \
270
- --review-receipt /path/from-build-review/review.json --json
270
+ --review-receipt /path/from-build-review/review.json \
271
+ --review-context build-context.json --json
271
272
  lumine admin comment post --draft-id 77 --json
272
273
  lumine admin news claim --output claim.json --scaffold editorial.json --json
273
274
  lumine admin news validate --claim claim.json --file editorial.json --json
@@ -285,9 +286,9 @@ Numeric recommendation targets default to subjects. Use `comment:<id>`,
285
286
  `aiStory:<id>`, `dailyReflection:<id>`, a canonical URL, or the matching
286
287
  `--type` for another post kind. Commenting is always `off` for a new run unless
287
288
  `--comment-mode draft` or `--comment-mode post` is explicitly supplied. Drafts
288
- and posts use the selected bot's server-owned canonical persona; a later human
289
- reply is handled by Twinkle's existing autonomous Zero/Ciel responder without
290
- Lumine remaining active.
289
+ and posts use the selected bot's server-owned canonical persona. Outside Build
290
+ threads, a later human reply is handled by Twinkle's existing autonomous
291
+ Zero/Ciel responder without Lumine remaining active.
291
292
 
292
293
  Management agents also inspect recent public Build candidates during each run.
293
294
  `builds review` opens one published app in an isolated temporary Chromium
@@ -297,8 +298,23 @@ subdirectory. A direct Build comment is never server-generated: review the
297
298
  runtime (or pull and read an
298
299
  open-source app), compose with `--file`, and attach the receipt. The server
299
300
  rejects missing or stale review evidence and any app/thread change before
300
- publication. Manual `--reviewed-version` / `--reviewed-via` evidence remains
301
- available for genuine code reviews.
301
+ publication. Also pass `--review-context` with a private JSON file containing
302
+ only an `understanding` string: the concrete app behavior and design the agent
303
+ actually learned during that review. The server stamps the canonical Build,
304
+ published version, review method, and review time around that understanding;
305
+ none of it is exposed in the public comment payload. Manual
306
+ `--reviewed-version` / `--reviewed-via` evidence remains available for genuine
307
+ code reviews.
308
+
309
+ When a human directly replies to that management comment, or to a later
310
+ Zero/Ciel reply descended from it, the same bot may answer from the stored
311
+ historical understanding. That answer uses the commenter's normal AI Energy
312
+ path, including the usual reply-or-Like decision; if their battery is empty,
313
+ the ordinary sponsor placeholder and button are shown. Build mentions and
314
+ replies without this private management provenance remain disabled. A newer
315
+ published Build version does not rewrite history: the bot is told that its
316
+ understanding came from the older reviewed version and must not claim it
317
+ rechecked the app.
302
318
 
303
319
  Every operation is noninteractive when its required arguments are present.
304
320
  `--json` prints exactly one uncolored JSON value and returns a nonzero status
package/lib/admin.js CHANGED
@@ -17,6 +17,8 @@ import {
17
17
  const MAX_EDITORIAL_FILE_BYTES = 256 * 1024;
18
18
  const MAX_COMPOSED_TEXT_FILE_BYTES = 64 * 1024;
19
19
  const MAX_COMPOSED_TEXT_LENGTH = 10_000;
20
+ const MAX_BUILD_REVIEW_CONTEXT_FILE_BYTES = 64 * 1024;
21
+ const MAX_BUILD_REVIEW_UNDERSTANDING_LENGTH = 12_000;
20
22
  const MAX_NOTABLE_NOTE_LENGTH = 2_000;
21
23
  const MAX_IDENTITY_INSPECTION_REASON_LENGTH = 500;
22
24
  const MAX_ESCALATION_DECISION_NOTE_LENGTH = 2_000;
@@ -54,6 +56,62 @@ function readComposedTextFile(filePath) {
54
56
  return normalized;
55
57
  }
56
58
 
59
+ function readBuildReviewContextFile(filePath) {
60
+ const normalizedPath = String(filePath || "").trim();
61
+ if (!normalizedPath) {
62
+ throw cliValidationError(
63
+ "Pass the private reviewed understanding with --review-context <context.json>.",
64
+ );
65
+ }
66
+ let contents;
67
+ try {
68
+ contents = readFileSync(normalizedPath, "utf8");
69
+ } catch {
70
+ throw cliValidationError(`Could not read ${normalizedPath}.`);
71
+ }
72
+ if (
73
+ Buffer.byteLength(contents, "utf8") > MAX_BUILD_REVIEW_CONTEXT_FILE_BYTES
74
+ ) {
75
+ throw cliValidationError(
76
+ "The Build review context file must be under 64KB.",
77
+ );
78
+ }
79
+ let parsed;
80
+ try {
81
+ parsed = JSON.parse(contents);
82
+ } catch {
83
+ throw cliValidationError(`${normalizedPath} is not valid JSON.`);
84
+ }
85
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
86
+ throw cliValidationError(
87
+ "The Build review context must be a JSON object with an understanding string.",
88
+ );
89
+ }
90
+ const unexpectedKeys = Object.keys(parsed).filter(
91
+ (key) => key !== "understanding",
92
+ );
93
+ if (unexpectedKeys.length > 0) {
94
+ throw cliValidationError(
95
+ "The Build review context JSON may contain only the understanding field; version and provenance are server-owned.",
96
+ );
97
+ }
98
+ const understanding =
99
+ typeof parsed.understanding === "string"
100
+ ? parsed.understanding.trim()
101
+ : "";
102
+ if (!understanding) {
103
+ throw cliValidationError(
104
+ "The Build review context understanding must be a non-empty string.",
105
+ );
106
+ }
107
+ if (understanding.length > MAX_BUILD_REVIEW_UNDERSTANDING_LENGTH) {
108
+ throw cliValidationError(
109
+ `The Build review context understanding must be at most ${MAX_BUILD_REVIEW_UNDERSTANDING_LENGTH} characters.`,
110
+ );
111
+ }
112
+ return understanding;
113
+ }
114
+
57
115
  function readEditorialFile(filePath) {
58
116
  const normalizedPath = String(filePath || "").trim();
59
117
  if (!normalizedPath) {
@@ -243,6 +301,8 @@ export async function adminCommand(options) {
243
301
  assertComposedCommentDraftResult({
244
302
  result,
245
303
  expectedContent: operation.body.content,
304
+ requiresBuildReviewContext:
305
+ typeof operation.body.buildReviewUnderstanding === "string",
246
306
  });
247
307
  }
248
308
  if (operation.name === "daily-run.start") {
@@ -363,7 +423,11 @@ export function normalizeAdminBuildCandidatesResult({ result, siteUrl }) {
363
423
  };
364
424
  }
365
425
 
366
- export function assertComposedCommentDraftResult({ result, expectedContent }) {
426
+ export function assertComposedCommentDraftResult({
427
+ result,
428
+ expectedContent,
429
+ requiresBuildReviewContext = false,
430
+ }) {
367
431
  const draft = result?.data?.draft;
368
432
  if (
369
433
  draft?.decision === "draft" &&
@@ -371,6 +435,25 @@ export function assertComposedCommentDraftResult({ result, expectedContent }) {
371
435
  draft?.content === expectedContent &&
372
436
  draft?.status === "ready"
373
437
  ) {
438
+ if (
439
+ requiresBuildReviewContext &&
440
+ draft?.buildReviewContextStored !== true
441
+ ) {
442
+ const error = new Error(
443
+ "The API did not confirm that it stored the private Build review context. Stop without publishing this draft and deploy the context-aware API first, then retry with a new idempotency key.",
444
+ );
445
+ error.code = "LUMINE_ADMIN_BUILD_REVIEW_CONTEXT_UNSUPPORTED";
446
+ error.data = {
447
+ ok: false,
448
+ status: "validation_error",
449
+ error: {
450
+ code: error.code,
451
+ message: error.message,
452
+ details: null,
453
+ },
454
+ };
455
+ throw error;
456
+ }
374
457
  return;
375
458
  }
376
459
  const error = new Error(
@@ -1255,6 +1338,9 @@ export function parseAdminOperation(options) {
1255
1338
  const reviewReceipt = options.adminReviewReceipt
1256
1339
  ? parseBuildReviewReceipt(options.adminReviewReceipt)
1257
1340
  : null;
1341
+ const buildReviewUnderstanding = options.adminReviewContext
1342
+ ? readBuildReviewContextFile(options.adminReviewContext)
1343
+ : undefined;
1258
1344
  if (reviewReceipt && (reviewedBuildVersionId || buildReviewMethod)) {
1259
1345
  throw cliValidationError(
1260
1346
  "Pass either --review-receipt or manual --reviewed-version/--reviewed-via evidence, not both.",
@@ -1266,6 +1352,22 @@ export function parseAdminOperation(options) {
1266
1352
  const confirmedBuildReviewMethod = reviewReceipt
1267
1353
  ? "runtime"
1268
1354
  : buildReviewMethod;
1355
+ if (
1356
+ buildReviewUnderstanding &&
1357
+ (!confirmedBuildVersionId || !confirmedBuildReviewMethod)
1358
+ ) {
1359
+ throw cliValidationError(
1360
+ "--review-context requires confirmed Build review evidence.",
1361
+ );
1362
+ }
1363
+ if (
1364
+ (confirmedBuildVersionId || confirmedBuildReviewMethod) &&
1365
+ !buildReviewUnderstanding
1366
+ ) {
1367
+ throw cliValidationError(
1368
+ "Build review evidence requires --review-context <context.json>.",
1369
+ );
1370
+ }
1269
1371
  if (
1270
1372
  reviewReceipt &&
1271
1373
  parsedTarget.type === "build" &&
@@ -1281,9 +1383,13 @@ export function parseAdminOperation(options) {
1281
1383
  "Build comments are management-agent composed only; pass --file <comment.md> after reviewing the project.",
1282
1384
  );
1283
1385
  }
1284
- if (!confirmedBuildVersionId || !confirmedBuildReviewMethod) {
1386
+ if (
1387
+ !confirmedBuildVersionId ||
1388
+ !confirmedBuildReviewMethod ||
1389
+ !buildReviewUnderstanding
1390
+ ) {
1285
1391
  throw cliValidationError(
1286
- "After reviewing the project, pass both --reviewed-version <published-artifact-id> and --reviewed-via runtime|code.",
1392
+ "After reviewing the project, pass review evidence and --review-context <context.json>.",
1287
1393
  );
1288
1394
  }
1289
1395
  } else if (
@@ -1313,6 +1419,9 @@ export function parseAdminOperation(options) {
1313
1419
  ...(confirmedBuildReviewMethod
1314
1420
  ? { buildReviewMethod: confirmedBuildReviewMethod }
1315
1421
  : {}),
1422
+ ...(buildReviewUnderstanding
1423
+ ? { buildReviewUnderstanding }
1424
+ : {}),
1316
1425
  },
1317
1426
  );
1318
1427
  }
package/lib/commands.js CHANGED
@@ -2363,6 +2363,7 @@ export function parseArgs(args) {
2363
2363
  adminScaffoldFile: raw.scaffold ? String(raw.scaffold) : "",
2364
2364
  adminTargetFile: raw.targetFile ? String(raw.targetFile) : "",
2365
2365
  adminReviewReceipt: raw.reviewReceipt ? String(raw.reviewReceipt) : "",
2366
+ adminReviewContext: raw.reviewContext ? String(raw.reviewContext) : "",
2366
2367
  adminSeverity: raw.severity ? String(raw.severity) : "",
2367
2368
  adminStatus: raw.status ? String(raw.status) : "",
2368
2369
  adminWaitMs: raw.waitMs ? String(raw.waitMs) : "",
@@ -2766,8 +2767,8 @@ export function printHelp() {
2766
2767
  lumine admin post skip <target> [--type comment|aiStory|dailyReflection] [--reason <text>] [--json]
2767
2768
  lumine admin post skip-batch --target-file <json-or-lines> [--reason <text>] [--checkpoint <file> [--resume]] [--json]
2768
2769
  lumine admin post reward <target> [--type subject|comment|aiStory|dailyReflection] --twinkles 3 [--json]
2769
- lumine admin comment draft <target> [--type subject|comment|build|aiStory|dailyReflection] [--file <comment.md>] [--review-receipt <review.json>|--reviewed-version <id> --reviewed-via runtime|code] [--identity zero|ciel|auto] [--json]
2770
- lumine admin comment reply comment:<id> [--file <reply.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--identity zero|ciel|auto] [--json]
2770
+ lumine admin comment draft <target> [--type subject|comment|build|aiStory|dailyReflection] [--file <comment.md>] [--review-receipt <review.json>|--reviewed-version <id> --reviewed-via runtime|code] [--review-context <context.json>] [--identity zero|ciel|auto] [--json]
2771
+ lumine admin comment reply comment:<id> [--file <reply.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--review-context <context.json>] [--identity zero|ciel|auto] [--json]
2771
2772
  lumine admin comment post --draft-id <id> [--json]
2772
2773
  lumine admin comment edit <comment-id> --file <comment.md> [--json]
2773
2774
  lumine admin brief [--days <1..30>] [--json]
@@ -2864,6 +2865,7 @@ Options:
2864
2865
  --scaffold <file> Write an editable newspaper editorial scaffold
2865
2866
  --target-file <file> JSON array or newline list for audited batch skips
2866
2867
  --review-receipt <f> Confirmed managed Build runtime review receipt
2868
+ --review-context <f> Private JSON understanding from the reviewed Build
2867
2869
  --severity <level> Run escalation severity: attention or urgent
2868
2870
  --status <state> Private escalation or todo lifecycle filter/state
2869
2871
  --wait-ms <ms> Managed Build runtime observation time (1000-45000)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage5/lumine",
3
- "version": "0.2.50",
3
+ "version": "0.2.51",
4
4
  "description": "Command line tools for launching Lumine builds on Twinkle.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,8 +1,8 @@
1
1
  # Build SDK Index
2
2
 
3
- Version: 1.36.0
4
- Updated: 2026-08-19
5
- Generated: 2026-08-19T05:45:14.858Z
3
+ Version: 1.37.0
4
+ Updated: 2026-08-25
5
+ Generated: 2026-08-25T02:01:15.207Z
6
6
 
7
7
  ## Notes
8
8
  - This SDK is injected into Build iframes via the Build preview/runtime.
@@ -348,10 +348,10 @@ const result = await Twinkle.ai.chat({ message, history: chatHistory, systemProm
348
348
  - Use this instead of asking Twinkle.ai.chat to return JSON.
349
349
  - expectedStructure must be a JSON object that describes the exact returned object shape.
350
350
  - mode is accepted as an alias for thinkingMode, and mid is accepted as an alias for medium.
351
- - Omit model to use the normal Lite/Medium/High routing. model accepts only claude-opus-5 or claude-fable-5, and either explicit model must be paired with thinkingMode: 'high'; unknown model IDs reject instead of silently falling back.
351
+ - Omit model to use the normal Lite/Medium/High routing. model accepts gpt-5.6-sol, claude-opus-5, or claude-fable-5, and every explicit model must be paired with thinkingMode: 'high'; unknown model IDs reject instead of silently falling back.
352
352
  - thinkingMode low uses GPT-5.6 Luna and consumes the viewer's AI Energy from confirmed provider usage; its smaller model is usually cheaper than Medium or High.
353
353
  - thinkingMode medium uses Grok 4.6 with medium reasoning and consumes normal AI Energy.
354
- - thinkingMode high uses GPT-5.6 Sol with high reasoning and consumes high AI Energy.
354
+ - thinkingMode high without model uses GPT-5.6 Sol with high reasoning and consumes high AI Energy. Explicit model: 'gpt-5.6-sol' selects Sol with xhigh reasoning at the same High AI Energy tier.
355
355
  - claude-opus-5 uses Anthropic adaptive High thinking. claude-fable-5 uses Anthropic xhigh thinking and normally consumes more AI Energy for comparable token use. Both debit confirmed provider usage at the High tier.
356
356
  - Pass onStatus and/or onText to stream progress from the same structured generation. onStatus receives high-level phases such as thinking, searching_web, responding, validating, and completed.
357
357
  - onText receives accumulated structured-output text plus { done, delta, requestId, status }. Partial output is intentionally incomplete and may include provider formatting; parse only when done is true, when the callback receives the canonical object serialized as JSON, and use the resolved object as the source of truth.
@@ -34,8 +34,10 @@ canonical structured data.
34
34
  ordering key for the People directory, so the bots now surface there after a
35
35
  run; that is the intended consequence of the timestamp being truthful.
36
36
  - A later human reply to a delegated Zero/Ciel comment enters the existing
37
- server-side autonomous comment-assistant pipeline. Lumine does not need to
38
- remain running.
37
+ server-side autonomous comment-assistant pipeline. For Build threads this is
38
+ limited to comments carrying the private reviewed-management provenance
39
+ described below. The human's normal AI Energy and sponsor path applies;
40
+ Lumine does not need to remain running.
39
41
 
40
42
  `auto` selects Zero first when no completed rotation exists, then alternates
41
43
  after a successfully completed run that performed a mutation. Failed,
@@ -887,8 +889,11 @@ captures a screenshot and bounded console evidence, then fetches the identity
887
889
  again. It writes `review.json` in a unique per-review subdirectory only when
888
890
  the browser completed, the screenshot exists, and the artifact did not change
889
891
  mid-review. Attach the returned `receiptPath` with
890
- `comment draft ... --review-receipt review.json`; this binds the draft to the
891
- exact reviewed artifact without copying a version number by hand.
892
+ `comment draft ... --review-receipt review.json`, and pass a separate private
893
+ `--review-context context.json` containing only the concrete `understanding`
894
+ learned during that review. The receipt binds the draft to the exact reviewed
895
+ artifact without copying a version number by hand; the server owns the Build,
896
+ version, method, and review-time fields around that understanding.
892
897
 
893
898
  During every management run, scan recent Build candidates back through the
894
899
  run's review window alongside Subjects and the recommendation queue. An app
@@ -2315,10 +2320,17 @@ to the exact published artifact you saw:
2315
2320
 
2316
2321
  ```bash
2317
2322
  lumine admin comment draft build:884 --file comment.md \
2318
- --reviewed-version 4512 --reviewed-via runtime --json
2323
+ --reviewed-version 4512 --reviewed-via runtime \
2324
+ --review-context context.json --json
2319
2325
  lumine admin comment post --draft-id 77 --json
2320
2326
  ```
2321
2327
 
2328
+ ```json
2329
+ {
2330
+ "understanding": "The start screen pairs a green zombie with a sci-fi soldier, and the first interaction teaches the player to select a zombie before firing the railgun."
2331
+ }
2332
+ ```
2333
+
2322
2334
  Use `--reviewed-via code` only when you actually pulled and read the project;
2323
2335
  `runtime` means you opened and tried the published app. Replies to human
2324
2336
  comments inside a Build use `comment:<id>` plus the same review flags. The API
@@ -2327,9 +2339,20 @@ published version, a private/noncanonical Build, or any Build/comment-context
2327
2339
  change between draft and publication. A changed version means review the new
2328
2340
  project state and compose again. The flags are an auditable statement of what
2329
2341
  the management agent did, not permission to infer experience from metadata.
2330
- Autonomous mention/reply generation and sponsored AI replies are disabled in
2331
- Build threads. The generic `comment edit` shortcut is also disabled there;
2332
- review the current version and post a version-bound correction reply instead.
2342
+ The review-context JSON is private server-owned conversation provenance; it is
2343
+ not included in the public comment, draft response, socket payload, or audit
2344
+ metadata. A direct human reply to the resulting Zero/Ciel management comment,
2345
+ or to a later reply by that same bot descended from it, may enter the ordinary
2346
+ comment-assistant pipeline using this stored historical understanding. It uses
2347
+ the human commenter's normal AI Energy and reply-or-Like gate. If that user has
2348
+ no remaining AI Energy, the normal sponsor placeholder/button is shown and a
2349
+ sponsor pays from their own battery. Mentions elsewhere in a Build, replies to
2350
+ unlinked or legacy bot comments, replies to humans, and the other bot remain
2351
+ ineligible. If the published version has changed, the responder is told the
2352
+ stored understanding belongs to the reviewed older version and must say it has
2353
+ not checked behavior that could have changed. The generic `comment edit`
2354
+ shortcut is also disabled there; review the current version and post a
2355
+ version-bound correction reply instead.
2333
2356
 
2334
2357
  **Offer a Lumine prompt when the moment invites it (Mikey's direction,
2335
2358
  2026-08-10).** Zero and Ciel may include one concrete, copy-pasteable Lumine
@@ -2362,6 +2385,11 @@ silently ignores `content` and generates with the server's model instead. The
2362
2385
  CLI therefore requires the ready draft response to echo the exact submitted
2363
2386
  text with `reason: "operator-composed"`; otherwise it stops with
2364
2387
  `LUMINE_ADMIN_COMPOSED_COMMENT_UNSUPPORTED`. Never publish that rejected draft.
2388
+ For Build drafts it additionally requires
2389
+ `buildReviewContextStored: true`; an older API that ignores the private context
2390
+ fails closed with `LUMINE_ADMIN_BUILD_REVIEW_CONTEXT_UNSUPPORTED`. Deploy the
2391
+ context-aware API, then retry with a new idempotency key rather than publishing
2392
+ the unconfirmed draft.
2365
2393
  Placement stays on the requested target: compose replies via `comment:<id>`
2366
2394
  targets (the generated path's model-chosen
2367
2395
  `replyTargetCommentId` does not apply). Everything below about targets,
@@ -2379,14 +2407,17 @@ A draft targets one of:
2379
2407
 
2380
2408
  A reply's container resolves canonically from the target comment: its subject,
2381
2409
  Build, or AI Story / Daily Reflection root. Comments under any other root are
2382
- rejected with `CLI_ADMIN_UNSUPPORTED_REPLY_ROOT`. Build replies require the
2383
- same exact-version review evidence as top-level Build comments. Replies to
2410
+ rejected with `CLI_ADMIN_UNSUPPORTED_REPLY_ROOT`. Build replies authored by the
2411
+ management agent require the same exact-version review evidence and private
2412
+ review context as top-level Build comments. Replies to
2384
2413
  Zero/Ciel comments and to notification comments are rejected with
2385
2414
  `CLI_ADMIN_INVALID_REPLY_TARGET` — the bots never thread with themselves or
2386
- each other, and a human's later reply to a delegated comment still enters the
2387
- existing autonomous comment-assistant pipeline. Published replies carry the
2388
- ordinary thread linkage (thread root and reply-to), and notification fan-out
2389
- uses the normal canonical path.
2415
+ each other through the delegated CLI. A human's later direct reply to a
2416
+ context-backed Build management comment may enter the energy-gated autonomous
2417
+ pipeline described above; ordinary human replies elsewhere follow the existing
2418
+ comment-assistant rules. Published replies carry the ordinary thread linkage
2419
+ (thread root and reply-to), and notification fan-out uses the normal canonical
2420
+ path.
2390
2421
 
2391
2422
  ```ts
2392
2423
  type CommentDraft = Success<{
@@ -2402,6 +2433,7 @@ type CommentDraft = Success<{
2402
2433
  commentMode: "draft" | "post";
2403
2434
  personaRevision: string; // SHA-256; raw prompt is never returned
2404
2435
  contextRevision: string; // SHA-256 of canonical container/comments/target
2436
+ buildReviewContextStored: boolean; // true before a Build draft may publish
2405
2437
  decision: "draft" | "skip";
2406
2438
  reason: string | null;
2407
2439
  content: string | null;