@stage5/lumine 0.2.49 → 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 +22 -6
- package/lib/admin.js +112 -3
- package/lib/app-mcp/server.js +22 -4
- package/lib/commands.js +4 -2
- package/package.json +1 -1
- package/sdk/BUILD_SDK_INDEX.md +5 -5
- package/sdk/LUMINE_ADMIN.md +46 -14
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
|
|
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
|
|
289
|
-
reply is handled by Twinkle's existing autonomous
|
|
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.
|
|
301
|
-
|
|
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({
|
|
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 (
|
|
1386
|
+
if (
|
|
1387
|
+
!confirmedBuildVersionId ||
|
|
1388
|
+
!confirmedBuildReviewMethod ||
|
|
1389
|
+
!buildReviewUnderstanding
|
|
1390
|
+
) {
|
|
1285
1391
|
throw cliValidationError(
|
|
1286
|
-
"After reviewing the project, pass
|
|
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/app-mcp/server.js
CHANGED
|
@@ -18,6 +18,22 @@ function delay(ms) {
|
|
|
18
18
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function rethrowAppMcpSessionError(error) {
|
|
22
|
+
const message = String(error?.message || error);
|
|
23
|
+
if (
|
|
24
|
+
Number(error?.status || 0) === 404 &&
|
|
25
|
+
/MCP session not found/i.test(message) &&
|
|
26
|
+
!/restart the Lumine app-mcp driver/i.test(message)
|
|
27
|
+
) {
|
|
28
|
+
const guided = new Error(
|
|
29
|
+
`${message}. Restart the Lumine app-mcp driver and reopen its new appUrl.`,
|
|
30
|
+
);
|
|
31
|
+
guided.status = error.status;
|
|
32
|
+
throw guided;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
|
|
21
37
|
function openApp(url) {
|
|
22
38
|
const command =
|
|
23
39
|
process.platform === "darwin"
|
|
@@ -144,7 +160,7 @@ async function callAppTool({
|
|
|
144
160
|
sessionId,
|
|
145
161
|
name,
|
|
146
162
|
arguments: toolArguments,
|
|
147
|
-
});
|
|
163
|
+
}).catch(rethrowAppMcpSessionError);
|
|
148
164
|
const callId = created?.call?.id;
|
|
149
165
|
if (!callId) throw new Error("Twinkle did not create the app tool call.");
|
|
150
166
|
const deadline = Date.now() + CALL_TIMEOUT_MS;
|
|
@@ -155,7 +171,7 @@ async function callAppTool({
|
|
|
155
171
|
buildId,
|
|
156
172
|
sessionId,
|
|
157
173
|
callId,
|
|
158
|
-
});
|
|
174
|
+
}).catch(rethrowAppMcpSessionError);
|
|
159
175
|
const call = payload?.call;
|
|
160
176
|
if (call?.status === "completed") return call.result;
|
|
161
177
|
if (call?.status === "failed") {
|
|
@@ -169,14 +185,16 @@ async function callAppTool({
|
|
|
169
185
|
buildId,
|
|
170
186
|
sessionId,
|
|
171
187
|
callId,
|
|
172
|
-
});
|
|
188
|
+
}).catch(rethrowAppMcpSessionError);
|
|
173
189
|
if (finalPayload?.call?.status === "completed") {
|
|
174
190
|
return finalPayload.call.result;
|
|
175
191
|
}
|
|
176
192
|
if (finalPayload?.call?.status === "failed") {
|
|
177
193
|
throw new Error(finalPayload.call.errorMessage || "App tool failed.");
|
|
178
194
|
}
|
|
179
|
-
throw new Error(
|
|
195
|
+
throw new Error(
|
|
196
|
+
"App tool call timed out. Reload the appUrl tab, or restart the Lumine app-mcp driver and reopen its new appUrl.",
|
|
197
|
+
);
|
|
180
198
|
}
|
|
181
199
|
|
|
182
200
|
async function handleMcpMessage({ line, options, auth, buildId, session, tools }) {
|
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
package/sdk/BUILD_SDK_INDEX.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Build SDK Index
|
|
2
2
|
|
|
3
|
-
Version: 1.
|
|
4
|
-
Updated: 2026-08-
|
|
5
|
-
Generated: 2026-08-
|
|
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
|
|
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.
|
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -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.
|
|
38
|
-
|
|
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
|
|
891
|
-
|
|
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
|
|
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
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
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
|
|
2383
|
-
same exact-version review evidence
|
|
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
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
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;
|