@cyber-dash-tech/revela 0.15.1 → 0.15.3

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.
Files changed (41) hide show
  1. package/README.md +58 -104
  2. package/README.zh-CN.md +59 -104
  3. package/designs/starter/DESIGN.md +33 -14
  4. package/designs/starter/preview.html +23 -16
  5. package/designs/summit/DESIGN.md +35 -42
  6. package/designs/summit/preview.html +49 -49
  7. package/lib/commands/brief.ts +1 -1
  8. package/lib/commands/designs-new.ts +6 -6
  9. package/lib/commands/designs.ts +9 -9
  10. package/lib/commands/domains.ts +9 -9
  11. package/lib/commands/edit.ts +1 -1
  12. package/lib/commands/help.ts +34 -37
  13. package/lib/commands/init.ts +1 -1
  14. package/lib/commands/inspect.ts +2 -20
  15. package/lib/commands/narrative.ts +3 -3
  16. package/lib/commands/pdf.ts +3 -3
  17. package/lib/commands/pptx.ts +2 -2
  18. package/lib/commands/review.ts +13 -6
  19. package/lib/decks-state.ts +6 -6
  20. package/lib/edit/deck-state.ts +1 -1
  21. package/lib/edit/prompt.ts +12 -0
  22. package/lib/edit/resolve-deck.ts +1 -1
  23. package/lib/inspect/prompt.ts +6 -1
  24. package/lib/inspect/server.ts +2 -2
  25. package/lib/media/download.ts +36 -11
  26. package/lib/media/save.ts +24 -0
  27. package/lib/media/search.ts +385 -0
  28. package/lib/media/types.ts +12 -0
  29. package/lib/prompt-builder.ts +20 -14
  30. package/lib/qa/checks.ts +2 -1
  31. package/lib/qa/index.ts +73 -2
  32. package/lib/refine/server.ts +758 -68
  33. package/package.json +1 -1
  34. package/plugin.ts +133 -283
  35. package/skill/NARRATIVE_SKILL.md +15 -17
  36. package/skill/SKILL.md +220 -477
  37. package/tools/edit.ts +1 -1
  38. package/tools/inspection-result.ts +1 -1
  39. package/tools/media-save.ts +6 -0
  40. package/lib/commands/disable.ts +0 -14
  41. package/lib/commands/enable.ts +0 -48
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyber-dash-tech/revela",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "description": "OpenCode plugin that turns AI into an HTML slide deck generator",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
package/plugin.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * revela — Core OpenCode Plugin
3
3
  *
4
- * Architecture: enable/disable mode + single /revela command (DCP style)
4
+ * Architecture: single /revela command surface (DCP style)
5
5
  *
6
6
  * Responsibilities:
7
7
  * 1. On load: seed built-in designs/domains + build initial _active-prompt.md
@@ -30,8 +30,6 @@ import { extractPdfText } from "./lib/read-hooks/extractors/pdf"
30
30
  import { createOfficeReadView } from "./lib/read-hooks/office-read-view"
31
31
  import { OFFICE_EXTENSIONS, IMAGE_EXTENSIONS, formatExtractedText } from "./lib/read-hooks/dispatch"
32
32
  import { handleHelp } from "./lib/commands/help"
33
- import { handleEnable } from "./lib/commands/enable"
34
- import { handleDisable } from "./lib/commands/disable"
35
33
  import {
36
34
  handleDesignsList,
37
35
  handleDesignsActivate,
@@ -46,8 +44,6 @@ import {
46
44
  } from "./lib/commands/domains"
47
45
  import { handlePdf } from "./lib/commands/pdf"
48
46
  import { buildPptxNotesPrompt, handlePptx, parsePptxArgs, resolvePptxDeck } from "./lib/commands/pptx"
49
- import { handleEdit } from "./lib/commands/edit"
50
- import { handleInspect } from "./lib/commands/inspect"
51
47
  import { handleRefine } from "./lib/commands/refine"
52
48
  import { formatArtifactQAReport, runArtifactQA } from "./lib/qa/artifact"
53
49
  import { ensureRefineDeckOpenForChange } from "./lib/refine/open"
@@ -61,9 +57,8 @@ import {
61
57
  import { buildInitPrompt } from "./lib/commands/init"
62
58
  import { buildResearchPrompt } from "./lib/commands/research"
63
59
  import { handleBrief, parseBriefArgs } from "./lib/commands/brief"
64
- import { buildNarrativeViewPrompt, handleNarrative, parseNarrativeArgs, parseStoryArgs } from "./lib/commands/narrative"
65
- import { parseRememberArgs, buildRememberPrompt } from "./lib/commands/remember"
66
- import { buildDeckPrompt, buildDeckReviewPrompt, buildReviewPrompt } from "./lib/commands/review"
60
+ import { buildNarrativeViewPrompt, parseStoryArgs } from "./lib/commands/narrative"
61
+ import { buildDeckPrompt } from "./lib/commands/review"
67
62
  import {
68
63
  extractDeckHtmlTargetsFromPatch,
69
64
  extractPatchTextArg,
@@ -235,7 +230,7 @@ const server: Plugin = (async (pluginCtx) => {
235
230
  opencodeConfig.command ??= {}
236
231
  opencodeConfig.command["revela"] = {
237
232
  template: "",
238
- description: "Revela narrative artifact workspace (init, research, story, make, refine, design)",
233
+ description: "show REVELA help",
239
234
  }
240
235
 
241
236
  // Register the research subagent.
@@ -316,277 +311,122 @@ const server: Plugin = (async (pluginCtx) => {
316
311
  await handleHelp(send)
317
312
  throw new Error("__REVELA_STATUS_HANDLED__")
318
313
  }
319
- if (sub === "enable") {
320
- await handleEnable(send)
321
- throw new Error("__REVELA_ENABLE_HANDLED__")
322
- }
323
- if (sub === "disable") {
324
- await handleDisable(send)
325
- throw new Error("__REVELA_DISABLE_HANDLED__")
326
- }
327
- if (sub === "init") {
328
- queueWorkflowCommand({
329
- sessionID,
330
- name: "init",
331
- mode: "narrative",
332
- visibleText: "Initialize Revela workspace.",
333
- hiddenPrompt: buildInitPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
334
- output,
335
- })
336
- return
337
- }
338
- if (sub === "remember") {
339
- const parsed = parseRememberArgs(param)
340
- if (!parsed.ok) {
341
- await send(parsed.error)
342
- throw new Error("__REVELA_REMEMBER_USAGE_HANDLED__")
343
- }
344
- queueWorkflowCommand({
345
- sessionID,
346
- name: "remember",
347
- mode: "narrative",
348
- visibleText: "Remember Revela workspace preference.",
349
- hiddenPrompt: buildRememberPrompt({ memory: parsed.memory, exists: hasDecksState(workspaceRoot) }),
350
- output,
351
- })
352
- return
353
- }
354
- if (sub === "research") {
355
- if (param) {
356
- await send("`/revela research` does not accept arguments yet. Add the research question in normal chat, or run it to work from open story gaps.")
357
- throw new Error("__REVELA_RESEARCH_USAGE_HANDLED__")
358
- }
359
- queueWorkflowCommand({
360
- sessionID,
361
- name: "research",
362
- mode: "narrative",
363
- visibleText: "Research Revela story gaps.",
364
- hiddenPrompt: buildResearchPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
365
- output,
366
- })
367
- return
368
- }
369
- if (sub === "review") {
370
- if (param) {
371
- await send("`/revela review` no longer accepts a deck name. It is a compatibility alias for `/revela story`. Use `/revela make deck --review` for deck/artifact readiness.")
372
- throw new Error("__REVELA_REVIEW_USAGE_HANDLED__")
373
- }
374
- queueWorkflowCommand({
375
- sessionID,
376
- name: "review",
377
- mode: "narrative",
378
- visibleText: "Review Revela story readiness.",
379
- hiddenPrompt: buildReviewPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
380
- output,
381
- })
382
- return
383
- }
384
- if (sub === "story") {
385
- const parsed = parseStoryArgs(param)
386
- if (!parsed.ok) {
387
- await send(parsed.error)
388
- throw new Error("__REVELA_STORY_USAGE_HANDLED__")
389
- }
390
- queueWorkflowCommand({
391
- sessionID,
392
- name: "story",
393
- mode: "narrative",
394
- visibleText: "Open Revela story workspace.",
395
- hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: parsed.args.language }),
396
- output,
397
- })
398
- return
399
- }
400
- if (sub === "narrative") {
401
- if (!param) {
402
- queueWorkflowCommand({
403
- sessionID,
404
- name: "narrative",
405
- mode: "narrative",
406
- visibleText: "Open Revela story workspace.",
407
- hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: "en" }),
408
- output,
409
- })
410
- return
411
- }
412
- const parsed = parseNarrativeArgs(param)
413
- if (!parsed.ok) {
414
- await send(parsed.error)
415
- throw new Error("__REVELA_NARRATIVE_USAGE_HANDLED__")
416
- }
417
- if (parsed.args.raw) {
418
- await handleNarrative({ workspaceRoot, openBrowser: true, language: parsed.args.language }, send)
419
- throw new Error("__REVELA_NARRATIVE_HANDLED__")
420
- }
421
- queueWorkflowCommand({
422
- sessionID,
423
- name: "narrative view",
424
- mode: "narrative",
425
- visibleText: "Open read-only Revela narrative map.",
426
- hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: parsed.args.language }),
427
- output,
428
- })
429
- return
430
- }
431
- if (sub === "brief") {
432
- const parsed = parseBriefArgs(param)
433
- if (!parsed.ok) {
434
- await send(parsed.error)
435
- throw new Error("__REVELA_BRIEF_USAGE_HANDLED__")
436
- }
437
- await handleBrief({ workspaceRoot, outputPath: parsed.args.outputPath }, send)
438
- throw new Error("__REVELA_BRIEF_HANDLED__")
439
- }
440
314
  if (sub === "make") {
441
315
  const target = args[1]?.toLowerCase() ?? ""
442
316
  const makeParam = args.slice(2).join(" ")
443
- if (target === "deck") {
444
- if (makeParam && makeParam !== "--review") {
445
- await send("Usage: `/revela make deck` starts approved-narrative deck handoff; `/revela make deck --review` reviews deck/artifact readiness.")
317
+ if (target === "--deck") {
318
+ if (makeParam) {
319
+ await send("Usage: `/revela make --deck`.")
446
320
  throw new Error("__REVELA_MAKE_DECK_USAGE_HANDLED__")
447
321
  }
448
322
  queueWorkflowCommand({
449
323
  sessionID,
450
- name: makeParam ? "make deck --review" : "make deck",
324
+ name: "make --deck",
451
325
  mode: "deck-render",
452
- visibleText: makeParam ? "Review Revela deck artifact readiness." : "Make Revela deck from approved story.",
453
- hiddenPrompt: makeParam
454
- ? buildDeckReviewPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot })
455
- : buildDeckPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
326
+ visibleText: "Make Revela deck from approved story.",
327
+ hiddenPrompt: buildDeckPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
456
328
  output,
457
329
  })
458
330
  return
459
331
  }
460
- if (target === "brief") {
332
+ if (target === "--brief") {
461
333
  const parsed = parseBriefArgs(makeParam)
462
334
  if (!parsed.ok) {
463
- await send(parsed.error.replace("/revela brief", "/revela make brief"))
335
+ await send(parsed.error.replace("/revela brief", "/revela make --brief"))
464
336
  throw new Error("__REVELA_MAKE_BRIEF_USAGE_HANDLED__")
465
337
  }
466
338
  await handleBrief({ workspaceRoot, outputPath: parsed.args.outputPath }, send)
467
339
  throw new Error("__REVELA_MAKE_BRIEF_HANDLED__")
468
340
  }
469
- await send("Usage: `/revela make deck [--review]` or `/revela make brief [workspace-relative-output.md]`.")
341
+ await send("Usage: `/revela make --deck` or `/revela make --brief [workspace-relative-output.md]`.")
470
342
  throw new Error("__REVELA_MAKE_USAGE_HANDLED__")
471
343
  }
472
- if (sub === "deck") {
473
- if (param && param !== "--review") {
474
- await send("Usage: `/revela deck` starts approved-narrative deck handoff; `/revela deck --review` reviews deck/artifact readiness. These are compatibility aliases for `/revela make deck`.")
475
- throw new Error("__REVELA_DECK_USAGE_HANDLED__")
476
- }
477
- if (!param) {
478
- queueWorkflowCommand({
479
- sessionID,
480
- name: "deck",
481
- mode: "deck-render",
482
- visibleText: "Make Revela deck from approved story.",
483
- hiddenPrompt: buildDeckPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
484
- output,
485
- })
486
- return
487
- }
488
- queueWorkflowCommand({
489
- sessionID,
490
- name: "deck --review",
491
- mode: "deck-render",
492
- visibleText: "Review Revela deck artifact readiness.",
493
- hiddenPrompt: buildDeckReviewPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
494
- output,
495
- })
496
- return
497
- }
498
344
  if (sub === "refine") {
499
- if (param) {
500
- await send("`/revela refine` does not accept a target. It opens the only HTML deck in `decks/`.")
345
+ if (param !== "--deck") {
346
+ await send("Usage: `/revela refine --deck`.")
501
347
  throw new Error("__REVELA_REFINE_USAGE_HANDLED__")
502
348
  }
503
349
  await handleRefine({ client, sessionID, workspaceRoot }, send)
504
350
  throw new Error("__REVELA_REFINE_HANDLED__")
505
351
  }
506
- if (sub === "edit") {
507
- if (param) {
508
- await send("`/revela edit` has been removed. Use `/revela refine` for the unified reading, inspection, and editing workspace.")
509
- throw new Error("__REVELA_EDIT_USAGE_HANDLED__")
510
- }
511
- await handleEdit({ client, sessionID, workspaceRoot }, send)
512
- throw new Error("__REVELA_EDIT_HANDLED__")
513
- }
514
- if (sub === "inspect") {
515
- if (param) {
516
- await send("`/revela inspect` is deprecated and does not accept a target. Use `/revela refine` for the unified reading and refinement workspace.")
517
- throw new Error("__REVELA_INSPECT_USAGE_HANDLED__")
352
+ if (sub === "export") {
353
+ const target = args[1]?.toLowerCase() ?? ""
354
+ const format = args[2]?.toLowerCase() ?? ""
355
+ const exportParam = args.slice(3).join(" ")
356
+ if (target !== "--deck" || (format !== "pdf" && format !== "pptx")) {
357
+ await send("Usage: `/revela export --deck pdf [file.html]` or `/revela export --deck pptx [file.html] [--notes]`.")
358
+ throw new Error("__REVELA_EXPORT_USAGE_HANDLED__")
359
+ }
360
+ if (format === "pdf") {
361
+ await handlePdf(exportParam, send, workspaceRoot)
362
+ throw new Error("__REVELA_EXPORT_PDF_HANDLED__")
363
+ }
364
+ const pptxArgs = parsePptxArgs(exportParam)
365
+ if (pptxArgs.notes) {
366
+ try {
367
+ const deck = resolvePptxDeck(workspaceRoot, pptxArgs.filePath)
368
+ queueWorkflowCommand({
369
+ sessionID,
370
+ name: "export --deck pptx --notes",
371
+ mode: "deck-render",
372
+ visibleText: "Export Revela deck to PPTX with speaker notes.",
373
+ hiddenPrompt: buildPptxNotesPrompt(deck),
374
+ output,
375
+ })
376
+ return
377
+ } catch (e) {
378
+ const msg = e instanceof Error ? e.message : String(e)
379
+ await send(`**PPTX export failed**\n\n\`\`\`\n${msg}\n\`\`\``)
380
+ throw new Error("__REVELA_EXPORT_PPTX_HANDLED__")
381
+ }
518
382
  }
519
- await handleInspect({ client, sessionID, workspaceRoot }, send)
520
- throw new Error("__REVELA_INSPECT_HANDLED__")
521
- }
522
- if (sub === "designs" && !param) {
523
- await handleDesignsList(send)
524
- throw new Error("__REVELA_DESIGNS_LIST_HANDLED__")
525
- }
526
- if (sub === "designs" && param) {
527
- await handleDesignsActivate(param, send)
528
- throw new Error("__REVELA_DESIGNS_ACTIVATE_HANDLED__")
529
- }
530
- if (sub === "domains" && !param) {
531
- await handleDomainsList(send)
532
- throw new Error("__REVELA_DOMAINS_LIST_HANDLED__")
533
- }
534
- if (sub === "domains" && param) {
535
- await handleDomainsActivate(param, send)
536
- throw new Error("__REVELA_DOMAINS_ACTIVATE_HANDLED__")
537
- }
538
- if (sub === "designs-add") {
539
- await handleDesignsAdd(param, send)
540
- throw new Error("__REVELA_DESIGNS_ADD_HANDLED__")
383
+ await handlePptx(exportParam, send, workspaceRoot)
384
+ throw new Error("__REVELA_EXPORT_PPTX_HANDLED__")
541
385
  }
542
386
  if (sub === "design") {
543
- const designAction = args[1]?.toLowerCase() ?? "list"
387
+ const designAction = args[1]?.toLowerCase() ?? ""
544
388
  const designParam = args.slice(2).join(" ")
545
- if (designAction === "list") {
546
- if (designParam) {
547
- await send("Usage: `/revela design list`.")
548
- throw new Error("__REVELA_DESIGN_LIST_USAGE_HANDLED__")
549
- }
389
+ if (!designAction) {
550
390
  await handleDesignsList(send)
551
391
  throw new Error("__REVELA_DESIGN_LIST_HANDLED__")
552
392
  }
553
- if (designAction === "use") {
393
+ if (designAction === "--use") {
554
394
  if (!designParam) {
555
- await send("Usage: `/revela design use <name>`.")
395
+ await send("Usage: `/revela design --use <name>`.")
556
396
  throw new Error("__REVELA_DESIGN_USE_USAGE_HANDLED__")
557
397
  }
558
398
  await handleDesignsActivate(designParam, send)
559
399
  throw new Error("__REVELA_DESIGN_USE_HANDLED__")
560
400
  }
561
- if (designAction === "add") {
401
+ if (designAction === "--add") {
562
402
  if (!designParam) {
563
- await send("Usage: `/revela design add <url|github:user/repo|local-path>`.")
403
+ await send("Usage: `/revela design --add <url|github:user/repo|local-path>`.")
564
404
  throw new Error("__REVELA_DESIGN_ADD_USAGE_HANDLED__")
565
405
  }
566
406
  await handleDesignsAdd(designParam, send)
567
407
  throw new Error("__REVELA_DESIGN_ADD_HANDLED__")
568
408
  }
569
- if (designAction === "rm" || designAction === "remove") {
409
+ if (designAction === "--rm") {
570
410
  if (!designParam) {
571
- await send("Usage: `/revela design rm <name>`.")
411
+ await send("Usage: `/revela design --rm <name>`.")
572
412
  throw new Error("__REVELA_DESIGN_RM_USAGE_HANDLED__")
573
413
  }
574
414
  await handleDesignsRemove(designParam, send)
575
415
  throw new Error("__REVELA_DESIGN_RM_HANDLED__")
576
416
  }
577
- if (designAction === "preview") {
417
+ if (designAction === "--preview") {
578
418
  await handleDesignsPreview(designParam, send)
579
419
  throw new Error("__REVELA_DESIGN_PREVIEW_HANDLED__")
580
420
  }
581
- if (designAction === "new") {
421
+ if (designAction === "--new") {
582
422
  const parsed = parseDesignsNewArgs(designParam)
583
423
  if (!parsed.ok) {
584
- await send(parsed.error.replaceAll("/revela designs-new", "/revela design new"))
424
+ await send(parsed.error)
585
425
  throw new Error("__REVELA_DESIGN_NEW_USAGE_HANDLED__")
586
426
  }
587
427
  queueWorkflowCommand({
588
428
  sessionID,
589
- name: `design new ${parsed.name}`,
429
+ name: `design --new ${parsed.name}`,
590
430
  mode: "deck-render",
591
431
  visibleText: `Create Revela design ${parsed.name}.`,
592
432
  hiddenPrompt: buildDesignsNewPrompt({ name: parsed.name, base: parsed.base }),
@@ -594,15 +434,15 @@ const server: Plugin = (async (pluginCtx) => {
594
434
  })
595
435
  return
596
436
  }
597
- if (designAction === "edit") {
437
+ if (designAction === "--edit") {
598
438
  const parsed = parseDesignsEditArgs(designParam)
599
439
  if (!parsed.ok) {
600
- await send(parsed.error.replaceAll("/revela designs-edit", "/revela design edit"))
440
+ await send(parsed.error)
601
441
  throw new Error("__REVELA_DESIGN_EDIT_USAGE_HANDLED__")
602
442
  }
603
443
  queueWorkflowCommand({
604
444
  sessionID,
605
- name: `design edit ${parsed.name}`,
445
+ name: `design --edit ${parsed.name}`,
606
446
  mode: "deck-render",
607
447
  visibleText: `Edit Revela design ${parsed.name}.`,
608
448
  hiddenPrompt: buildDesignsEditPrompt({ name: parsed.name }),
@@ -610,84 +450,94 @@ const server: Plugin = (async (pluginCtx) => {
610
450
  })
611
451
  return
612
452
  }
613
- await send("Usage: `/revela design [list|use <name>|new <name>|edit <name>|preview [name]|add <source>|rm <name>]`.")
453
+ await send("Usage: `/revela design [--use <name>|--preview [name]|--new <name>|--edit <name>|--add <source>|--rm <name>]`.")
614
454
  throw new Error("__REVELA_DESIGN_USAGE_HANDLED__")
615
455
  }
616
- if (sub === "designs-new") {
617
- const parsed = parseDesignsNewArgs(param)
618
- if (!parsed.ok) {
619
- await send(parsed.error)
620
- throw new Error("__REVELA_DESIGNS_NEW_USAGE_HANDLED__")
456
+ if (sub === "domain") {
457
+ const domainAction = args[1]?.toLowerCase() ?? ""
458
+ const domainParam = args.slice(2).join(" ")
459
+ if (!domainAction) {
460
+ await handleDomainsList(send)
461
+ throw new Error("__REVELA_DOMAIN_LIST_HANDLED__")
462
+ }
463
+ if (domainAction === "--use") {
464
+ if (!domainParam) {
465
+ await send("Usage: `/revela domain --use <name>`.")
466
+ throw new Error("__REVELA_DOMAIN_USE_USAGE_HANDLED__")
467
+ }
468
+ await handleDomainsActivate(domainParam, send)
469
+ throw new Error("__REVELA_DOMAIN_USE_HANDLED__")
470
+ }
471
+ if (domainAction === "--add") {
472
+ if (!domainParam) {
473
+ await send("Usage: `/revela domain --add <url|github:user/repo|local-path>`.")
474
+ throw new Error("__REVELA_DOMAIN_ADD_USAGE_HANDLED__")
475
+ }
476
+ await handleDomainsAdd(domainParam, send)
477
+ throw new Error("__REVELA_DOMAIN_ADD_HANDLED__")
478
+ }
479
+ if (domainAction === "--rm") {
480
+ if (!domainParam) {
481
+ await send("Usage: `/revela domain --rm <name>`.")
482
+ throw new Error("__REVELA_DOMAIN_RM_USAGE_HANDLED__")
483
+ }
484
+ await handleDomainsRemove(domainParam, send)
485
+ throw new Error("__REVELA_DOMAIN_RM_HANDLED__")
486
+ }
487
+ await send("Usage: `/revela domain [--use <name>|--add <source>|--rm <name>]`.")
488
+ throw new Error("__REVELA_DOMAIN_USAGE_HANDLED__")
489
+ }
490
+ const legacyCommands = new Set([
491
+ "enable", "disable", "review", "narrative", "deck", "brief", "edit", "inspect", "remember",
492
+ "designs", "designs-new", "designs-edit", "designs-preview", "designs-add", "designs-rm",
493
+ "domains", "domains-add", "domains-rm", "pdf", "pptx",
494
+ ])
495
+ if (legacyCommands.has(sub)) {
496
+ await send(`\`/revela ${sub}\` is no longer a public command. Run \`/revela\` to see the current REVELA help.`)
497
+ throw new Error("__REVELA_LEGACY_COMMAND_HANDLED__")
498
+ }
499
+ if (sub === "init") {
500
+ queueWorkflowCommand({
501
+ sessionID,
502
+ name: "init",
503
+ mode: "narrative",
504
+ visibleText: "Initialize Revela workspace.",
505
+ hiddenPrompt: buildInitPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
506
+ output,
507
+ })
508
+ return
509
+ }
510
+ if (sub === "research") {
511
+ if (param) {
512
+ await send("`/revela research` does not accept arguments yet. Add the research question in normal chat, or run it to work from open story gaps.")
513
+ throw new Error("__REVELA_RESEARCH_USAGE_HANDLED__")
621
514
  }
622
515
  queueWorkflowCommand({
623
516
  sessionID,
624
- name: `designs-new ${parsed.name}`,
625
- mode: "deck-render",
626
- visibleText: `Create Revela design ${parsed.name}.`,
627
- hiddenPrompt: buildDesignsNewPrompt({ name: parsed.name, base: parsed.base }),
517
+ name: "research",
518
+ mode: "narrative",
519
+ visibleText: "Research Revela story gaps.",
520
+ hiddenPrompt: buildResearchPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
628
521
  output,
629
522
  })
630
523
  return
631
524
  }
632
- if (sub === "designs-edit") {
633
- const parsed = parseDesignsEditArgs(param)
525
+ if (sub === "story") {
526
+ const parsed = parseStoryArgs(param)
634
527
  if (!parsed.ok) {
635
528
  await send(parsed.error)
636
- throw new Error("__REVELA_DESIGNS_EDIT_USAGE_HANDLED__")
529
+ throw new Error("__REVELA_STORY_USAGE_HANDLED__")
637
530
  }
638
531
  queueWorkflowCommand({
639
532
  sessionID,
640
- name: `designs-edit ${parsed.name}`,
641
- mode: "deck-render",
642
- visibleText: `Edit Revela design ${parsed.name}.`,
643
- hiddenPrompt: buildDesignsEditPrompt({ name: parsed.name }),
533
+ name: "story",
534
+ mode: "narrative",
535
+ visibleText: "Open Revela story workspace.",
536
+ hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: parsed.args.language }),
644
537
  output,
645
538
  })
646
539
  return
647
540
  }
648
- if (sub === "designs-preview") {
649
- await handleDesignsPreview(param, send)
650
- throw new Error("__REVELA_DESIGNS_PREVIEW_HANDLED__")
651
- }
652
- if (sub === "domains-add") {
653
- await handleDomainsAdd(param, send)
654
- throw new Error("__REVELA_DOMAINS_ADD_HANDLED__")
655
- }
656
- if (sub === "designs-rm") {
657
- await handleDesignsRemove(param, send)
658
- throw new Error("__REVELA_DESIGNS_RM_HANDLED__")
659
- }
660
- if (sub === "domains-rm") {
661
- await handleDomainsRemove(param, send)
662
- throw new Error("__REVELA_DOMAINS_RM_HANDLED__")
663
- }
664
- if (sub === "pdf") {
665
- await handlePdf(param, send, workspaceRoot)
666
- throw new Error("__REVELA_PDF_HANDLED__")
667
- }
668
- if (sub === "pptx") {
669
- const args = parsePptxArgs(param)
670
- if (args.notes) {
671
- try {
672
- const deck = resolvePptxDeck(workspaceRoot, args.filePath)
673
- queueWorkflowCommand({
674
- sessionID,
675
- name: "pptx --notes",
676
- mode: "deck-render",
677
- visibleText: "Export Revela deck to PPTX with speaker notes.",
678
- hiddenPrompt: buildPptxNotesPrompt(deck),
679
- output,
680
- })
681
- return
682
- } catch (e) {
683
- const msg = e instanceof Error ? e.message : String(e)
684
- await send(`**PPTX export failed**\n\n\`\`\`\n${msg}\n\`\`\``)
685
- throw new Error("__REVELA_PPTX_HANDLED__")
686
- }
687
- }
688
- await handlePptx(param, send, workspaceRoot)
689
- throw new Error("__REVELA_PPTX_HANDLED__")
690
- }
691
541
 
692
542
  await send(`**Unknown sub-command:** \`${sub}\`\nRun \`/revela\` to see available commands.`)
693
543
  throw new Error("__REVELA_UNKNOWN_HANDLED__")
@@ -817,7 +667,7 @@ const server: Plugin = (async (pluginCtx) => {
817
667
  // This prevents a silent "revela enabled but not working" scenario.
818
668
  output.system.push(
819
669
  "\n\n[REVELA ERROR: Failed to load the slide generation prompt. " +
820
- "Run /revela disable then /revela enable to reinitialize.]"
670
+ "Run /revela to confirm the plugin is available, then retry the workflow command.]"
821
671
  )
822
672
  }
823
673
  },
@@ -10,7 +10,7 @@ You help the user turn source materials, research, data, and intent into trusted
10
10
 
11
11
  Decks are important, but they are render targets. The durable source of truth is the canonical narrative state: audience, decision, thesis, claims, evidence boundaries, objections, risks, research gaps, approval provenance, and artifact coverage.
12
12
 
13
- Default mode is narrative-first. Do not generate HTML slides, choose layouts, fetch design CSS/components, or ask for slide count unless the user explicitly enters a make-deck workflow or asks for design work.
13
+ Default mode is narrative-first. Do not generate HTML slides, choose layouts, fetch design CSS/components, or ask for slide count unless the user explicitly enters `/revela make --deck` or asks for design work.
14
14
 
15
15
  ## Workflow Model
16
16
 
@@ -27,17 +27,15 @@ Public command surface:
27
27
  - `/revela init`
28
28
  - `/revela research`
29
29
  - `/revela story`
30
- - `/revela make deck`
31
- - `/revela make brief`
32
- - `/revela refine`
30
+ - `/revela make --deck`
31
+ - `/revela make --brief`
32
+ - `/revela refine --deck`
33
+ - `/revela export --deck pdf`
34
+ - `/revela export --deck pptx`
33
35
  - `/revela design`
36
+ - `/revela domain`
34
37
 
35
- Compatibility aliases:
36
-
37
- - `/revela review` means a legacy story readiness report
38
- - `/revela narrative` means `/revela story`
39
- - `/revela deck` means `/revela make deck`
40
- - `/revela brief` means `/revela make brief`
38
+ Deprecated compatibility aliases such as `/revela review`, `/revela narrative`, `/revela deck`, `/revela brief`, `/revela inspect`, `/revela edit`, `/revela pdf`, `/revela pptx`, `/revela designs*`, and `/revela domains*` are no longer public commands. Direct users to `/revela` for current REVELA Help.
41
39
 
42
40
  ## Workspace State
43
41
 
@@ -87,7 +85,7 @@ During research:
87
85
 
88
86
  When the user invokes `/revela story`, open the read-only story workspace UI. Do not turn that command into a blocking readiness report.
89
87
 
90
- When the user invokes `/revela review` or explicitly asks for a readiness report, call `revela-decks` action `reviewNarrative` and report the tool result as authoritative.
88
+ When the user explicitly asks for a readiness report, call `revela-decks` action `reviewNarrative` and report the tool result as authoritative.
91
89
 
92
90
  Use this report shape:
93
91
 
@@ -104,7 +102,7 @@ If the narrative is ready for approval, ask the user whether to approve or revis
104
102
 
105
103
  ## Make Rules
106
104
 
107
- For `/revela make deck` and compatible deck handoff:
105
+ For `/revela make --deck` deck handoff:
108
106
 
109
107
  - switch to deck-render mode through the command workflow
110
108
  - check narrative readiness and current approval before compiling deck specs
@@ -113,22 +111,22 @@ For `/revela make deck` and compatible deck handoff:
113
111
  - fetch design layouts/components only after narrative handoff is valid
114
112
  - keep the HTML deck contract valid: one `<section class="slide">` per slide, canonical 1-based `data-slide-index`, and matching `DECKS.json` slide specs
115
113
 
116
- For `/revela make brief`, render the executive brief from canonical narrative state and graph-backed claim/evidence relationships, not from a deck summary.
114
+ For `/revela make --brief`, render the executive brief from canonical narrative state and graph-backed claim/evidence relationships, not from a deck summary.
117
115
 
118
- If story readiness, approval, evidence, or artifact blockers remain, report the blocker and suggest `/revela review`, `/revela research`, or a targeted user answer. Do not bypass with invented state.
116
+ If story readiness, approval, evidence, or artifact blockers remain, report the blocker and suggest `/revela story`, `/revela research`, or a targeted user answer. Do not bypass with invented state.
119
117
 
120
118
  ## Refine Rules
121
119
 
122
- Use `/revela refine` for post-artifact reading, inspection, and editing.
120
+ Use `/revela refine --deck` for post-artifact reading, inspection, and editing.
123
121
 
124
122
  - Reading should explain source, support strength, caveat, unsupported scope, narrative purpose, related risks/objections, research gaps, and artifact coverage.
125
123
  - Pure artifact polish may stay artifact-level: layout, typography, spacing, crop, visual hierarchy, export mechanics, and deck contract fixes.
126
124
  - Meaning-changing edits must update canonical narrative first, then run story readiness/approval or explicit override, then remake affected artifacts.
127
- - `/revela edit` has been removed; use `/revela refine`. Deprecated `/revela inspect` routes to Refine.
125
+ - `/revela edit` and `/revela inspect` have been removed from the public surface; use `/revela refine --deck`.
128
126
 
129
127
  ## Design Surface
130
128
 
131
- Use `/revela design` for visual-system work: list/use/new/edit/preview/install/remove designs.
129
+ Use `/revela design` for visual-system work: list, `--use`, `--new`, `--edit`, `--preview`, `--add`, and `--rm` designs. Use `/revela domain` for domain list, `--use`, `--add`, and `--rm`.
132
130
 
133
131
  Do not inject design CSS, layout catalogs, component indexes, chart rules, or deck HTML skeletons during init, research, or story. Fetch design context only for make-deck or explicit design-authoring workflows.
134
132