@stage5/lumine 0.2.27 → 0.2.29
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 +1 -0
- package/lib/admin.js +25 -1
- package/lib/commands.js +1 -0
- package/package.json +1 -1
- package/sdk/LUMINE_ADMIN.md +78 -23
package/README.md
CHANGED
|
@@ -181,6 +181,7 @@ lumine admin subject feature 123 --json
|
|
|
181
181
|
lumine admin subject unfeature 123 --json
|
|
182
182
|
lumine admin featured reorder --subject-ids 30,20,10 --json
|
|
183
183
|
lumine admin brief --days 3 --json
|
|
184
|
+
lumine admin notable add Minecrarft_guy --json
|
|
184
185
|
lumine admin post recommend comment:456 --anyone-can-reward --reward-twinkles 3 --json
|
|
185
186
|
lumine admin post reward comment:456 --twinkles 3 --json
|
|
186
187
|
lumine admin daily-run complete --json
|
package/lib/admin.js
CHANGED
|
@@ -585,6 +585,24 @@ export function parseAdminOperation(options) {
|
|
|
585
585
|
);
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
+
if (namespace === "notable" && action === "add") {
|
|
589
|
+
const rawTarget = String(target || "").trim();
|
|
590
|
+
if (!rawTarget) {
|
|
591
|
+
throw cliValidationError(
|
|
592
|
+
"Usage: lumine admin notable add <userId|username>.",
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
const body = /^\d+$/.test(rawTarget)
|
|
596
|
+
? { userId: parseRequiredInteger(rawTarget, "user ID", 1) }
|
|
597
|
+
: { username: rawTarget };
|
|
598
|
+
return writeOperation(
|
|
599
|
+
"notable.add",
|
|
600
|
+
"POST",
|
|
601
|
+
"/cli/admin/notable-users",
|
|
602
|
+
body,
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
|
|
588
606
|
if (namespace === "brief" && !action) {
|
|
589
607
|
if (options.adminDays) {
|
|
590
608
|
const days = Number(options.adminDays);
|
|
@@ -683,7 +701,7 @@ export function parseAdminOperation(options) {
|
|
|
683
701
|
}
|
|
684
702
|
|
|
685
703
|
throw cliValidationError(
|
|
686
|
-
"Usage: lumine admin identity|daily-run|recommendations|post|subjects|subject|featured|comment|news|audit|brief ...",
|
|
704
|
+
"Usage: lumine admin identity|daily-run|recommendations|post|subjects|subject|featured|comment|news|audit|brief|notable ...",
|
|
687
705
|
);
|
|
688
706
|
}
|
|
689
707
|
|
|
@@ -1088,6 +1106,12 @@ function printAdminResult({ operation, result }) {
|
|
|
1088
1106
|
}
|
|
1089
1107
|
return;
|
|
1090
1108
|
}
|
|
1109
|
+
if (data.notableUser) {
|
|
1110
|
+
console.log(
|
|
1111
|
+
`${result.status || "success"}: ${data.notableUser.username || "unknown"} (#${data.notableUser.userId}).`,
|
|
1112
|
+
);
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1091
1115
|
if (data.skip) {
|
|
1092
1116
|
console.log(
|
|
1093
1117
|
`${result.status}: ${data.skip.contentType}:${data.skip.contentId} skipped.`,
|
package/lib/commands.js
CHANGED
|
@@ -2528,6 +2528,7 @@ export function printHelp() {
|
|
|
2528
2528
|
lumine admin comment post --draft-id <id> [--json]
|
|
2529
2529
|
lumine admin comment edit <comment-id> --file <comment.md> [--json]
|
|
2530
2530
|
lumine admin brief [--days <1..30>] [--json]
|
|
2531
|
+
lumine admin notable add <user-id|username> [--json]
|
|
2531
2532
|
lumine admin audit [list] [--run current|last|<run-id>] [--target <target>] [--actions <a,b>] [--full] [--cursor <cursor>] [--json]
|
|
2532
2533
|
|
|
2533
2534
|
Examples:
|
package/package.json
CHANGED
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -139,6 +139,17 @@ Escalate, with the canonical `https://www.twin-kle.com/subjects/<id>` or
|
|
|
139
139
|
pay-me-to-win contests, and anything that teaches other children a method for
|
|
140
140
|
any of these. Note the recommendation count: a manipulation how-to that other
|
|
141
141
|
kids are recommending is spreading, and that is the urgent part.
|
|
142
|
+
- **AI-cost exploits** — patterns that convert free AI allowances into farmable
|
|
143
|
+
value: clusters of young accounts with heavy AI/battery usage, one person
|
|
144
|
+
operating many accounts that feed a single build through team branches,
|
|
145
|
+
plus-tagged or dot-variant email families (`kid+1@`, `k.id@`) behind multiple
|
|
146
|
+
active accounts, repeated first exchanges across accounts already linked by
|
|
147
|
+
independent evidence, or a rescue claim by an account created under 30 days
|
|
148
|
+
ago (the API maturity gate should make that last case impossible). A new
|
|
149
|
+
member's one first exchange is intended onboarding and is not suspicious by
|
|
150
|
+
itself. The daily battery is real provider money; treat farming signatures
|
|
151
|
+
with the same seriousness as coin farming. Escalate the account list and
|
|
152
|
+
evidence; never auto-enforce.
|
|
142
153
|
- **Bug reports** the run encountered, even secondhand in a comment thread.
|
|
143
154
|
|
|
144
155
|
Two rules that keep the list worth reading:
|
|
@@ -1041,6 +1052,8 @@ type NewsSubmit = NewsStatus; // "success"; newspaper includes revisionNumber
|
|
|
1041
1052
|
```bash
|
|
1042
1053
|
lumine admin brief --json
|
|
1043
1054
|
lumine admin brief --days 3 --json
|
|
1055
|
+
lumine admin notable add 12647 --json
|
|
1056
|
+
lumine admin notable add Minecrarft_guy --json
|
|
1044
1057
|
```
|
|
1045
1058
|
|
|
1046
1059
|
Read-only management insights for the delegated workflow, windowed since the
|
|
@@ -1066,21 +1079,44 @@ Four sections (Mikey's chosen cut, 2026-08-10):
|
|
|
1066
1079
|
report period can begin up to one day before or after the exact brief window,
|
|
1067
1080
|
so use those bounds when describing it. Flag accounts that jumped tiers or
|
|
1068
1081
|
dominate that report period. May be `{ unavailable: true }` if the cost
|
|
1069
|
-
report fails; say so rather than guessing.
|
|
1082
|
+
report fails; say so rather than guessing. This section is also the run's
|
|
1083
|
+
AI-cost exploit watch: while reading it, actively look for the signatures the
|
|
1084
|
+
brief actually exposes — one risk group spanning several user IDs, repeated
|
|
1085
|
+
plus-tag or dot-variant email families among top accounts, or heavy spend by
|
|
1086
|
+
accounts that `economy.topGainers` or `notableCandidates` independently marks
|
|
1087
|
+
as recent signups. Cross-check those signals against the escalation
|
|
1088
|
+
categories. Missing join-date or community data is unknown, not evidence that
|
|
1089
|
+
an account is young or empty. A run that reads the spending report without
|
|
1090
|
+
asking "could any of this be one person with many accounts?" has skipped a
|
|
1091
|
+
duty.
|
|
1070
1092
|
- `notableCandidates` — kids (never bots, staff `userType`s, or users already
|
|
1071
1093
|
on the Notable Users list) ranked by authored activity in the window, with
|
|
1072
1094
|
`isNewUser` marking window-new signups. Use it to find the overlooked and
|
|
1073
1095
|
rising users the editorial priorities exist for, and propose additions to
|
|
1074
|
-
Mikey's Notable Users list in the report
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1096
|
+
Mikey's Notable Users list in the report. When Mikey approves additions,
|
|
1097
|
+
execute them with `lumine admin notable add <userId|username>` (idempotent —
|
|
1098
|
+
an existing member returns `already_done`; requires the `notable:write`
|
|
1099
|
+
scope, audited as `notable.add`, and writes through the management page's
|
|
1100
|
+
own canonical service). Without his approval the run only proposes.
|
|
1101
|
+
- `teachers` — the mentor/sage achievement holders (the accounts the website
|
|
1102
|
+
titles teacher/headteacher): real classroom teachers, NOT the
|
|
1103
|
+
`userType='supermod'` Korean operations staff, whose work-only usage is
|
|
1104
|
+
expected and deliberately excluded. Mikey's standing question here: which
|
|
1105
|
+
teachers genuinely use the website for themselves and which only work
|
|
1106
|
+
through it. Recommendations and rewards are classroom "work" verbs and
|
|
1107
|
+
count for nothing toward interest; genuine personal interest is measured by
|
|
1108
|
+
what a teacher does for themselves — authored subjects/comments,
|
|
1109
|
+
`reflections` (Daily Reflections answered), `dailyTasksCompleted`,
|
|
1110
|
+
`wordlePlays`, `buildsTouched` (Lumine builds they own that changed in the
|
|
1111
|
+
window), `aiStories`, and bounded `xpEvents` (XP-ledger activity). Shape:
|
|
1112
|
+
`genuinelyInterested` (interestScore > 0, ordered by it, each row carrying
|
|
1113
|
+
all the per-window counters plus `rank: mentor|sage` and `workScore`),
|
|
1114
|
+
`workOnly` (classroom verbs only, zero personal signals), `activeButSilent`
|
|
1115
|
+
(window-active log-ins with nothing at all, capped at 40), and `totals`.
|
|
1116
|
+
Daily-task counts use canonical whole-day indices and can begin up to one
|
|
1117
|
+
calendar day before the exact `window.sinceTs`.
|
|
1118
|
+
Report the contrast between the buckets, and treat `genuinelyInterested` as
|
|
1119
|
+
notable-users-but-for-teachers.
|
|
1084
1120
|
|
|
1085
1121
|
The command needs only an active run's `content:read` scope and mutates
|
|
1086
1122
|
nothing; reading the brief is not audited content action. Window boundaries
|
|
@@ -1089,6 +1125,27 @@ on the big append-only ledgers are found by binary-searching the PRIMARY key
|
|
|
1089
1125
|
is still bounded to the selected 1–30 day window.
|
|
1090
1126
|
|
|
1091
1127
|
```ts
|
|
1128
|
+
type TeacherInsight = {
|
|
1129
|
+
userId: number;
|
|
1130
|
+
username: string | null;
|
|
1131
|
+
rank: 'mentor' | 'sage';
|
|
1132
|
+
lastActive: number | null;
|
|
1133
|
+
daysSinceActive: number | null;
|
|
1134
|
+
subjectsPosted: number;
|
|
1135
|
+
commentsPosted: number;
|
|
1136
|
+
reflections: number;
|
|
1137
|
+
dailyTasksCompleted: number;
|
|
1138
|
+
wordlePlays: number;
|
|
1139
|
+
buildsTouched: number;
|
|
1140
|
+
aiStories: number;
|
|
1141
|
+
xpEvents: number;
|
|
1142
|
+
recommendationsGiven: number;
|
|
1143
|
+
rewardsGiven: number;
|
|
1144
|
+
rewardTwinklesGiven: number;
|
|
1145
|
+
interestScore: number;
|
|
1146
|
+
workScore: number;
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1092
1149
|
type InsightsBrief = Success<{
|
|
1093
1150
|
window: {
|
|
1094
1151
|
sinceTs: number;
|
|
@@ -1124,18 +1181,16 @@ type InsightsBrief = Success<{
|
|
|
1124
1181
|
isNewUser: boolean;
|
|
1125
1182
|
lastActive: number | null;
|
|
1126
1183
|
}>;
|
|
1127
|
-
teachers:
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
engagementScore: number;
|
|
1138
|
-
}>;
|
|
1184
|
+
teachers: {
|
|
1185
|
+
genuinelyInterested: TeacherInsight[];
|
|
1186
|
+
workOnly: TeacherInsight[];
|
|
1187
|
+
activeButSilent: TeacherInsight[];
|
|
1188
|
+
totals: {
|
|
1189
|
+
total: number;
|
|
1190
|
+
activeInWindow: number;
|
|
1191
|
+
interestedInWindow: number;
|
|
1192
|
+
};
|
|
1193
|
+
};
|
|
1139
1194
|
aiSpending:
|
|
1140
1195
|
| {
|
|
1141
1196
|
days: number;
|