@stage5/lumine 0.2.39 → 0.2.41

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/lib/commands.js CHANGED
@@ -63,6 +63,9 @@ import { probeUrl, requestJson } from "./http.js";
63
63
  import { sdkCommand } from "./sdk.js";
64
64
  import { doctorCommand, normalizePreviewUrl } from "./doctor.js";
65
65
  import { adminCommand } from "./admin.js";
66
+ import { runBuildForumCommand } from "./forum.js";
67
+ import { agentCommand } from "./agent.js";
68
+ import { agentMcpCommand } from "./agent/mcp-server.js";
66
69
  import {
67
70
  defaultMainCheckoutDir,
68
71
  defaultReferenceDir,
@@ -102,6 +105,12 @@ import {
102
105
 
103
106
  export async function main() {
104
107
  const options = parseArgs(process.argv.slice(2));
108
+ // MCP stdio must remain protocol-clean: no update checks, help text, or
109
+ // other stdout can run before the server takes ownership of the stream.
110
+ if (options.command === "agent-mcp") {
111
+ await agentMcpCommand(options);
112
+ return;
113
+ }
105
114
  options.lumineCli = await loadLumineCliVersionInfo({ options });
106
115
  if (options.help) {
107
116
  printHelp();
@@ -116,6 +125,11 @@ export async function main() {
116
125
  return;
117
126
  }
118
127
 
128
+ if (options.command === "agent") {
129
+ await agentCommand(options, { saveWorkspace: save });
130
+ return;
131
+ }
132
+
119
133
  if (options.command === "workspace") {
120
134
  await workspace(options);
121
135
  return;
@@ -156,6 +170,10 @@ export async function main() {
156
170
  await branches(options);
157
171
  return;
158
172
  }
173
+ if (options.command === "forum") {
174
+ await forum(options);
175
+ return;
176
+ }
159
177
  if (options.command === "suggest") {
160
178
  await sendSuggestion(options);
161
179
  return;
@@ -450,6 +468,28 @@ export async function branches(options) {
450
468
  printContributionBranches({ result, rootBuild, options });
451
469
  }
452
470
 
471
+ export async function forum(options) {
472
+ const explicitAction = ["read", "listen"].includes(
473
+ String(options.positional?.[0] || ""),
474
+ );
475
+ const maximumPositionals = explicitAction ? 2 : 1;
476
+ if ((options.positional?.length || 0) > maximumPositionals) {
477
+ throw new Error(
478
+ "Usage: lumine forum [read|listen] [twinkle-build-url-or-id]",
479
+ );
480
+ }
481
+ if (options.forumCursor === null) {
482
+ throw new Error("--cursor must be a non-negative integer.");
483
+ }
484
+ if (options.forumPollMs === null) {
485
+ throw new Error("--poll-ms must be an integer from 1000 through 60000.");
486
+ }
487
+ const auth = await resolveAuth(options);
488
+ await assertAuthScope({ options, auth, scope: "build:read" });
489
+ const buildId = await resolveRequiredBuildIdOrSelected(options, auth);
490
+ await runBuildForumCommand({ options, auth, buildId });
491
+ }
492
+
453
493
  export async function sendSuggestion(options) {
454
494
  const suggestionType = String(options.suggestionAction || "").trim();
455
495
  if (suggestionType !== "branch" && suggestionType !== "thumbnail") {
@@ -2182,6 +2222,11 @@ export function parseArgs(args) {
2182
2222
  "full",
2183
2223
  "unviewed",
2184
2224
  "viewed",
2225
+ "all",
2226
+ "resume",
2227
+ "sinceRun",
2228
+ "includeLegacy",
2229
+ "noReviewLoop",
2185
2230
  ]);
2186
2231
 
2187
2232
  for (let i = 0; i < rest.length; i += 1) {
@@ -2233,10 +2278,39 @@ export function parseArgs(args) {
2233
2278
  positional[0] === "list" ? positional[1] || "" : positional[0] || "",
2234
2279
  )
2235
2280
  : "";
2281
+ const forumAction =
2282
+ command === "forum" && ["read", "listen"].includes(positional[0])
2283
+ ? String(positional[0])
2284
+ : "read";
2285
+ const forumTarget =
2286
+ command === "forum"
2287
+ ? String(
2288
+ forumAction === "read" && positional[0] !== "read"
2289
+ ? positional[0] || ""
2290
+ : positional[1] || "",
2291
+ )
2292
+ : "";
2293
+ const forumCursor = Object.prototype.hasOwnProperty.call(raw, "cursor")
2294
+ ? /^\d+$/.test(String(raw.cursor).trim()) &&
2295
+ Number.isSafeInteger(Number(raw.cursor))
2296
+ ? Number(raw.cursor)
2297
+ : null
2298
+ : 0;
2299
+ const forumPollMs = Object.prototype.hasOwnProperty.call(raw, "pollMs")
2300
+ ? /^\d+$/.test(String(raw.pollMs).trim()) &&
2301
+ Number.isSafeInteger(Number(raw.pollMs)) &&
2302
+ Number(raw.pollMs) >= 1000 &&
2303
+ Number(raw.pollMs) <= 60_000
2304
+ ? Number(raw.pollMs)
2305
+ : null
2306
+ : 3000;
2236
2307
 
2237
2308
  return {
2238
2309
  command,
2239
2310
  positional,
2311
+ forumAction,
2312
+ forumCursor,
2313
+ forumPollMs,
2240
2314
  suggestionAction,
2241
2315
  suggestionId:
2242
2316
  command === "suggestions" && suggestionAction !== "list"
@@ -2252,7 +2326,33 @@ export function parseArgs(args) {
2252
2326
  cursor: Math.max(0, Math.floor(Number(raw.cursor) || 0)),
2253
2327
  adminCursor: raw.cursor ? String(raw.cursor) : "",
2254
2328
  adminAfter: raw.after ? String(raw.after) : "",
2329
+ adminSinceRun: Boolean(raw.sinceRun),
2330
+ adminIncludeLegacy: Boolean(raw.includeLegacy),
2331
+ adminAll: Boolean(raw.all),
2332
+ adminResume: Boolean(raw.resume),
2333
+ adminCheckpoint: raw.checkpoint ? String(raw.checkpoint) : "",
2334
+ adminOutput: raw.output ? String(raw.output) : "",
2335
+ adminOutputDir: raw.outputDir ? String(raw.outputDir) : "",
2336
+ adminClaimFile: raw.claim ? String(raw.claim) : "",
2337
+ adminScaffoldFile: raw.scaffold ? String(raw.scaffold) : "",
2338
+ adminTargetFile: raw.targetFile ? String(raw.targetFile) : "",
2339
+ adminReviewReceipt: raw.reviewReceipt ? String(raw.reviewReceipt) : "",
2340
+ adminSeverity: raw.severity ? String(raw.severity) : "",
2341
+ adminWaitMs: raw.waitMs ? String(raw.waitMs) : "",
2342
+ adminBrowserPath: raw.browserPath ? String(raw.browserPath) : "",
2255
2343
  adminEffort: raw.effort ? String(raw.effort) : "",
2344
+ agentEffort:
2345
+ command === "agent" && raw.effort ? String(raw.effort) : "",
2346
+ provider: raw.provider ? String(raw.provider) : "",
2347
+ providerPath: raw.providerPath ? String(raw.providerPath) : "",
2348
+ agentPrompt:
2349
+ command === "agent"
2350
+ ? String(raw.prompt || positional.join(" ")).trim()
2351
+ : "",
2352
+ runtimeFile: raw.runtimeFile ? String(raw.runtimeFile) : "",
2353
+ traceFile: raw.traceFile ? String(raw.traceFile) : "",
2354
+ baseFilesHash: raw.baseFilesHash ? String(raw.baseFilesHash) : "",
2355
+ reviewLoop: parseBoolean(raw.noReviewLoop, false) ? false : true,
2256
2356
  adminLevel: raw.level ? String(raw.level) : "",
2257
2357
  adminIds: raw.subjectIds
2258
2358
  ? String(raw.subjectIds)
@@ -2310,7 +2410,9 @@ export function parseArgs(args) {
2310
2410
  ? ""
2311
2411
  : command === "suggestions"
2312
2412
  ? suggestionListTarget
2313
- : positional[0] || ""),
2413
+ : command === "forum"
2414
+ ? forumTarget
2415
+ : positional[0] || ""),
2314
2416
  title:
2315
2417
  String(
2316
2418
  raw.title ||
@@ -2562,12 +2664,15 @@ export function printHelp() {
2562
2664
  lumine login
2563
2665
  lumine whoami
2564
2666
  lumine logout
2667
+ lumine agent --provider <codex|claude-code> "<build request>"
2565
2668
  lumine new [title]
2566
2669
  lumine rename [title] [--target <twinkle-build-url-or-id>]
2567
2670
  lumine describe [description] [--target <twinkle-build-url-or-id>]
2568
2671
  lumine upgrade [twinkle-build-url-or-id]
2569
2672
  lumine projects
2570
2673
  lumine branches [twinkle-build-url-or-id] [--limit <n>]
2674
+ lumine forum [read] [twinkle-build-url-or-id] [--cursor <sequence>] [--json]
2675
+ lumine forum listen [twinkle-build-url-or-id] [--cursor <sequence>] [--poll-ms <ms>] [--json]
2571
2676
  lumine suggest branch [message] [--target <twinkle-branch-url>]
2572
2677
  lumine suggest thumbnail [--target <twinkle-branch-url>]
2573
2678
  lumine suggestions [twinkle-build-url-or-id]
@@ -2607,23 +2712,26 @@ export function printHelp() {
2607
2712
  lumine admin ai-bucket accounts add --bucket-id <id> --user-ids <id,id,...> [--note <text>] [--json]
2608
2713
  lumine admin ai-bucket note set --bucket-id <id> --note <text> [--json]
2609
2714
  lumine admin daily-run start [--identity zero|ciel|auto] [--comment-mode off|draft|post] [--run-key <key>] [--json]
2610
- lumine admin daily-run status|complete|fail [--reason <text>] [--json]
2611
- lumine admin recommendations list [--content-types comment,dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
2612
- lumine admin builds candidates [--cursor <cursor>] [--limit <number>] [--json]
2613
- lumine admin subjects candidates [--after <date>] [--effort unassigned] [--unviewed|--viewed] [--cursor <cursor>] [--json]
2715
+ lumine admin daily-run status|report|complete|fail [--reason <text>] [--json]
2716
+ lumine admin daily-run escalation add --target <target> --note <summary> [--severity attention|urgent] [--json]
2717
+ lumine admin recommendations list [--since-run|--after <date>|--include-legacy] [--all --checkpoint <file> [--resume]] [--content-types comment,dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
2718
+ lumine admin builds candidates [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--limit <number>] [--json]
2719
+ lumine admin builds review <build-url-or-id> [--output-dir <dir>] [--wait-ms <ms>] [--browser-path <path>] [--json]
2720
+ lumine admin subjects candidates [--after <date>] [--effort unassigned] [--unviewed|--viewed] [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--json]
2614
2721
  lumine admin subject get|reveal <subject-url-or-id> [--json]
2615
- lumine admin subject comments <subject-url-or-id> [--unviewed|--viewed] [--cursor <cursor>] [--json]
2722
+ lumine admin subject comments <subject-url-or-id> [--unviewed|--viewed] [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--json]
2616
2723
  lumine admin subject effort set <subject-id> --level <1|2|3> [--json]
2617
2724
  lumine admin subject creator set-made-by-poster <subject-id> [--json]
2618
2725
  lumine admin subject feature|unfeature <subject-id> [--json]
2619
2726
  lumine admin featured list [--unviewed|--viewed] [--json]
2620
2727
  lumine admin featured reorder --subject-ids <id,id,...> [--json]
2621
2728
  lumine admin post get <target> [--type subject|comment|aiStory|dailyReflection] [--json]
2622
- lumine admin post comments <target> [--type subject|aiStory|dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
2729
+ lumine admin post comments <target> [--type subject|aiStory|dailyReflection] [--unviewed|--viewed] [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--json]
2623
2730
  lumine admin post recommend <target> [--type subject|comment|aiStory|dailyReflection] [--anyone-can-reward] [--reward-twinkles 3] [--json]
2624
2731
  lumine admin post skip <target> [--type comment|aiStory|dailyReflection] [--reason <text>] [--json]
2732
+ lumine admin post skip-batch --target-file <json-or-lines> [--reason <text>] [--checkpoint <file> [--resume]] [--json]
2625
2733
  lumine admin post reward <target> [--type subject|comment|aiStory|dailyReflection] --twinkles 3 [--json]
2626
- 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]
2734
+ 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]
2627
2735
  lumine admin comment reply comment:<id> [--file <reply.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--identity zero|ciel|auto] [--json]
2628
2736
  lumine admin comment post --draft-id <id> [--json]
2629
2737
  lumine admin comment edit <comment-id> --file <comment.md> [--json]
@@ -2631,8 +2739,11 @@ export function printHelp() {
2631
2739
  lumine admin bot-output [--days <1..30>] [--json]
2632
2740
  lumine admin announcement post --file <announcement.md> [--json]
2633
2741
  lumine admin chat send <user-id|username> --file <message.md> [--json]
2742
+ lumine admin news claim [--date YYYY-MM-DD] [--output <claim.json>] [--scaffold <editorial.json>] [--json]
2743
+ lumine admin news validate --claim <claim.json> --file <editorial.json> [--json]
2744
+ lumine admin news submit --claim <claim.json> --file <editorial.json> [--model <name>] [--json]
2634
2745
  lumine admin notable add <user-id|username> --note <text> [--json]
2635
- lumine admin audit [list] [--run current|last|<run-id>] [--target <target>] [--actions <a,b>] [--full] [--cursor <cursor>] [--json]
2746
+ lumine admin audit [list] [--run current|last|<run-id>] [--target <target>] [--actions <a,b>] [--full] [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--json]
2636
2747
 
2637
2748
  Examples:
2638
2749
  npx @stage5/lumine@latest
@@ -2645,6 +2756,8 @@ Examples:
2645
2756
  npx @stage5/lumine@latest upgrade https://www.twin-kle.com/app/123
2646
2757
  npx @stage5/lumine@latest new --title "Daily Reflection App" --description "Private journal with streaks"
2647
2758
  npx @stage5/lumine@latest branches 884
2759
+ npx @stage5/lumine@latest forum 884 --json
2760
+ npx @stage5/lumine@latest forum listen --json
2648
2761
  npx @stage5/lumine@latest suggest branch "Ready for review"
2649
2762
  npx @stage5/lumine@latest suggest thumbnail
2650
2763
  npx @stage5/lumine@latest suggestions 884
@@ -2661,6 +2774,8 @@ Examples:
2661
2774
  npx @stage5/lumine@latest restore 41 --main
2662
2775
  npx @stage5/lumine@latest update-from-main
2663
2776
  npx @stage5/lumine@latest pull
2777
+ npx @stage5/lumine@latest agent --provider codex "Add keyboard controls"
2778
+ npx @stage5/lumine@latest agent --provider claude-code "Fix the mobile layout"
2664
2779
  npx @stage5/lumine@latest save
2665
2780
  npx @stage5/lumine@latest save --publish
2666
2781
  npx @stage5/lumine@latest launch --save
@@ -2688,6 +2803,10 @@ Options:
2688
2803
  --auth-file <path> Saved login path
2689
2804
  --auth-token <token> Override saved login
2690
2805
  --dir <path> Directory for pulled project files
2806
+ --provider <agent> Subscription agent for lumine agent: codex or claude-code
2807
+ --provider-path <p> Override the selected agent CLI executable
2808
+ --effort <level> Optional provider reasoning effort
2809
+ --no-review-loop Skip the evidence-based post-run loop retrospective
2691
2810
  --target <build> Explicit Build URL or ID for rename/describe/upgrade
2692
2811
  --main With pull/versions/restore: target the team project's main
2693
2812
  --version <n> With pull: read-only checkout of previous save v<n>
@@ -2696,8 +2815,23 @@ Options:
2696
2815
  --no-description Skip New description or clear with describe
2697
2816
  --summary <text> Save summary
2698
2817
  --note <text> Suggestion, notable-user, or AI-bucket context
2699
- --cursor <id> Continue an owner suggestion inbox listing
2700
- --after <date> Admin subjects: inclusive Unix/ISO creation boundary
2818
+ --cursor <id> Continue suggestions, Forum activity, or admin listing
2819
+ --poll-ms <ms> Forum listener interval (1000-60000; default 3000)
2820
+ --after <date> Admin listing: inclusive Unix/ISO creation boundary
2821
+ --since-run Recommendations since the previous completed run (default)
2822
+ --include-legacy Explicitly include the full historical recommendation queue
2823
+ --all Automatically read every page in the canonical snapshot
2824
+ --checkpoint <file> Persist automatic pagination or batch progress
2825
+ --resume Resume the exact request recorded by --checkpoint
2826
+ --output <file> Save an admin result or newspaper claim as JSON
2827
+ --output-dir <dir> Directory for managed Build review evidence
2828
+ --claim <file> Newspaper claim JSON used for validation/submission
2829
+ --scaffold <file> Write an editable newspaper editorial scaffold
2830
+ --target-file <file> JSON array or newline list for audited batch skips
2831
+ --review-receipt <f> Confirmed managed Build runtime review receipt
2832
+ --severity <level> Run escalation severity: attention or urgent
2833
+ --wait-ms <ms> Managed Build runtime observation time (1000-45000)
2834
+ --browser-path <path> Chrome/Chromium executable for managed Build review
2701
2835
  --effort unassigned Admin subjects: show only unassigned effort
2702
2836
  --unviewed Admin content lists: retain unviewed and unknown items
2703
2837
  --viewed Admin content lists: retain viewed and unknown items
package/lib/constants.js CHANGED
@@ -168,6 +168,17 @@ lumine save --summary "Describe the change"
168
168
  need --allow-write and mutate real app data.
169
169
  - Owned canonical builds may be published only when the user explicitly asks.
170
170
 
171
+ ## Team Forum
172
+
173
+ - Before starting team-project work, run \`lumine forum --json\` and read every
174
+ canonical post and reply returned for this workspace. Main owners receive
175
+ Main plus all branch activity; branch contributors receive their branch plus
176
+ every project-owner post and reply on Main.
177
+ - During longer collaborative work, keep \`lumine forum listen --json\` open in
178
+ a separate terminal. It resumes only from server-confirmed cursors and emits
179
+ complete canonical update batches. Do not infer teammate intent from stale
180
+ files or local state when the Forum provides the current instruction.
181
+
171
182
  ## Team Suggestions
172
183
 
173
184
  - After saving contribution-branch work, use \`lumine suggest branch "Ready for review"\`
@@ -319,6 +330,7 @@ export const MAIN_CHECKOUT_READONLY_COMMANDS = new Set([
319
330
  "pull",
320
331
  "check",
321
332
  "branches",
333
+ "forum",
322
334
  "diff",
323
335
  "sdk",
324
336
  "select",
@@ -331,6 +343,8 @@ export const MAIN_CHECKOUT_READONLY_COMMANDS = new Set([
331
343
  ]);
332
344
  export const COMMANDS = new Set([
333
345
  "admin",
346
+ "agent",
347
+ "agent-mcp",
334
348
  "workspace",
335
349
  "login",
336
350
  "logout",
@@ -341,6 +355,7 @@ export const COMMANDS = new Set([
341
355
  "upgrade",
342
356
  "projects",
343
357
  "branches",
358
+ "forum",
344
359
  "suggest",
345
360
  "suggestions",
346
361
  "explore",