@cyber-dash-tech/revela 0.15.2 → 0.15.4

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/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,131 @@ 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
344
+ if (sub === "review") {
345
+ if (param !== "--deck") {
346
+ await send("Usage: `/revela review --deck`.")
347
+ throw new Error("__REVELA_REVIEW_USAGE_HANDLED__")
487
348
  }
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
349
+ await handleRefine({ client, sessionID, workspaceRoot }, send)
350
+ throw new Error("__REVELA_REVIEW_HANDLED__")
497
351
  }
498
352
  if (sub === "refine") {
499
- if (param) {
500
- await send("`/revela refine` does not accept a target. It opens the only HTML deck in `decks/`.")
353
+ if (param !== "--deck") {
354
+ await send("Usage: `/revela review --deck`.")
501
355
  throw new Error("__REVELA_REFINE_USAGE_HANDLED__")
502
356
  }
357
+ await send("`/revela refine --deck` is deprecated. Use `/revela review --deck`.")
503
358
  await handleRefine({ client, sessionID, workspaceRoot }, send)
504
359
  throw new Error("__REVELA_REFINE_HANDLED__")
505
360
  }
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__")
361
+ if (sub === "export") {
362
+ const target = args[1]?.toLowerCase() ?? ""
363
+ const format = args[2]?.toLowerCase() ?? ""
364
+ const exportParam = args.slice(3).join(" ")
365
+ if (target !== "--deck" || (format !== "pdf" && format !== "pptx")) {
366
+ await send("Usage: `/revela export --deck pdf [file.html]` or `/revela export --deck pptx [file.html] [--notes]`.")
367
+ throw new Error("__REVELA_EXPORT_USAGE_HANDLED__")
368
+ }
369
+ if (format === "pdf") {
370
+ await handlePdf(exportParam, send, workspaceRoot)
371
+ throw new Error("__REVELA_EXPORT_PDF_HANDLED__")
372
+ }
373
+ const pptxArgs = parsePptxArgs(exportParam)
374
+ if (pptxArgs.notes) {
375
+ try {
376
+ const deck = resolvePptxDeck(workspaceRoot, pptxArgs.filePath)
377
+ queueWorkflowCommand({
378
+ sessionID,
379
+ name: "export --deck pptx --notes",
380
+ mode: "deck-render",
381
+ visibleText: "Export Revela deck to PPTX with speaker notes.",
382
+ hiddenPrompt: buildPptxNotesPrompt(deck),
383
+ output,
384
+ })
385
+ return
386
+ } catch (e) {
387
+ const msg = e instanceof Error ? e.message : String(e)
388
+ await send(`**PPTX export failed**\n\n\`\`\`\n${msg}\n\`\`\``)
389
+ throw new Error("__REVELA_EXPORT_PPTX_HANDLED__")
390
+ }
518
391
  }
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__")
392
+ await handlePptx(exportParam, send, workspaceRoot)
393
+ throw new Error("__REVELA_EXPORT_PPTX_HANDLED__")
541
394
  }
542
395
  if (sub === "design") {
543
- const designAction = args[1]?.toLowerCase() ?? "list"
396
+ const designAction = args[1]?.toLowerCase() ?? ""
544
397
  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
- }
398
+ if (!designAction) {
550
399
  await handleDesignsList(send)
551
400
  throw new Error("__REVELA_DESIGN_LIST_HANDLED__")
552
401
  }
553
- if (designAction === "use") {
402
+ if (designAction === "--use") {
554
403
  if (!designParam) {
555
- await send("Usage: `/revela design use <name>`.")
404
+ await send("Usage: `/revela design --use <name>`.")
556
405
  throw new Error("__REVELA_DESIGN_USE_USAGE_HANDLED__")
557
406
  }
558
407
  await handleDesignsActivate(designParam, send)
559
408
  throw new Error("__REVELA_DESIGN_USE_HANDLED__")
560
409
  }
561
- if (designAction === "add") {
410
+ if (designAction === "--add") {
562
411
  if (!designParam) {
563
- await send("Usage: `/revela design add <url|github:user/repo|local-path>`.")
412
+ await send("Usage: `/revela design --add <url|github:user/repo|local-path>`.")
564
413
  throw new Error("__REVELA_DESIGN_ADD_USAGE_HANDLED__")
565
414
  }
566
415
  await handleDesignsAdd(designParam, send)
567
416
  throw new Error("__REVELA_DESIGN_ADD_HANDLED__")
568
417
  }
569
- if (designAction === "rm" || designAction === "remove") {
418
+ if (designAction === "--rm") {
570
419
  if (!designParam) {
571
- await send("Usage: `/revela design rm <name>`.")
420
+ await send("Usage: `/revela design --rm <name>`.")
572
421
  throw new Error("__REVELA_DESIGN_RM_USAGE_HANDLED__")
573
422
  }
574
423
  await handleDesignsRemove(designParam, send)
575
424
  throw new Error("__REVELA_DESIGN_RM_HANDLED__")
576
425
  }
577
- if (designAction === "preview") {
426
+ if (designAction === "--preview") {
578
427
  await handleDesignsPreview(designParam, send)
579
428
  throw new Error("__REVELA_DESIGN_PREVIEW_HANDLED__")
580
429
  }
581
- if (designAction === "new") {
430
+ if (designAction === "--new") {
582
431
  const parsed = parseDesignsNewArgs(designParam)
583
432
  if (!parsed.ok) {
584
- await send(parsed.error.replaceAll("/revela designs-new", "/revela design new"))
433
+ await send(parsed.error)
585
434
  throw new Error("__REVELA_DESIGN_NEW_USAGE_HANDLED__")
586
435
  }
587
436
  queueWorkflowCommand({
588
437
  sessionID,
589
- name: `design new ${parsed.name}`,
438
+ name: `design --new ${parsed.name}`,
590
439
  mode: "deck-render",
591
440
  visibleText: `Create Revela design ${parsed.name}.`,
592
441
  hiddenPrompt: buildDesignsNewPrompt({ name: parsed.name, base: parsed.base }),
@@ -594,15 +443,15 @@ const server: Plugin = (async (pluginCtx) => {
594
443
  })
595
444
  return
596
445
  }
597
- if (designAction === "edit") {
446
+ if (designAction === "--edit") {
598
447
  const parsed = parseDesignsEditArgs(designParam)
599
448
  if (!parsed.ok) {
600
- await send(parsed.error.replaceAll("/revela designs-edit", "/revela design edit"))
449
+ await send(parsed.error)
601
450
  throw new Error("__REVELA_DESIGN_EDIT_USAGE_HANDLED__")
602
451
  }
603
452
  queueWorkflowCommand({
604
453
  sessionID,
605
- name: `design edit ${parsed.name}`,
454
+ name: `design --edit ${parsed.name}`,
606
455
  mode: "deck-render",
607
456
  visibleText: `Edit Revela design ${parsed.name}.`,
608
457
  hiddenPrompt: buildDesignsEditPrompt({ name: parsed.name }),
@@ -610,83 +459,93 @@ const server: Plugin = (async (pluginCtx) => {
610
459
  })
611
460
  return
612
461
  }
613
- await send("Usage: `/revela design [list|use <name>|new <name>|edit <name>|preview [name]|add <source>|rm <name>]`.")
462
+ await send("Usage: `/revela design [--use <name>|--preview [name]|--new <name>|--edit <name>|--add <source>|--rm <name>]`.")
614
463
  throw new Error("__REVELA_DESIGN_USAGE_HANDLED__")
615
464
  }
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__")
465
+ if (sub === "domain") {
466
+ const domainAction = args[1]?.toLowerCase() ?? ""
467
+ const domainParam = args.slice(2).join(" ")
468
+ if (!domainAction) {
469
+ await handleDomainsList(send)
470
+ throw new Error("__REVELA_DOMAIN_LIST_HANDLED__")
471
+ }
472
+ if (domainAction === "--use") {
473
+ if (!domainParam) {
474
+ await send("Usage: `/revela domain --use <name>`.")
475
+ throw new Error("__REVELA_DOMAIN_USE_USAGE_HANDLED__")
476
+ }
477
+ await handleDomainsActivate(domainParam, send)
478
+ throw new Error("__REVELA_DOMAIN_USE_HANDLED__")
479
+ }
480
+ if (domainAction === "--add") {
481
+ if (!domainParam) {
482
+ await send("Usage: `/revela domain --add <url|github:user/repo|local-path>`.")
483
+ throw new Error("__REVELA_DOMAIN_ADD_USAGE_HANDLED__")
484
+ }
485
+ await handleDomainsAdd(domainParam, send)
486
+ throw new Error("__REVELA_DOMAIN_ADD_HANDLED__")
621
487
  }
488
+ if (domainAction === "--rm") {
489
+ if (!domainParam) {
490
+ await send("Usage: `/revela domain --rm <name>`.")
491
+ throw new Error("__REVELA_DOMAIN_RM_USAGE_HANDLED__")
492
+ }
493
+ await handleDomainsRemove(domainParam, send)
494
+ throw new Error("__REVELA_DOMAIN_RM_HANDLED__")
495
+ }
496
+ await send("Usage: `/revela domain [--use <name>|--add <source>|--rm <name>]`.")
497
+ throw new Error("__REVELA_DOMAIN_USAGE_HANDLED__")
498
+ }
499
+ const legacyCommands = new Set([
500
+ "enable", "disable", "review", "narrative", "deck", "brief", "edit", "inspect", "remember",
501
+ "designs", "designs-new", "designs-edit", "designs-preview", "designs-add", "designs-rm",
502
+ "domains", "domains-add", "domains-rm", "pdf", "pptx",
503
+ ])
504
+ if (legacyCommands.has(sub)) {
505
+ await send(`\`/revela ${sub}\` is no longer a public command. Run \`/revela\` to see the current REVELA help.`)
506
+ throw new Error("__REVELA_LEGACY_COMMAND_HANDLED__")
507
+ }
508
+ if (sub === "init") {
622
509
  queueWorkflowCommand({
623
510
  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 }),
511
+ name: "init",
512
+ mode: "narrative",
513
+ visibleText: "Initialize Revela workspace.",
514
+ hiddenPrompt: buildInitPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
628
515
  output,
629
516
  })
630
517
  return
631
518
  }
632
- if (sub === "designs-edit") {
633
- const parsed = parseDesignsEditArgs(param)
634
- if (!parsed.ok) {
635
- await send(parsed.error)
636
- throw new Error("__REVELA_DESIGNS_EDIT_USAGE_HANDLED__")
519
+ if (sub === "research") {
520
+ if (param) {
521
+ 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.")
522
+ throw new Error("__REVELA_RESEARCH_USAGE_HANDLED__")
637
523
  }
638
524
  queueWorkflowCommand({
639
525
  sessionID,
640
- name: `designs-edit ${parsed.name}`,
641
- mode: "deck-render",
642
- visibleText: `Edit Revela design ${parsed.name}.`,
643
- hiddenPrompt: buildDesignsEditPrompt({ name: parsed.name }),
526
+ name: "research",
527
+ mode: "narrative",
528
+ visibleText: "Research Revela story gaps.",
529
+ hiddenPrompt: buildResearchPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
644
530
  output,
645
531
  })
646
532
  return
647
533
  }
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
- }
534
+ if (sub === "story") {
535
+ const parsed = parseStoryArgs(param)
536
+ if (!parsed.ok) {
537
+ await send(parsed.error)
538
+ throw new Error("__REVELA_STORY_USAGE_HANDLED__")
687
539
  }
688
- await handlePptx(param, send, workspaceRoot)
689
- throw new Error("__REVELA_PPTX_HANDLED__")
540
+ queueWorkflowCommand({
541
+ sessionID,
542
+ name: "story",
543
+ mode: "narrative",
544
+ visibleText: "Open Revela story workspace.",
545
+ hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: parsed.args.language }),
546
+ output,
547
+ })
548
+ return
690
549
  }
691
550
 
692
551
  await send(`**Unknown sub-command:** \`${sub}\`\nRun \`/revela\` to see available commands.`)
@@ -817,7 +676,7 @@ const server: Plugin = (async (pluginCtx) => {
817
676
  // This prevents a silent "revela enabled but not working" scenario.
818
677
  output.system.push(
819
678
  "\n\n[REVELA ERROR: Failed to load the slide generation prompt. " +
820
- "Run /revela disable then /revela enable to reinitialize.]"
679
+ "Run /revela to confirm the plugin is available, then retry the workflow command.]"
821
680
  )
822
681
  }
823
682
  },
@@ -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
 
@@ -20,24 +20,22 @@ Use the same phase semantics whether the user invokes a slash command or asks in
20
20
  - `Research` runs closed loops to fill open story gaps, bind supported findings into canonical evidence, narrow overbroad claims/relations, and reduce caveats without crossing evidence boundaries.
21
21
  - `Story` opens the read-only story workspace UI for inspecting claim flow, evidence strength, unsupported scope, caveats, objections, risks, research gaps, approval state, and affected artifacts.
22
22
  - `Make` renders an artifact from approved or explicitly overridden narrative state. Supported 0.15 targets are deck and executive brief.
23
- - `Refine` is the post-artifact workspace for reading, inspection, and targeted editing. Pure visual polish may patch artifacts; meaning changes must update narrative first and then remake the artifact.
23
+ - `Review` is the post-artifact workspace for reading, insight, and targeted commenting. Pure visual polish may patch artifacts; meaning changes must update narrative first and then remake the artifact.
24
24
 
25
25
  Public command surface:
26
26
 
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 review --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
- ## Refine Rules
118
+ ## Review Rules
121
119
 
122
- Use `/revela refine` for post-artifact reading, inspection, and editing.
120
+ Use `/revela review --deck` for post-artifact reading, insight, and commenting.
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 review --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