@stage5/lumine 0.2.67 → 0.2.68

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.
@@ -23,6 +23,11 @@ canonical structured data.
23
23
  carry-over work, or final full-run report. Every run-scoped CLI command loads
24
24
  the canonical active run and sends its ID; the API rejects a missing,
25
25
  expired, scope-mismatched, or actor-mismatched run.
26
+ - `--scope newspaper` is a newspaper-only authorization envelope. It grants
27
+ newspaper status/claim/submit/print and completion only, with comment mode
28
+ `off`. It cannot inspect queues, conduct, logs, Builds, or Featured.
29
+ Completion does not advance full-review windows or carry-over telemetry.
30
+ Its distinct `/daily-runs/start/newspaper` endpoint fails closed on older APIs.
26
31
  - The public content actor is Zero or Ciel. Mikey's operator ID is retained in
27
32
  private audit rows and is not embedded in public comment metadata.
28
33
  - Delegated HTTP work never authenticates as the bot, opens a bot socket, changes
@@ -44,6 +49,13 @@ canonical structured data.
44
49
  described below. The human's normal AI Energy and sponsor path applies;
45
50
  Lumine does not need to remain running.
46
51
 
52
+ `--output <file.json>` saves the canonical JSON result for ordinary admin
53
+ commands, whether or not `--json` is also used. Files are atomically replaced
54
+ with mode `0600`. Paginated scans keep their existing streaming-to-file path;
55
+ `news claim` keeps its claim/scaffold contract. If saving fails after a server
56
+ mutation, the structured error includes `canonicalResult`: inspect it rather
57
+ than repeating a successful mutation to recover an output file.
58
+
47
59
  The Zero/Ciel shift is assigned by **Asia/Bangkok calendar day, not by run**.
48
60
  The schedule is anchored with 2026-08-31 assigned to Zero and alternates by
49
61
  elapsed Bangkok dates from there. Every automatic primary, supplemental,
@@ -64,8 +76,10 @@ Comment mode is stored only on the current run:
64
76
  - `draft`: server-generated drafts, no public comment.
65
77
  - `post`: drafts plus idempotent publication through the ordinary comment path.
66
78
 
67
- A Featured-only run always uses comment mode `off` and grants only Featured
68
- subject inspection, subject reveal, Featured mutation, and run completion. It can complete
79
+ A Featured-only run always uses comment mode `off` and grants Featured
80
+ subject inspection, subject reveal, Featured mutation, review-bound Featured
81
+ comment encouragement (`featured:comments`), and run completion. It does not
82
+ grant generic recommendation/reward authority or comment publication. It can complete
69
83
  without a sponsor-integrity scan. Completing it does not advance any full-run
70
84
  content/cost/conduct window, queue-coverage record, last-completed identity, or
71
85
  carry-over surfacing telemetry. Start one only when Mikey requested that slice; never turn a small
@@ -73,6 +87,14 @@ request into a full review merely because the technical command needs a run.
73
87
  The API enforces these scopes, and the CLI also rejects out-of-scope operations
74
88
  before calling endpoints outside the Lumine Admin router (notably Build review).
75
89
 
90
+ Featured capacity and delegated addition authority are separate policies:
91
+ the website editor supports 100 Subjects, while delegated additions are limited
92
+ to a board of 20. `maximum` remains the delegated limit for compatibility;
93
+ `maximumScope`, `delegatedMaximum`, and `websiteMaximum` label the distinction.
94
+ A board of 25 is not a website overflow or an instruction to remove five pins.
95
+ Equal-size replacements and complete-set reorders accept up to the website's
96
+ 100-Subject capacity without exercising delegated growth authority.
97
+
76
98
  ### Private AI-bucket maintenance
77
99
 
78
100
  AI identity buckets are private operator bookkeeping, not a Zero/Ciel public
@@ -238,7 +260,11 @@ in another language; reply naturally in concise English.
238
260
 
239
261
  **Twinkle is not Reddit.** Do not rank a run's attention by popularity,
240
262
  recommendation count, or polish. Most users here are young children, and the
241
- posts that most need Zero or Ciel are the ones nobody else answered.
263
+ posts that most need Zero or Ciel are the ones nobody else answered. These
264
+ outreach priorities do not replace the full daily Featured-comment review
265
+ below: active threads need encouragement too. Featured selection has its own
266
+ primary objective: invite genuine member-to-member engagement, not assemble
267
+ the most thought-provoking posts.
242
268
 
243
269
  - **Look first at new, quiet, and overlooked users.** A child's first post, or a
244
270
  post from someone who rarely gets replies, is worth more of a run's attention
@@ -250,10 +276,10 @@ posts that most need Zero or Ciel are the ones nobody else answered.
250
276
  - **Zero engagement is a reason to act, not to skip.** A post sitting at no
251
277
  recommendations and no comments is the strongest signal in the queue that
252
278
  someone should notice it.
253
- - **Thought-provoking posts deserve substance, not applause — and an unnoticed
254
- one is the highest priority of all.** When a child asks a real question or
255
- makes a real argument and the thread is empty, that is the clearest case for
256
- a Zero/Ciel comment on the whole site. Engage with the idea itself: answer it,
279
+ - **Thought-provoking posts deserve substantive replies.** When a child asks
280
+ a real question or makes a real argument and the thread is empty, it is a
281
+ strong case for a Zero/Ciel reply, not an automatic top Featured ranking.
282
+ Engage with the idea itself: answer it,
257
283
  add a perspective or a counter-consideration, and leave the author somewhere
258
284
  to go next. A good question that nobody answered teaches a child that thinking
259
285
  hard is not worth it; that is the outcome these runs exist to prevent. This
@@ -305,21 +331,45 @@ posts that most need Zero or Ciel are the ones nobody else answered.
305
331
  - **Sincere requests for personal help are Featured material.** Posts asking
306
332
  the community for advice about school, friendships, loneliness, or other
307
333
  ordinary real-life problems embody Twinkle's purpose; being personal is never
308
- a reason to suppress or remove them. Receiving meaningful support does not
309
- make one stale or create a duty to rotate it out; keep judging what the live
310
- board contributes now, and never use prior recognition as a removal proxy.
334
+ a reason to suppress them or judge them unsuitable. Receiving meaningful
335
+ support does not reduce their value. They still participate in the daily
336
+ Featured refresh below: rotating the spotlight is not withdrawing support,
337
+ and a good post does not require an indefinite pin.
311
338
  - **Speculative privacy is never an editorial signal.** Do not lower, remove,
312
339
  unfeature, or escalate content because it might identify someone, mentions a
313
340
  school, city, class, or ordinary location, or invites everyday community
314
341
  context. Those possibilities carry zero weight in Featured decisions. An
315
342
  actual sensitive disclosure or an author's explicit removal request follows
316
343
  the separate concrete-safety path; it does not make the post low-quality.
317
- - **Featured values participation, continuity, and child voice—not adult
318
- polish.** Accessible questions that many children can answer and ongoing
319
- personal series such as records, journals, or recurring updates are strong
320
- Featured forms. Age, brevity, simplicity, prior recognition, or a modest
321
- description is not a removal reason. Review the whole subject and its role in
322
- the community instead of grading its opening text like an essay.
344
+ - **Featured prioritizes engagement, participation, and child voice.** Choose
345
+ the recent eligible Subjects most likely to get members commenting on other
346
+ members' Subjects and responding to one another. Accessible questions,
347
+ everyday experiences, playful prompts, drawings, invitations, personal help,
348
+ and ongoing records or creative series can outperform a polished essay for
349
+ this purpose. Being thought-provoking is a bonus, not the primary ranking
350
+ criterion. Explain the concrete invitation to participate, using the full
351
+ Subject and thread as context; do not rank by adult polish, intellectual
352
+ depth, existing popularity, or raw recommendation counts. Genuine engagement
353
+ does not mean bait, spam, or reward farming. Age, brevity, simplicity, prior
354
+ recognition, or a modest description does not make a Subject low-quality.
355
+ Daily rotation is an independent editorial reason to refresh a good post's
356
+ slot; do not invent a defect to justify it.
357
+ - **Aim to replace all of yesterday's Featured Subjects each day.** During a
358
+ full daily management review, plan a complete refresh of the previous day's
359
+ board with recent, never-before-Featured Subjects, ordered by likely genuine
360
+ engagement. A small handful of swaps is not the default target. Use the
361
+ Bangkok calendar day, not the number of runs: do not churn pins newly added
362
+ today because a follow-up starts another session. Quality and eligibility
363
+ still apply. If there are too few eligible candidates, a current explicit
364
+ keep instruction, an unread thread, or another concrete constraint, explain
365
+ each retained pin and the shortfall; do not pad the list or silently settle
366
+ for a partial refresh. An earlier positive assessment is not a permanent
367
+ keep instruction. New installments can carry a series forward without
368
+ treating earlier ones as noise. This daily target changes editorial judgment,
369
+ not mutation authority: show the full proposed rotation and obtain Mikey's
370
+ go-ahead before removing or reordering any pins. One go-ahead for that exact
371
+ complete plan authorizes executing all its swaps, not just the first one;
372
+ carry it through and verify the final board without seeking per-item approval.
323
373
  - **A "new" Featured addition has two non-negotiable eligibility gates.** When
324
374
  Mikey asks for new Featured subjects, additions, or replacements, a candidate
325
375
  must both (1) have been posted recently and (2) have never appeared on the
@@ -336,7 +386,7 @@ posts that most need Zero or Ciel are the ones nobody else answered.
336
386
  - **The live Featured board is Mikey's word.** Do not remove or reorder a
337
387
  currently Featured subject without first showing Mikey the planned removals
338
388
  and replacements and getting his go-ahead. Additions have standing approval
339
- when a fresh `featured list` is below its canonical maximum: proactively
389
+ when a fresh `featured list` is below its delegated-admin maximum: proactively
340
390
  feature genuinely reviewed, editorially strong new subjects without asking
341
391
  case by case. This is judgment, not a quota — never add filler merely because
342
392
  capacity exists. If a subject that was Featured or pinned during an earlier
@@ -351,6 +401,89 @@ Sensitive disclosures, active disputes, and anything needing crisis or medical
351
401
  judgment remain out of scope for a bot comment no matter how neglected the post
352
402
  is. Those go to Mikey.
353
403
 
404
+ ### Daily Featured comments and refresh
405
+
406
+ This is a standing duty for every **full daily management review**, after the
407
+ newspaper duty. It is not an instruction to start or repeat a full run when
408
+ Mikey requests a small edit, proposal, or other scoped action. A request only
409
+ to discuss Featured candidates authorizes discussion, not recommendations or
410
+ pin changes. The technical `--scope featured` envelope permits the review-bound
411
+ comment workflow below only when encouragement is in Mikey's requested slice;
412
+ it never authorizes unrelated daily work or generic recommendation commands.
413
+
414
+ 1. **Read all comments on every current Featured Subject each day.** Start
415
+ from a fresh `featured list`, save the dated board, and inspect each full
416
+ Subject and all top-level comments and nested replies. Include old and
417
+ already-viewed comments, not just new ones, the recommendation queue, or a
418
+ sample of the thread. Review outgoing Subjects before their approved
419
+ rotation so their commenters are not missed; review any newly added
420
+ Subjects' threads too. Use `featured comments scan --checkpoint <file>` to
421
+ download every snapshot-bound page, then actually read every listed page
422
+ file before `featured comments acknowledge --checkpoint <file> --reviewed`.
423
+ Fetching does not acknowledge reading. A fresh scan after rotation covers
424
+ the incoming board. `commentsIncluded: false` or a locked secret is not
425
+ an empty thread: use the ordinary authorized reveal path, never bypass
426
+ secret semantics, and report any inaccessible or unfinished coverage.
427
+ Preserve the reviewed snapshot boundaries so "all" describes actual reads.
428
+ 2. **At least recommend most comments that are not genuinely worthless.**
429
+ The purpose is to encourage members to comment on other users' Subjects and
430
+ to give those contributions visibility. A sincere answer, friendly reaction,
431
+ relevant joke, question, attempt to help, or conversational follow-up is
432
+ usually enough; it need not be profound, long, polished, or Twinkle-worthy.
433
+ Read in context and lean toward encouragement. A one-line or emoji response
434
+ can be worthwhile; brevity or "nothing for the bot to add" is not a reason
435
+ to withhold a recommendation. Do not restrict recognition to a few standout
436
+ replies. Do not mechanically approve everything: genuine spam, meaningless
437
+ noise, harassment, or exploit promotion is not deserving merely because it
438
+ appears on Featured. System/view notifications and the bots' own comments
439
+ are context to read, not user participation to boost or count toward this
440
+ duty. Leave narrow concrete-safety cases for Mikey under the existing rules.
441
+ 3. **Separate encouragement from reward eligibility.** The ordinary action is
442
+ a selected item in `featured comments recommend --file <decisions.json>`,
443
+ omitting `anyoneCanReward` and `rewardTwinkles` (defaults: `false` and `0`).
444
+ Turn on the UI's "everyone can
445
+ reward" option (`anyoneCanReward: true`) only when the comment independently
446
+ deserves that stronger endorsement; direct Twinkle rewards are selective
447
+ too. Do not withhold a basic recommendation just because rewards are not
448
+ deserved, and do not mass-enable rewards to satisfy this duty. Honor
449
+ canonical Zero/Ciel deduplication: already-recommended comments still get
450
+ read, but do not need a second recommendation or daily reward. A bare
451
+ recommend does not revoke an existing reward permission; never claim it
452
+ switched one off. This duty is not authority to downgrade past decisions.
453
+ 4. **Propose the whole daily refresh, get approval, then execute it.** Identify carryover
454
+ pins from the saved board and canonical Featured history, without assuming
455
+ missing pins should be restored. Review replacements under the recency and
456
+ never-Featured gates above and rank them by the engagement they invite.
457
+ Show Mikey a specific old-Subject -> new-Subject mapping with titles, IDs,
458
+ canonical URLs, reasons, and the proposed final order, plus any retained
459
+ pins and specific constraints. Explicitly ask for his go-ahead and wait
460
+ before performing the proposed rotation. Daily freshness
461
+ and giving new conversations a turn are sufficient editorial reasons; a
462
+ prior Subject need not become bad or unsuitable first. Keep existing
463
+ removal/reorder approval and addition-capacity boundaries intact. After
464
+ Mikey approves the exact plan, autonomously perform **all approved swaps
465
+ and the approved ordering**, without per-item approval or asking him to
466
+ operate the website. Prepare the server-stored `featured plan` before
467
+ presenting it, then use `featured apply --file <plan.json> --approve <hash>`
468
+ only after that exact plan gets his go-ahead. Membership and final ordering
469
+ commit together; the server rechecks the original board, history revision,
470
+ and new-candidate eligibility inside the board transaction.
471
+ Verify the exact final membership and order from the server, then report
472
+ completion. Recover retryable failures within the approved scope; if
473
+ intervening owner changes, eligibility changes, or an API limit require a
474
+ materially different plan, preserve the new state, report what actually
475
+ completed, and seek approval for that difference instead of substituting
476
+ candidates or overwriting changes. Report proposals separately from
477
+ completed actions. Approval is for the presented plan, not future boards.
478
+ 5. **Make coverage and encouragement auditable.** In the final full-run report,
479
+ state Subjects covered, comments read, new basic recommendations,
480
+ already-recommended comments, selective reward-eligibility grants/direct
481
+ rewards, and genuinely skipped categories. Use canonical results, not
482
+ attempted commands, for action counts. Report any unread Subjects/pages
483
+ explicitly; never call a sample, a filtered queue, or a blocked thread a
484
+ completed all-Featured-comment review. Include refresh progress and any
485
+ carryovers as required in the `Featured rotation` report section below.
486
+
354
487
  ## Escalation to Mikey
355
488
 
356
489
  A full daily management run is not finished when the mutations are done. Curation surfaces things only
@@ -620,7 +753,7 @@ type DailyRun = {
620
753
  publicActorUserId: number;
621
754
  identityMode: "auto" | "zero" | "ciel";
622
755
  commentMode: "off" | "draft" | "post";
623
- runScope: "full" | "featured";
756
+ runScope: "full" | "featured" | "newspaper";
624
757
  sessionKind: "delegated-admin";
625
758
  scopes: string[];
626
759
  status: "active" | "completed" | "failed" | "expired";
@@ -722,6 +855,7 @@ identity, or advances rotation.
722
855
  ```bash
723
856
  lumine admin daily-run start --identity auto --comment-mode off --json
724
857
  lumine admin daily-run start --scope featured --identity auto --json
858
+ lumine admin daily-run start --scope newspaper --identity auto --json
725
859
  lumine admin daily-run start --identity ciel --comment-mode draft \
726
860
  --run-key daily:2026-08-06:review --json
727
861
  lumine admin daily-run status --json
@@ -815,16 +949,22 @@ written automatically only after an
815
949
  its local checkpoint and cannot be misreported as complete.
816
950
 
817
951
  **Every agent-authored final full-management report includes a `Featured rotation`
818
- section.** Base it on a fresh `featured list`. When capacity exists, make and
819
- report strong additions during the run under the standing approval above; do
820
- not defer them as proposals. Then name each current Subject proposed for
821
- removal with its canonical URL and a concrete editorial reason, followed by
822
- any replacement that would require that removal. Every proposed or completed
823
- addition described as new must include its posting date and canonical evidence
824
- that it has never been Featured; omit it when either gate is unverified. Never
825
- omit the section; when no removal or reorder is honestly warranted, say `None`
826
- and explain why. Removing or reordering pins remains a proposal until Mikey
827
- gives his go-ahead.
952
+ section.** Base it on the dated starting board, a fresh `featured list`, and
953
+ canonical history. Report the target of replacing **all previous-day pins**,
954
+ the exact proposed/completed outgoing-to-incoming mapping, and each retained
955
+ pin with its reason. Rank new candidates by likely genuine member engagement,
956
+ not thoughtfulness. Include the all-Featured-comment coverage and encouragement
957
+ counts described above. When genuine capacity exists, make and report strong
958
+ additions under the standing approval above; do not defer those as proposals.
959
+ Every proposed or completed new addition must include its posting date and
960
+ canonical never-Featured evidence; omit it when either gate is unverified.
961
+ If a complete refresh is constrained, state the shortfall, including inadequate
962
+ eligible inventory, inaccessible context, specific keep instructions, or pending
963
+ approval. Do not report `None` merely because yesterday's posts are still good
964
+ or have received support. Removing or reordering pins remains a proposal until
965
+ Mikey gives his go-ahead; a pending proposal is not a completed refresh. After
966
+ approval, execute the entire approved plan and verify it without asking for
967
+ each swap again. Never omit this section from a full-run report.
828
968
 
829
969
  Creating an escalation belongs to the active run; acknowledging, annotating,
830
970
  resolving, or reopening it does not. Use the run-independent `escalation`
@@ -1147,12 +1287,19 @@ website's canonical reward-level projection shape; deployment should verify
1147
1287
  (or `(contentId, ...)`) as the canonical route already requires. The joins/`NOT EXISTS` checks are necessary
1148
1288
  to preserve the normal recommendation and skip rules, but they run only for
1149
1289
  IDs in that bounded window. Subject-comment traversal uses
1150
- `idx_comments_isDeleted_subject_id`; standalone-post comments use the existing
1290
+ `idx_comments_isDeleted_subject_id`; standalone-post and Build comments use the existing
1151
1291
  `idx_content_comments_root_deleted` index (whose InnoDB entries also carry the
1152
1292
  primary ID). Recommendation identity uses
1153
1293
  `uniq_content_recommendations_active_identity`; `earn_comment_candidates` is
1154
1294
  driven by its primary key. No offset scan or new broad table scan was added.
1155
1295
 
1296
+ Featured comment review adds at most 100 per-Subject `MAX(id)` probes using
1297
+ `idx_comments_isDeleted_subject_id`, then reuses the bounded 50-comment page
1298
+ path. Receipt lookups use the audit primary key; review summaries use the
1299
+ existing `idx_laae_run_id (runId, id)` range and project only coverage/action
1300
+ outcomes, not downloaded comment bodies. Approved plans use the shared board
1301
+ lock and the history primary key for `MAX(id)`. No new schema is needed.
1302
+
1156
1303
  Deployment can verify the required existing index definitions with:
1157
1304
 
1158
1305
  ```sql
@@ -1199,8 +1346,18 @@ lumine admin subject comments 123 --cursor '<cursor>' --json
1199
1346
  lumine admin comments get 456 --json
1200
1347
  lumine admin post get https://www.twin-kle.com/ai-stories/88 --json
1201
1348
  lumine admin post comments dailyReflection:99 --cursor '<cursor>' --json
1349
+ lumine admin post comments build:884 --all --output build-comments.json --json
1202
1350
  ```
1203
1351
 
1352
+ Build comment inspection accepts `build:<id>`, a public `/app/<id>` URL, or
1353
+ `--type build`. It reads all root-thread comments and replies through a
1354
+ snapshot-bound cursor, with full text and `parentCommentId`/`replyToCommentId`
1355
+ relationships.
1356
+ Only public, published, canonical owner Builds qualify; contribution branches
1357
+ and private/unpublished Builds are rejected. This is thread inspection, not
1358
+ evidence of having reviewed the published app. Build-comment publication still
1359
+ requires its separate version-bound review evidence.
1360
+
1204
1361
  Schemas:
1205
1362
 
1206
1363
  ```ts
@@ -1300,6 +1457,9 @@ type FeaturedList = Success<{
1300
1457
  subjects: Subject[];
1301
1458
  count: number;
1302
1459
  maximum: 20;
1460
+ maximumScope: "delegated_admin";
1461
+ delegatedMaximum: 20;
1462
+ websiteMaximum: 100;
1303
1463
  }>;
1304
1464
 
1305
1465
  type FeaturedHistory = Success<{
@@ -1379,7 +1539,7 @@ effective level). Every response is reloaded from the writer.
1379
1539
 
1380
1540
  Featured reorder is a complete-set replacement: it rejects duplicates,
1381
1541
  unknown/deleted IDs, missing current members, non-subject rows, and more than
1382
- 20 subjects. Permanent pins and editorial ordering policy are deliberately not
1542
+ 100 subjects. Permanent pins and editorial ordering policy are deliberately not
1383
1543
  hardcoded.
1384
1544
 
1385
1545
  `featured history` is the compact canonical evidence path. It returns only
@@ -1423,9 +1583,12 @@ The response includes the canonical final board and the confirmed rotation
1423
1583
  IDs, so callers never synthesize Featured state locally.
1424
1584
 
1425
1585
  The two lists must have the same nonzero length, so rotation never changes the
1426
- board's count. That also lets an approved swap proceed when the website has
1427
- left a pre-existing board above the delegated maximum without growing it;
1428
- repair the inherited overflow separately with an approved `subject unfeature`.
1586
+ board's count. Up to 100 replacements are accepted, including an existing board
1587
+ above the delegated growth limit of 20. That is not an overflow to repair.
1588
+ The server also enforces live, recent, provably never-Featured additions. Pass
1589
+ `--posted-after` explicitly; for compatibility the legacy rotation command
1590
+ defaults to seven days before the current Bangkok day's midnight. The exact
1591
+ approved-plan workflow below always requires an explicit cutoff.
1429
1592
 
1430
1593
  This mutation deliberately does not choose candidates or override the
1431
1594
  editorial gates above. Before invoking it, the management agent must have
@@ -1433,11 +1596,120 @@ freshly reviewed the board, shown Mikey the removals and replacements, received
1433
1596
  his go-ahead, and verified that every proposed new addition is recent and has
1434
1597
  never previously been Featured from canonical evidence.
1435
1598
 
1599
+ ### Exact approved refresh and resumable comment encouragement
1600
+
1601
+ For the daily old-to-new proposal, prepare a canonical plan without changing pins:
1602
+
1603
+ ```bash
1604
+ lumine admin featured plan --remove-subject-ids 30,20 \
1605
+ --add-subject-ids 50,40 --subject-ids 40,50,10 \
1606
+ --posted-after 2026-09-01T00:00:00+07:00 --output featured-plan.json --json
1607
+ ```
1608
+
1609
+ Removal and addition lists are equal-size pairs. Optional `--subject-ids` is
1610
+ the **entire final ordered board**, including retained pins; without it,
1611
+ additions lead in supplied order and retained pins keep their relative order.
1612
+ The receipt contains titles, IDs, URLs, replacement pairs, final order, posting
1613
+ cutoff, run/actor identity, expected board and history revision, and `planHash`.
1614
+ Add qualitative reasons, show Mikey the exact mapping/order, and wait for his
1615
+ go-ahead. A generated hash is not itself human approval. After approval:
1616
+
1617
+ ```bash
1618
+ lumine admin featured apply --file featured-plan.json \
1619
+ --approve <exact-plan-hash> --json
1620
+ ```
1621
+
1622
+ The API loads the immutable plan from its same-run/operator/actor audit receipt,
1623
+ checks the supplied hash, and applies all swaps and ordering in one transaction.
1624
+ It rejects intervening reorders, swaps, even a changed-then-restored board, and
1625
+ newly ineligible candidates. No substitute candidates or follow-up reorder are
1626
+ inferred. The CLI then reads the live board and verifies exact membership/order.
1627
+ Retry the identical apply command after uncertain transport failure; it reuses
1628
+ the same idempotency key. If the final read fails or finds an intervening change,
1629
+ the error retains the canonical apply receipt and never restores old state.
1630
+ Expired/different runs require a fresh plan and renewed approval.
1631
+
1632
+ Use the following workflow for full daily comment review, or only when Mikey's
1633
+ Featured slice includes comment encouragement:
1634
+
1635
+ ```bash
1636
+ lumine admin featured comments scan --checkpoint featured-read.json --json
1637
+ # On interruption: repeat with --resume, in the same active run.
1638
+ # Read ALL pageFiles, including full root context and nested replies.
1639
+ lumine admin featured comments acknowledge \
1640
+ --checkpoint featured-read.json --reviewed --json
1641
+ ```
1642
+
1643
+ The scan snapshots every current Featured Subject (up to 100) and its maximum
1644
+ comment ID, includes already-viewed and older comments, and downloads full-text
1645
+ pages of 50 through server-owned receipt chains. It rejects filtered scans;
1646
+ there is no popularity, length, language, or keyword selection heuristic.
1647
+ Each private mode-0600 page file has a checkpointed hash; resume verifies the
1648
+ complete chain and uses stable request keys after lost responses. Concurrent
1649
+ use of a checkpoint is locked. Deleted/unavailable Subjects and locked secrets
1650
+ remain explicitly incomplete; an empty thread still requires a terminal page.
1651
+ The scanner never automatically reveals secrets. If reveal is authorized, use
1652
+ the ordinary explicit reveal command and resume. New comments above the saved
1653
+ boundary belong to a fresh scan, not a silently expanded claim of coverage.
1654
+
1655
+ `acknowledge --reviewed` is the agent's explicit confirmation that it read the
1656
+ downloaded terminal chains. The API validates those chains, records covered and
1657
+ missing Subject IDs and comment counts, and distinguishes complete from partial
1658
+ coverage. A download alone never counts as a read or grants recommendations.
1659
+ After a resumed scan fills a gap, read those pages and acknowledge again.
1660
+
1661
+ Compose a decisions JSON file from the genuinely reviewed comments, using the
1662
+ returned review ID, coverage receipt ID, and each selected comment's page ID:
1663
+
1664
+ ```json
1665
+ {
1666
+ "reviewId": 100,
1667
+ "coverageId": 1050,
1668
+ "selections": [
1669
+ { "commentId": 120, "pageId": 1001 },
1670
+ { "commentId": 119, "pageId": 1001, "anyoneCanReward": true },
1671
+ { "commentId": 118, "pageId": 1001, "anyoneCanReward": true, "rewardTwinkles": 3 }
1672
+ ]
1673
+ }
1674
+ ```
1675
+
1676
+ The agent chooses comments by context under the generous encouragement policy;
1677
+ the tool never auto-selects them. Reward permission defaults off; the only
1678
+ direct reward option is an explicitly selected 3-Twinkle pairing. Existing
1679
+ permissions are not revoked by a basic recommendation. Then apply and report:
1680
+
1681
+ ```bash
1682
+ lumine admin featured comments recommend --file featured-decisions.json \
1683
+ --checkpoint featured-recommend.json --json
1684
+ # Retry exactly this file/checkpoint with --resume after interruption.
1685
+ lumine admin featured comments report --checkpoint featured-read.json --json
1686
+ ```
1687
+
1688
+ Use separate scan and recommendation checkpoints. Selection files are capped at
1689
+ 20,000 unique comments/2 MiB; split larger work into explicit batches. Each
1690
+ target must belong to the reviewed page and an acknowledged Subject chain in
1691
+ this same run. The API re-reads it, rejects changed/hidden/deleted comments,
1692
+ system notifications and Zero/Ciel's own comments, and uses the normal canonical
1693
+ recommendation/reward/deduplication path. A blocked Subject does not prevent
1694
+ encouragement on acknowledged Subjects. Batches stop at a failed decision,
1695
+ retain confirmed receipts, and resume without replaying completed decisions.
1696
+ These recommendations are independent per-comment mutations, not an atomic
1697
+ batch; report partial completion honestly.
1698
+
1699
+ The review report and full/historical daily reports' `featuredReviews` expose
1700
+ acknowledged coverage, confirmed new/basic recommendations, already-done
1701
+ actions, selective reward-permission grants, and created direct rewards. The
1702
+ counts describe canonical outcomes, not attempted commands or downloaded rows.
1703
+ Read comments that are already recommended too; use the page evidence for
1704
+ already-recommended and skipped-category totals rather than treating the
1705
+ report's selected `alreadyDone` actions as all previously recommended comments.
1706
+
1436
1707
  ## Recommendation, Karma approval, and Twinkle rewards
1437
1708
 
1438
1709
  ```bash
1439
1710
  lumine admin post recommend 123 --json
1440
1711
  lumine admin post recommend https://www.twin-kle.com/ai-stories/88 --json
1712
+ lumine admin post recommend comment:456 --json
1441
1713
  lumine admin post recommend comment:456 --anyone-can-reward \
1442
1714
  --reward-twinkles 3 --idempotency-key review-456-v1 --json
1443
1715
  lumine admin post reward comment:456 --twinkles 3 --json
@@ -1447,6 +1719,15 @@ Numeric targets default to `subject`. Use `subject:<id>`, `comment:<id>`,
1447
1719
  `aiStory:<id>`, `dailyReflection:<id>`, a canonical URL, or the corresponding
1448
1720
  `--type`.
1449
1721
 
1722
+ For daily Featured-comment encouragement, prefer the review-bound
1723
+ `featured comments` workflow above so coverage and outcomes remain linked.
1724
+ The generic bare comment recommendation has the same basic default, but is
1725
+ not available in a Featured-only run. `--anyone-can-reward` and
1726
+ `--reward-twinkles` are separate, selective judgments, not required flags for an
1727
+ ordinary worthwhile comment.
1728
+ Follow **Daily Featured comments and refresh** for full-thread coverage and
1729
+ the intentionally generous basic-recommendation threshold.
1730
+
1450
1731
  ```ts
1451
1732
  type PriorRecommendationApproval = {
1452
1733
  recommendationId: number;
@@ -1553,7 +1834,7 @@ If recommendation succeeds but reward fails, the command exits nonzero with
1553
1834
 
1554
1835
  ```bash
1555
1836
  lumine admin post skip dailyReflection:99 --json
1556
- lumine admin post skip comment:456 --reason "one-line answer, nothing to add" --json
1837
+ lumine admin post skip comment:456 --reason "duplicate coin-begging spam" --json
1557
1838
  lumine admin post skip-batch --target-file skip-targets.json \
1558
1839
  --checkpoint skip-progress.json --json
1559
1840
  lumine admin post skip-batch --target-file skip-targets.json \
@@ -2106,8 +2387,8 @@ dump raw sections at him.
2106
2387
  ### Application AI calendar-month cost (standing duty, every full daily review)
2107
2388
 
2108
2389
  Run `lumine admin ai-costs monthly --json` during every full daily management
2109
- review. This read-only command requires the active delegated run and returns one
2110
- server-owned calendar summary from the canonical deduplicated application AI-
2390
+ review. This read-only command does not require or attach to a delegated run.
2391
+ It returns one server-owned calendar summary from the canonical deduplicated application AI-
2111
2392
  cost ledger. It deliberately takes no `--days`: all boundaries are UTC calendar
2112
2393
  months, so the result is directly comparable from one run to the next.
2113
2394
 
@@ -3301,6 +3582,16 @@ Deploy and verify the API's `/cli/admin/subjects/featured/rotation` route before
3301
3582
  publishing a CLI release that exposes `featured rotate`; an older API rejects
3302
3583
  the command without changing Featured state.
3303
3584
 
3585
+ The approved-plan and Featured-comment workflows require the new
3586
+ `/subjects/featured/plan`, `/plan/apply` (under that same Featured base), and
3587
+ `/subjects/featured/reviews` routes. Deploy the API before releasing the CLI;
3588
+ there is no fallback to unbound writes or a full daily run on an older API.
3589
+ Existing runs remain readable/completable with their original scopes, but are
3590
+ not silently granted `featured:comments`; start a fresh scoped/full run as
3591
+ appropriate after finishing the existing authorized work. No new migration is
3592
+ required for these workflows: server receipts reuse the existing audit table
3593
+ and full-board mutation history.
3594
+
3304
3595
  For scoped runs and Featured history, also apply
3305
3596
  `add-lumine-admin-run-scope.sql` and `add-featured-subject-history.sql` before
3306
3597
  the API release. After every serving API worker is verified on that release