@stage5/lumine 0.2.33 → 0.2.34
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 +11 -0
- package/lib/admin.js +147 -3
- package/lib/commands.js +12 -4
- package/package.json +1 -1
- package/sdk/LUMINE_ADMIN.md +88 -12
package/README.md
CHANGED
|
@@ -169,6 +169,7 @@ lumine admin daily-run start --identity auto --comment-mode off --json
|
|
|
169
169
|
lumine admin recommendations list --cursor '<cursor>' --json
|
|
170
170
|
lumine admin subjects candidates --after 2026-08-01T00:00:00Z --json
|
|
171
171
|
lumine admin subjects candidates --effort unassigned --json
|
|
172
|
+
lumine admin builds candidates --cursor '<cursor>' --json
|
|
172
173
|
lumine admin subject get 123 --include-comments --json
|
|
173
174
|
lumine admin post get https://www.twin-kle.com/ai-stories/88 --json
|
|
174
175
|
lumine admin post comments dailyReflection:99 --json
|
|
@@ -184,6 +185,9 @@ lumine admin brief --days 3 --json
|
|
|
184
185
|
lumine admin notable add Minecrarft_guy --note "Created 8 thoughtful subjects and helped peers in 23 comments this window." --json
|
|
185
186
|
lumine admin post recommend comment:456 --anyone-can-reward --reward-twinkles 3 --json
|
|
186
187
|
lumine admin post reward comment:456 --twinkles 3 --json
|
|
188
|
+
lumine admin comment draft build:884 --file comment.md \
|
|
189
|
+
--reviewed-version 4512 --reviewed-via runtime --json
|
|
190
|
+
lumine admin comment post --draft-id 77 --json
|
|
187
191
|
lumine admin daily-run complete --json
|
|
188
192
|
```
|
|
189
193
|
|
|
@@ -195,6 +199,13 @@ and posts use the selected bot's server-owned canonical persona; a later human
|
|
|
195
199
|
reply is handled by Twinkle's existing autonomous Zero/Ciel responder without
|
|
196
200
|
Lumine remaining active.
|
|
197
201
|
|
|
202
|
+
Management agents also inspect recent public Build candidates during each run.
|
|
203
|
+
A direct Build comment is never server-generated: first open and try the
|
|
204
|
+
published app or pull and read its code, then compose with `--file` and bind
|
|
205
|
+
the draft to the exact `publishedArtifactVersionId` using
|
|
206
|
+
`--reviewed-version` and `--reviewed-via runtime|code`. The server rejects
|
|
207
|
+
missing or stale review evidence and any app/thread change before publication.
|
|
208
|
+
|
|
198
209
|
Every operation is noninteractive when its required arguments are present.
|
|
199
210
|
`--json` prints exactly one uncolored JSON value and returns a nonzero status
|
|
200
211
|
for forbidden, not-found, validation, and partial-failure responses. Pass a
|
package/lib/admin.js
CHANGED
|
@@ -125,6 +125,12 @@ export async function adminCommand(options) {
|
|
|
125
125
|
},
|
|
126
126
|
timeoutMs: options.timeoutMs,
|
|
127
127
|
});
|
|
128
|
+
if (operation.name === "builds.candidates") {
|
|
129
|
+
result = normalizeAdminBuildCandidatesResult({
|
|
130
|
+
result,
|
|
131
|
+
siteUrl: options.siteUrl,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
128
134
|
if (recommendationContentTypes) {
|
|
129
135
|
result = filterRecommendationQueueResult({
|
|
130
136
|
result,
|
|
@@ -179,6 +185,38 @@ export async function adminCommand(options) {
|
|
|
179
185
|
return result;
|
|
180
186
|
}
|
|
181
187
|
|
|
188
|
+
export function normalizeAdminBuildCandidatesResult({ result, siteUrl }) {
|
|
189
|
+
const builds = Array.isArray(result?.builds) ? result.builds : [];
|
|
190
|
+
const nextCursor = String(result?.cursor || "").trim() || null;
|
|
191
|
+
return {
|
|
192
|
+
ok: true,
|
|
193
|
+
status: "success",
|
|
194
|
+
data: {
|
|
195
|
+
builds: builds.map((build) => {
|
|
196
|
+
const id = Number(build?.id || 0);
|
|
197
|
+
return {
|
|
198
|
+
...build,
|
|
199
|
+
url:
|
|
200
|
+
id > 0
|
|
201
|
+
? `${String(siteUrl || "").replace(/\/$/, "")}/app/${id}`
|
|
202
|
+
: null,
|
|
203
|
+
review: {
|
|
204
|
+
publishedArtifactVersionId:
|
|
205
|
+
Number(build?.publishedArtifactVersionId || 0) || null,
|
|
206
|
+
codePullAvailable: build?.collaborationMode === "open_source",
|
|
207
|
+
requiredBeforeComment: true,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}),
|
|
211
|
+
pagination: {
|
|
212
|
+
nextCursor,
|
|
213
|
+
hasMore: Boolean(nextCursor),
|
|
214
|
+
exhausted: !nextCursor,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
182
220
|
export function assertComposedCommentDraftResult({ result, expectedContent }) {
|
|
183
221
|
const draft = result?.data?.draft;
|
|
184
222
|
if (
|
|
@@ -385,6 +423,25 @@ export function parseAdminOperation(options) {
|
|
|
385
423
|
},
|
|
386
424
|
);
|
|
387
425
|
}
|
|
426
|
+
if (action === "note" && target === "set") {
|
|
427
|
+
const note = String(options.note || "").trim();
|
|
428
|
+
if (!note) {
|
|
429
|
+
throw cliValidationError(
|
|
430
|
+
"Pass the quota-only context with --note <text>.",
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
if (note.length > 255) {
|
|
434
|
+
throw cliValidationError(
|
|
435
|
+
"An AI bucket note can be at most 255 characters.",
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
return writeOperation(
|
|
439
|
+
"ai-bucket.note.set",
|
|
440
|
+
"PUT",
|
|
441
|
+
`/cli/admin/ai-buckets/${bucketId}/note`,
|
|
442
|
+
{ note },
|
|
443
|
+
);
|
|
444
|
+
}
|
|
388
445
|
}
|
|
389
446
|
|
|
390
447
|
if (namespace === "daily-run") {
|
|
@@ -434,6 +491,18 @@ export function parseAdminOperation(options) {
|
|
|
434
491
|
);
|
|
435
492
|
}
|
|
436
493
|
|
|
494
|
+
if (namespace === "builds" && action === "candidates") {
|
|
495
|
+
return readOperation(
|
|
496
|
+
"builds.candidates",
|
|
497
|
+
withQuery("/build/public/list", {
|
|
498
|
+
sort: "recent",
|
|
499
|
+
scope: "all",
|
|
500
|
+
cursor: options.adminCursor,
|
|
501
|
+
limit: options.limit,
|
|
502
|
+
}),
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
437
506
|
if (
|
|
438
507
|
namespace === "subjects" &&
|
|
439
508
|
(action === "list" || action === "candidates")
|
|
@@ -671,7 +740,7 @@ export function parseAdminOperation(options) {
|
|
|
671
740
|
}
|
|
672
741
|
|
|
673
742
|
if (namespace === "bot-output" && !action) {
|
|
674
|
-
if (options.adminDays
|
|
743
|
+
if (options.adminDays) {
|
|
675
744
|
const days = Number(options.adminDays);
|
|
676
745
|
if (!Number.isInteger(days) || days < 1 || days > 30) {
|
|
677
746
|
throw cliValidationError("--days must be an integer between 1 and 30.");
|
|
@@ -703,7 +772,7 @@ export function parseAdminOperation(options) {
|
|
|
703
772
|
|
|
704
773
|
if (namespace === "comment") {
|
|
705
774
|
if (action === "draft" || action === "reply") {
|
|
706
|
-
const parsedTarget =
|
|
775
|
+
const parsedTarget = parseAdminCommentTarget({
|
|
707
776
|
target,
|
|
708
777
|
explicitType: options.adminType,
|
|
709
778
|
});
|
|
@@ -712,6 +781,35 @@ export function parseAdminOperation(options) {
|
|
|
712
781
|
"comment reply targets a comment: lumine admin comment reply comment:<id>.",
|
|
713
782
|
);
|
|
714
783
|
}
|
|
784
|
+
const reviewedBuildVersionId = options.adminReviewedBuildVersion
|
|
785
|
+
? parseRequiredInteger(
|
|
786
|
+
options.adminReviewedBuildVersion,
|
|
787
|
+
"--reviewed-version",
|
|
788
|
+
1,
|
|
789
|
+
)
|
|
790
|
+
: undefined;
|
|
791
|
+
const buildReviewMethod = options.adminBuildReviewMethod
|
|
792
|
+
? parseAdminBuildReviewMethod(options.adminBuildReviewMethod)
|
|
793
|
+
: undefined;
|
|
794
|
+
if (parsedTarget.type === "build") {
|
|
795
|
+
if (!options.adminFile) {
|
|
796
|
+
throw cliValidationError(
|
|
797
|
+
"Build comments are management-agent composed only; pass --file <comment.md> after reviewing the project.",
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
if (!reviewedBuildVersionId || !buildReviewMethod) {
|
|
801
|
+
throw cliValidationError(
|
|
802
|
+
"After reviewing the project, pass both --reviewed-version <published-artifact-id> and --reviewed-via runtime|code.",
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
} else if (
|
|
806
|
+
parsedTarget.type !== "comment" &&
|
|
807
|
+
(reviewedBuildVersionId || buildReviewMethod)
|
|
808
|
+
) {
|
|
809
|
+
throw cliValidationError(
|
|
810
|
+
"Build review evidence applies only to build:<id> or a comment:<id> inside a Build.",
|
|
811
|
+
);
|
|
812
|
+
}
|
|
715
813
|
return writeOperation(
|
|
716
814
|
"comment.draft",
|
|
717
815
|
"POST",
|
|
@@ -725,6 +823,8 @@ export function parseAdminOperation(options) {
|
|
|
725
823
|
...(options.adminFile
|
|
726
824
|
? { content: readComposedCommentFile(options.adminFile) }
|
|
727
825
|
: {}),
|
|
826
|
+
...(reviewedBuildVersionId ? { reviewedBuildVersionId } : {}),
|
|
827
|
+
...(buildReviewMethod ? { buildReviewMethod } : {}),
|
|
728
828
|
},
|
|
729
829
|
);
|
|
730
830
|
}
|
|
@@ -768,7 +868,7 @@ export function parseAdminOperation(options) {
|
|
|
768
868
|
}
|
|
769
869
|
|
|
770
870
|
throw cliValidationError(
|
|
771
|
-
"Usage: lumine admin identity|daily-run|recommendations|post|subjects|subject|featured|comment|chat|news|audit|brief|bot-output|notable ...",
|
|
871
|
+
"Usage: lumine admin identity|daily-run|recommendations|builds|post|subjects|subject|featured|comment|chat|news|audit|brief|bot-output|notable ...",
|
|
772
872
|
);
|
|
773
873
|
}
|
|
774
874
|
|
|
@@ -947,6 +1047,50 @@ export function parseRecommendationTarget({ target, explicitType = "" }) {
|
|
|
947
1047
|
return { type, id };
|
|
948
1048
|
}
|
|
949
1049
|
|
|
1050
|
+
export function parseAdminCommentTarget({ target, explicitType = "" }) {
|
|
1051
|
+
const normalized = String(target || "").trim();
|
|
1052
|
+
const prefixed = normalized.match(
|
|
1053
|
+
/^(subject|comment|build|aistory|dailyreflection):(\d+)$/i,
|
|
1054
|
+
);
|
|
1055
|
+
const buildUrl = normalized.match(/\/(?:app|build)\/(\d+)(?:[/?#]|$)/i);
|
|
1056
|
+
const baseTarget = parseRecommendationTarget({
|
|
1057
|
+
target:
|
|
1058
|
+
prefixed?.[1]?.toLowerCase() === "build" || buildUrl
|
|
1059
|
+
? `subject:${prefixed?.[2] || buildUrl?.[1]}`
|
|
1060
|
+
: normalized,
|
|
1061
|
+
explicitType:
|
|
1062
|
+
String(explicitType || "").toLowerCase() === "build"
|
|
1063
|
+
? "subject"
|
|
1064
|
+
: explicitType,
|
|
1065
|
+
});
|
|
1066
|
+
const inferredBuild = prefixed?.[1]?.toLowerCase() === "build" || !!buildUrl;
|
|
1067
|
+
const explicitBuild = String(explicitType || "").toLowerCase() === "build";
|
|
1068
|
+
if (explicitType && !explicitBuild && inferredBuild) {
|
|
1069
|
+
throw cliValidationError(
|
|
1070
|
+
"The target and --type identify different content types.",
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
if (explicitBuild && !inferredBuild && !/^\d+$/.test(normalized)) {
|
|
1074
|
+
throw cliValidationError(
|
|
1075
|
+
"The target and --type identify different content types.",
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
if (inferredBuild || explicitBuild) {
|
|
1079
|
+
return { type: "build", id: baseTarget.id };
|
|
1080
|
+
}
|
|
1081
|
+
return baseTarget;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function parseAdminBuildReviewMethod(value) {
|
|
1085
|
+
const normalized = String(value || "")
|
|
1086
|
+
.trim()
|
|
1087
|
+
.toLowerCase();
|
|
1088
|
+
if (normalized !== "runtime" && normalized !== "code") {
|
|
1089
|
+
throw cliValidationError("--reviewed-via must be runtime or code.");
|
|
1090
|
+
}
|
|
1091
|
+
return normalized;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
950
1094
|
function normalizeRecommendationTargetType(value) {
|
|
951
1095
|
const normalized = String(value || "")
|
|
952
1096
|
.trim()
|
package/lib/commands.js
CHANGED
|
@@ -2194,6 +2194,10 @@ export function parseArgs(args) {
|
|
|
2194
2194
|
adminEditionId: raw.editionId ? String(raw.editionId) : "",
|
|
2195
2195
|
adminLeaseToken: raw.leaseToken ? String(raw.leaseToken) : "",
|
|
2196
2196
|
adminFile: raw.file ? String(raw.file) : "",
|
|
2197
|
+
adminReviewedBuildVersion: raw.reviewedVersion
|
|
2198
|
+
? String(raw.reviewedVersion)
|
|
2199
|
+
: "",
|
|
2200
|
+
adminBuildReviewMethod: raw.reviewedVia ? String(raw.reviewedVia) : "",
|
|
2197
2201
|
adminFull: parseBoolean(raw.full, false),
|
|
2198
2202
|
rewardTwinkles: raw.rewardTwinkles ? String(raw.rewardTwinkles) : "",
|
|
2199
2203
|
includeComments: parseBoolean(raw.includeComments, false),
|
|
@@ -2511,9 +2515,11 @@ export function printHelp() {
|
|
|
2511
2515
|
lumine admin identity list|status|use <zero|ciel|auto> [--json]
|
|
2512
2516
|
lumine admin ai-bucket get --bucket-id <id> [--json]
|
|
2513
2517
|
lumine admin ai-bucket accounts add --bucket-id <id> --user-ids <id,id,...> [--note <text>] [--json]
|
|
2518
|
+
lumine admin ai-bucket note set --bucket-id <id> --note <text> [--json]
|
|
2514
2519
|
lumine admin daily-run start [--identity zero|ciel|auto] [--comment-mode off|draft|post] [--run-key <key>] [--json]
|
|
2515
2520
|
lumine admin daily-run status|complete|fail [--reason <text>] [--json]
|
|
2516
2521
|
lumine admin recommendations list [--content-types comment,dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
|
|
2522
|
+
lumine admin builds candidates [--cursor <cursor>] [--limit <number>] [--json]
|
|
2517
2523
|
lumine admin subjects candidates [--after <date>] [--effort unassigned] [--unviewed|--viewed] [--cursor <cursor>] [--json]
|
|
2518
2524
|
lumine admin subject get|reveal <subject-url-or-id> [--json]
|
|
2519
2525
|
lumine admin subject comments <subject-url-or-id> [--unviewed|--viewed] [--cursor <cursor>] [--json]
|
|
@@ -2527,8 +2533,8 @@ export function printHelp() {
|
|
|
2527
2533
|
lumine admin post recommend <target> [--type subject|comment|aiStory|dailyReflection] [--anyone-can-reward] [--reward-twinkles 3] [--json]
|
|
2528
2534
|
lumine admin post skip <target> [--type comment|aiStory|dailyReflection] [--reason <text>] [--json]
|
|
2529
2535
|
lumine admin post reward <target> [--type subject|comment|aiStory|dailyReflection] --twinkles 3 [--json]
|
|
2530
|
-
lumine admin comment draft <target> [--type subject|comment|aiStory|dailyReflection] [--identity zero|ciel|auto] [--json]
|
|
2531
|
-
lumine admin comment reply comment:<id> [--identity zero|ciel|auto] [--json]
|
|
2536
|
+
lumine admin comment draft <target> [--type subject|comment|build|aiStory|dailyReflection] [--file <comment.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--identity zero|ciel|auto] [--json]
|
|
2537
|
+
lumine admin comment reply comment:<id> [--file <reply.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--identity zero|ciel|auto] [--json]
|
|
2532
2538
|
lumine admin comment post --draft-id <id> [--json]
|
|
2533
2539
|
lumine admin comment edit <comment-id> --file <comment.md> [--json]
|
|
2534
2540
|
lumine admin brief [--days <1..30>] [--json]
|
|
@@ -2597,7 +2603,7 @@ Options:
|
|
|
2597
2603
|
--description <text> Build description for new/describe
|
|
2598
2604
|
--no-description Skip New description or clear with describe
|
|
2599
2605
|
--summary <text> Save summary
|
|
2600
|
-
--note <text>
|
|
2606
|
+
--note <text> Suggestion, notable-user, or AI-bucket context
|
|
2601
2607
|
--cursor <id> Continue an owner suggestion inbox listing
|
|
2602
2608
|
--after <date> Admin subjects: inclusive Unix/ISO creation boundary
|
|
2603
2609
|
--effort unassigned Admin subjects: show only unassigned effort
|
|
@@ -2611,13 +2617,15 @@ Options:
|
|
|
2611
2617
|
--subject-ids <ids> Complete ordered Featured subject IDs
|
|
2612
2618
|
--bucket-id <id> Unbanned AI identity bucket for account consolidation
|
|
2613
2619
|
--user-ids <ids> Explicit user IDs for an AI bucket batch (up to 500)
|
|
2614
|
-
--type <type> Admin target: subject, comment, aiStory, or dailyReflection
|
|
2620
|
+
--type <type> Admin target: subject, comment, build, aiStory, or dailyReflection
|
|
2615
2621
|
--kind recommend Admin recommendation queue kind
|
|
2616
2622
|
--anyone-can-reward Enable canonical reward eligibility
|
|
2617
2623
|
--reward-twinkles 3 Pair a recommendation with exactly 3 Twinkles
|
|
2618
2624
|
--twinkles 3 Give exactly 3 Twinkles through the normal economy
|
|
2619
2625
|
--draft-id <id> Canonical delegated comment draft ID
|
|
2620
2626
|
--file <path> Editorial JSON or composed comment text file
|
|
2627
|
+
--reviewed-version <id> Published Build artifact version actually reviewed
|
|
2628
|
+
--reviewed-via <method> Build review method: runtime or code
|
|
2621
2629
|
--reason <text> Reason when marking an admin run failed
|
|
2622
2630
|
--force Overwrite server files even if this workspace is stale or missing filesHash
|
|
2623
2631
|
--search <text> Search public open-source Builds
|
package/package.json
CHANGED
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -59,6 +59,8 @@ lumine admin ai-bucket get --bucket-id 10 --json
|
|
|
59
59
|
lumine admin ai-bucket accounts add --bucket-id 10 \
|
|
60
60
|
--user-ids 3127,13037,15410,16288 \
|
|
61
61
|
--note "operator-confirmed account family" --json
|
|
62
|
+
lumine admin ai-bucket note set --bucket-id 10 \
|
|
63
|
+
--note "Quota accounting only; not a moderation flag." --json
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
`accounts add` accepts 1-500 unique positive user IDs, preflights the complete
|
|
@@ -67,6 +69,10 @@ re-attributes current-day AI usage, and returns the canonical bucket members.
|
|
|
67
69
|
It is idempotent to retry. The API records the real operator in the private
|
|
68
70
|
Lumine audit log; no public bot identity is involved.
|
|
69
71
|
|
|
72
|
+
`note set` records up to 255 characters of private operational context on the
|
|
73
|
+
canonical bucket. Use it to distinguish quota bookkeeping from moderation;
|
|
74
|
+
the note itself changes no access, ban, or identity rules.
|
|
75
|
+
|
|
70
76
|
This surface intentionally accepts only an existing **unbanned** bucket. It
|
|
71
77
|
cannot ban accounts, block signup, add IP/device/risk-key rules, or infer an
|
|
72
78
|
account family. Identification remains a human/LLM evidence judgment and must
|
|
@@ -484,6 +490,7 @@ lumine admin subjects candidates --after 2026-08-01T00:00:00Z \
|
|
|
484
490
|
--cursor '<cursor>' --json
|
|
485
491
|
lumine admin subjects candidates --effort unassigned --json
|
|
486
492
|
lumine admin subjects candidates --unviewed --json
|
|
493
|
+
lumine admin builds candidates --cursor '<cursor>' --limit 50 --json
|
|
487
494
|
```
|
|
488
495
|
|
|
489
496
|
Schemas:
|
|
@@ -529,6 +536,29 @@ type SubjectCandidates = Success<{
|
|
|
529
536
|
subjects: Subject[];
|
|
530
537
|
pagination: Pagination & { scannedCount: number };
|
|
531
538
|
}>;
|
|
539
|
+
|
|
540
|
+
type BuildCandidates = Success<{
|
|
541
|
+
builds: Array<{
|
|
542
|
+
id: number;
|
|
543
|
+
title: string | null;
|
|
544
|
+
description: string | null;
|
|
545
|
+
username: string | null;
|
|
546
|
+
publishedAt: number | null;
|
|
547
|
+
publishedArtifactVersionId: number | null;
|
|
548
|
+
collaborationMode: "private" | "open_source";
|
|
549
|
+
url: string;
|
|
550
|
+
review: {
|
|
551
|
+
publishedArtifactVersionId: number | null;
|
|
552
|
+
codePullAvailable: boolean;
|
|
553
|
+
requiredBeforeComment: true;
|
|
554
|
+
};
|
|
555
|
+
}>;
|
|
556
|
+
pagination: {
|
|
557
|
+
nextCursor: string | null;
|
|
558
|
+
hasMore: boolean;
|
|
559
|
+
exhausted: boolean;
|
|
560
|
+
};
|
|
561
|
+
}>;
|
|
532
562
|
```
|
|
533
563
|
|
|
534
564
|
Both cursors freeze a primary-key high-water mark and traverse descending IDs,
|
|
@@ -538,6 +568,24 @@ filters, so a page — recommendation or subject — can be empty while `hasMore
|
|
|
538
568
|
remains true; continue until `exhausted`. Subject `--after` is inclusive, and
|
|
539
569
|
the opaque cursor is bound to its original date and effort filters.
|
|
540
570
|
|
|
571
|
+
`builds candidates` is a management-agent discovery view over the canonical
|
|
572
|
+
public Build browser, ordered by the current published release. It is
|
|
573
|
+
available through the `admin` namespace only while a delegated run is active;
|
|
574
|
+
page until `pagination.exhausted`. Each item includes its canonical app URL,
|
|
575
|
+
published artifact version, and whether its code is pullable. This list does
|
|
576
|
+
not decide that an app deserves a comment. The management agent must open and
|
|
577
|
+
genuinely try the published runtime, or pull and read an open-source project,
|
|
578
|
+
before making that judgment. Direct API/persona automation is never a review
|
|
579
|
+
substitute.
|
|
580
|
+
|
|
581
|
+
During every management run, scan recent Build candidates back through the
|
|
582
|
+
run's review window alongside Subjects and the recommendation queue. An app
|
|
583
|
+
that is thin, broken, private, unchanged since a prior substantive bot
|
|
584
|
+
comment, or not meaningfully understood may be left alone. A new or materially
|
|
585
|
+
updated app where specific, truthful feedback would help is comment-worthy.
|
|
586
|
+
This is editorial attention, not a quota: do not manufacture a Build comment
|
|
587
|
+
just to prove the queue was visited.
|
|
588
|
+
|
|
541
589
|
`--content-types` is sent to APIs that support server-side filtering so excluded
|
|
542
590
|
types do not run their eligibility/content queries. The local CLI also filters
|
|
543
591
|
the returned page defensively for deployment compatibility. The server cursor
|
|
@@ -1653,7 +1701,7 @@ from memory:
|
|
|
1653
1701
|
decisions are yours to make and record with `post skip` or in the run
|
|
1654
1702
|
report).
|
|
1655
1703
|
|
|
1656
|
-
**Lumine Build app posts are composed-only, and only after actually looking
|
|
1704
|
+
**Lumine Build apps and app posts are composed-only, and only after actually looking
|
|
1657
1705
|
(Mikey's direction, 2026-08-10).** When a post is about a Build app — the
|
|
1658
1706
|
author shares their app, announces an update, or asks for feedback on their
|
|
1659
1707
|
build — never use the server-generated draft path: the API persona cannot
|
|
@@ -1671,6 +1719,29 @@ tried it — ask the author about it instead. This is the standing rule for
|
|
|
1671
1719
|
every composed comment, applied to apps: never claim an experience the
|
|
1672
1720
|
session did not actually have.
|
|
1673
1721
|
|
|
1722
|
+
The same rule covers comments placed **directly on a Build app**. This is
|
|
1723
|
+
deliberately management-agent-only: no server-generated draft and no pure API
|
|
1724
|
+
persona may author one. After reviewing the project, bind the composed comment
|
|
1725
|
+
to the exact published artifact you saw:
|
|
1726
|
+
|
|
1727
|
+
```bash
|
|
1728
|
+
lumine admin comment draft build:884 --file comment.md \
|
|
1729
|
+
--reviewed-version 4512 --reviewed-via runtime --json
|
|
1730
|
+
lumine admin comment post --draft-id 77 --json
|
|
1731
|
+
```
|
|
1732
|
+
|
|
1733
|
+
Use `--reviewed-via code` only when you actually pulled and read the project;
|
|
1734
|
+
`runtime` means you opened and tried the published app. Replies to human
|
|
1735
|
+
comments inside a Build use `comment:<id>` plus the same review flags. The API
|
|
1736
|
+
rejects missing review evidence, a server-generated Build draft, a mismatched
|
|
1737
|
+
published version, a private/noncanonical Build, or any Build/comment-context
|
|
1738
|
+
change between draft and publication. A changed version means review the new
|
|
1739
|
+
project state and compose again. The flags are an auditable statement of what
|
|
1740
|
+
the management agent did, not permission to infer experience from metadata.
|
|
1741
|
+
Autonomous mention/reply generation and sponsored AI replies are disabled in
|
|
1742
|
+
Build threads. The generic `comment edit` shortcut is also disabled there;
|
|
1743
|
+
review the current version and post a version-bound correction reply instead.
|
|
1744
|
+
|
|
1674
1745
|
**Offer a Lumine prompt when the moment invites it (Mikey's direction,
|
|
1675
1746
|
2026-08-10).** Zero and Ciel may include one concrete, copy-pasteable Lumine
|
|
1676
1747
|
prompt in a comment or reply — a genuinely powerful one, tailored to what the
|
|
@@ -1710,15 +1781,18 @@ containers, and publication applies to both kinds of draft.
|
|
|
1710
1781
|
A draft targets one of:
|
|
1711
1782
|
|
|
1712
1783
|
- `subject:<id>` (or a bare numeric ID) — a top-level comment on the subject;
|
|
1784
|
+
- `build:<id>` — a top-level comment on a public canonical Build, composed
|
|
1785
|
+
after reviewing its exact published version;
|
|
1713
1786
|
- `aiStory:<id>` / `dailyReflection:<id>` — a top-level comment on the
|
|
1714
1787
|
standalone post;
|
|
1715
1788
|
- `comment:<id>` — a public reply to that specific comment. `comment reply`
|
|
1716
1789
|
is the same operation and requires a comment target.
|
|
1717
1790
|
|
|
1718
1791
|
A reply's container resolves canonically from the target comment: its subject,
|
|
1719
|
-
or
|
|
1720
|
-
rejected with `CLI_ADMIN_UNSUPPORTED_REPLY_ROOT`.
|
|
1721
|
-
|
|
1792
|
+
Build, or AI Story / Daily Reflection root. Comments under any other root are
|
|
1793
|
+
rejected with `CLI_ADMIN_UNSUPPORTED_REPLY_ROOT`. Build replies require the
|
|
1794
|
+
same exact-version review evidence as top-level Build comments. Replies to
|
|
1795
|
+
Zero/Ciel comments and to notification comments are rejected with
|
|
1722
1796
|
`CLI_ADMIN_INVALID_REPLY_TARGET` — the bots never thread with themselves or
|
|
1723
1797
|
each other, and a human's later reply to a delegated comment still enters the
|
|
1724
1798
|
existing autonomous comment-assistant pipeline. Published replies carry the
|
|
@@ -1730,7 +1804,7 @@ type CommentDraft = Success<{
|
|
|
1730
1804
|
draft: {
|
|
1731
1805
|
id: number;
|
|
1732
1806
|
runId: number;
|
|
1733
|
-
targetType: "subject" | "comment" | "aiStory" | "dailyReflection";
|
|
1807
|
+
targetType: "subject" | "comment" | "build" | "aiStory" | "dailyReflection";
|
|
1734
1808
|
targetId: number;
|
|
1735
1809
|
targetUrl: string;
|
|
1736
1810
|
subjectId: number | null; // container subject; null for standalone posts
|
|
@@ -1761,7 +1835,8 @@ type CommentPost = CommentGet & {
|
|
|
1761
1835
|
};
|
|
1762
1836
|
published: {
|
|
1763
1837
|
commentId: number;
|
|
1764
|
-
targetType:
|
|
1838
|
+
targetType:
|
|
1839
|
+
"subject" | "comment" | "build" | "aiStory" | "dailyReflection";
|
|
1765
1840
|
targetId: number;
|
|
1766
1841
|
subjectId: number | null;
|
|
1767
1842
|
subjectUrl: string | null;
|
|
@@ -1772,12 +1847,13 @@ type CommentPost = CommentGet & {
|
|
|
1772
1847
|
};
|
|
1773
1848
|
```
|
|
1774
1849
|
|
|
1775
|
-
|
|
1776
|
-
complete visible comment context, then invokes the existing exact
|
|
1777
|
-
system prompt through the shared response assembler with a
|
|
1778
|
-
decision policy (comment vs reply). The raw prompt is never
|
|
1779
|
-
audited. The model—not regexes or keyword rules—chooses `draft`
|
|
1780
|
-
under the run policy.
|
|
1850
|
+
For Subjects and standalone posts, the server loads the canonical container
|
|
1851
|
+
and its complete visible comment context, then invokes the existing exact
|
|
1852
|
+
Zero/Ciel system prompt through the shared response assembler with a
|
|
1853
|
+
mode-specific decision policy (comment vs reply). The raw prompt is never
|
|
1854
|
+
returned or audited. The model—not regexes or keyword rules—chooses `draft`
|
|
1855
|
+
or `skip` under the run policy. Build comments never enter that generated
|
|
1856
|
+
path; they require management-agent-composed content and review evidence.
|
|
1781
1857
|
|
|
1782
1858
|
Draft IDs are bound to operator, run, public bot, target, comment mode,
|
|
1783
1859
|
context revision, persona revision, expiry, and idempotency key. The context
|