@cyber-dash-tech/revela 0.15.2 → 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.
- package/README.md +58 -104
- package/README.zh-CN.md +59 -104
- package/designs/starter/DESIGN.md +33 -14
- package/designs/starter/preview.html +23 -16
- package/designs/summit/DESIGN.md +35 -42
- package/designs/summit/preview.html +49 -49
- package/lib/commands/brief.ts +1 -1
- package/lib/commands/designs-new.ts +6 -6
- package/lib/commands/designs.ts +9 -9
- package/lib/commands/domains.ts +9 -9
- package/lib/commands/edit.ts +1 -1
- package/lib/commands/help.ts +34 -37
- package/lib/commands/init.ts +1 -1
- package/lib/commands/inspect.ts +2 -20
- package/lib/commands/narrative.ts +3 -3
- package/lib/commands/pdf.ts +3 -3
- package/lib/commands/pptx.ts +2 -2
- package/lib/commands/review.ts +13 -6
- package/lib/decks-state.ts +6 -6
- package/lib/edit/deck-state.ts +1 -1
- package/lib/edit/resolve-deck.ts +1 -1
- package/lib/inspect/server.ts +2 -2
- package/lib/prompt-builder.ts +20 -14
- package/package.json +1 -1
- package/plugin.ts +133 -283
- package/skill/NARRATIVE_SKILL.md +15 -17
- package/skill/SKILL.md +220 -477
- package/tools/edit.ts +1 -1
- package/tools/inspection-result.ts +1 -1
- package/lib/commands/disable.ts +0 -14
- package/lib/commands/enable.ts +0 -48
package/plugin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* revela — Core OpenCode Plugin
|
|
3
3
|
*
|
|
4
|
-
* Architecture:
|
|
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,
|
|
65
|
-
import {
|
|
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: "
|
|
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
|
|
445
|
-
await send("Usage: `/revela make
|
|
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:
|
|
324
|
+
name: "make --deck",
|
|
451
325
|
mode: "deck-render",
|
|
452
|
-
visibleText:
|
|
453
|
-
hiddenPrompt:
|
|
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
|
|
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
|
|
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 === "
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
|
520
|
-
throw new Error("
|
|
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() ?? "
|
|
387
|
+
const designAction = args[1]?.toLowerCase() ?? ""
|
|
544
388
|
const designParam = args.slice(2).join(" ")
|
|
545
|
-
if (designAction
|
|
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"
|
|
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
|
|
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
|
|
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 [
|
|
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 === "
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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:
|
|
625
|
-
mode: "
|
|
626
|
-
visibleText:
|
|
627
|
-
hiddenPrompt:
|
|
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 === "
|
|
633
|
-
const parsed =
|
|
525
|
+
if (sub === "story") {
|
|
526
|
+
const parsed = parseStoryArgs(param)
|
|
634
527
|
if (!parsed.ok) {
|
|
635
528
|
await send(parsed.error)
|
|
636
|
-
throw new Error("
|
|
529
|
+
throw new Error("__REVELA_STORY_USAGE_HANDLED__")
|
|
637
530
|
}
|
|
638
531
|
queueWorkflowCommand({
|
|
639
532
|
sessionID,
|
|
640
|
-
name:
|
|
641
|
-
mode: "
|
|
642
|
-
visibleText:
|
|
643
|
-
hiddenPrompt:
|
|
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
|
|
670
|
+
"Run /revela to confirm the plugin is available, then retry the workflow command.]"
|
|
821
671
|
)
|
|
822
672
|
}
|
|
823
673
|
},
|
package/skill/NARRATIVE_SKILL.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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`
|
|
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
|
|
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`
|
|
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
|
|
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
|
|