@cyber-dash-tech/revela 0.17.23 → 0.18.2

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 (34) hide show
  1. package/README.md +24 -25
  2. package/README.zh-CN.md +25 -26
  3. package/bin/revela.ts +2 -4
  4. package/lib/commands/help.ts +13 -13
  5. package/lib/commands/init.ts +24 -0
  6. package/lib/commands/png.ts +29 -0
  7. package/lib/commands/refine.ts +1 -1
  8. package/lib/commands/research.ts +24 -0
  9. package/lib/commands/review.ts +92 -14
  10. package/lib/decks-state.ts +7 -7
  11. package/lib/design/designs.ts +44 -0
  12. package/lib/narrative-state/deck-plan-artifact.ts +849 -19
  13. package/lib/narrative-state/render-plan.ts +13 -14
  14. package/lib/pdf/export.ts +84 -24
  15. package/lib/refine/server.ts +4 -3
  16. package/lib/runtime/index.ts +52 -7
  17. package/lib/runtime/review.ts +4 -104
  18. package/lib/workspace-state/render-targets.ts +2 -2
  19. package/lib/workspace-state/rendered-artifacts.ts +1 -1
  20. package/lib/workspace-state/types.ts +1 -1
  21. package/package.json +1 -1
  22. package/plugin.ts +31 -42
  23. package/plugins/revela/.codex-plugin/plugin.json +2 -2
  24. package/plugins/revela/.mcp.json +1 -1
  25. package/plugins/revela/mcp/revela-server.ts +118 -58
  26. package/plugins/revela/skills/revela-design/SKILL.md +9 -1
  27. package/plugins/revela/skills/revela-domain/SKILL.md +1 -1
  28. package/plugins/revela/skills/revela-export/SKILL.md +4 -5
  29. package/plugins/revela/skills/revela-init/SKILL.md +19 -34
  30. package/plugins/revela/skills/revela-make-deck/SKILL.md +15 -34
  31. package/plugins/revela/skills/revela-research/SKILL.md +17 -26
  32. package/plugins/revela/skills/revela-review-deck/SKILL.md +11 -29
  33. package/skill/SKILL.md +22 -19
  34. package/plugins/revela/skills/revela-story/SKILL.md +0 -24
package/plugin.ts CHANGED
@@ -44,6 +44,7 @@ import {
44
44
  } from "./lib/commands/domains"
45
45
  import { handlePdf } from "./lib/commands/pdf"
46
46
  import { buildPptxNotesPrompt, handlePptx, parsePptxArgs, resolvePptxDeck } from "./lib/commands/pptx"
47
+ import { handlePng } from "./lib/commands/png"
47
48
  import { handleRefine } from "./lib/commands/refine"
48
49
  import { formatArtifactQAReport, runArtifactQA } from "./lib/qa/artifact"
49
50
  import { ensureRefineDeckOpenForChange } from "./lib/refine/open"
@@ -57,9 +58,7 @@ import {
57
58
  } from "./lib/commands/designs-new"
58
59
  import { buildInitPrompt } from "./lib/commands/init"
59
60
  import { buildResearchPrompt } from "./lib/commands/research"
60
- import { handleBrief, parseBriefArgs } from "./lib/commands/brief"
61
- import { buildNarrativeViewPrompt, parseStoryArgs } from "./lib/commands/narrative"
62
- import { buildDeckPrompt } from "./lib/commands/review"
61
+ import { buildDeckMakePrompt, buildDeckPlanPrompt } from "./lib/commands/review"
63
62
  import {
64
63
  extractDeckHtmlTargetsFromPatch,
65
64
  extractPatchTextArg,
@@ -87,9 +86,6 @@ import mediaBatchSaveTool from "./tools/media-batch-save"
87
86
  import mediaSaveTool from "./tools/media-save"
88
87
  import researchImagesListTool from "./tools/research-images-list"
89
88
  import researchSaveTool from "./tools/research-save"
90
- import inspectionContextTool from "./tools/inspection-context"
91
- import inspectionResultTool from "./tools/inspection-result"
92
- import narrativeViewTool from "./tools/narrative-view"
93
89
  import workspaceScanTool from "./tools/workspace-scan"
94
90
  import extractDocumentMaterialsTool from "./tools/extract-document-materials"
95
91
  import qaTool from "./tools/qa"
@@ -356,24 +352,32 @@ const server: Plugin = (async (pluginCtx) => {
356
352
  sessionID,
357
353
  name: "make --deck",
358
354
  mode: "deck-render",
359
- visibleText: "Make Revela deck from approved story.",
360
- hiddenPrompt: buildDeckPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
355
+ visibleText: "Make Revela deck from deck-plan.",
356
+ hiddenPrompt: buildDeckMakePrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
361
357
  output,
362
358
  })
363
359
  return
364
360
  }
365
- if (target === "--brief") {
366
- const parsed = parseBriefArgs(makeParam)
367
- if (!parsed.ok) {
368
- await send(parsed.error.replace("/revela brief", "/revela make --brief"))
369
- throw new Error("__REVELA_MAKE_BRIEF_USAGE_HANDLED__")
370
- }
371
- await handleBrief({ workspaceRoot, outputPath: parsed.args.outputPath }, send)
372
- throw new Error("__REVELA_MAKE_BRIEF_HANDLED__")
373
- }
374
- await send("Usage: `/revela make --deck` or `/revela make --brief [workspace-relative-output.md]`.")
361
+ await send("Usage: `/revela make --deck`.")
375
362
  throw new Error("__REVELA_MAKE_USAGE_HANDLED__")
376
363
  }
364
+ if (sub === "plan") {
365
+ const target = args[1]?.toLowerCase() ?? ""
366
+ const planParam = args.slice(2).join(" ")
367
+ if (target !== "--deck" || planParam) {
368
+ await send("Usage: `/revela plan --deck`.")
369
+ throw new Error("__REVELA_PLAN_USAGE_HANDLED__")
370
+ }
371
+ queueWorkflowCommand({
372
+ sessionID,
373
+ name: "plan --deck",
374
+ mode: "deck-render",
375
+ visibleText: "Plan Revela deck from local materials and research.",
376
+ hiddenPrompt: buildDeckPlanPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
377
+ output,
378
+ })
379
+ return
380
+ }
377
381
  if (sub === "review") {
378
382
  if (param !== "--deck") {
379
383
  await send("Usage: `/revela review --deck`.")
@@ -395,14 +399,18 @@ const server: Plugin = (async (pluginCtx) => {
395
399
  const target = args[1]?.toLowerCase() ?? ""
396
400
  const format = args[2]?.toLowerCase() ?? ""
397
401
  const exportParam = args.slice(3).join(" ")
398
- if (target !== "--deck" || (format !== "pdf" && format !== "pptx")) {
399
- await send("Usage: `/revela export --deck pdf [file.html]` or `/revela export --deck pptx [file.html] [--notes]`.")
402
+ if (target !== "--deck" || (format !== "pdf" && format !== "pptx" && format !== "png")) {
403
+ await send("Usage: `/revela export --deck pdf [file.html]`, `/revela export --deck pptx [file.html] [--notes]`, or `/revela export --deck png [file.html]`.")
400
404
  throw new Error("__REVELA_EXPORT_USAGE_HANDLED__")
401
405
  }
402
406
  if (format === "pdf") {
403
407
  await handlePdf(exportParam, send, workspaceRoot)
404
408
  throw new Error("__REVELA_EXPORT_PDF_HANDLED__")
405
409
  }
410
+ if (format === "png") {
411
+ await handlePng(exportParam, send, workspaceRoot)
412
+ throw new Error("__REVELA_EXPORT_PNG_HANDLED__")
413
+ }
406
414
  const pptxArgs = parsePptxArgs(exportParam)
407
415
  if (pptxArgs.notes) {
408
416
  try {
@@ -530,7 +538,7 @@ const server: Plugin = (async (pluginCtx) => {
530
538
  throw new Error("__REVELA_DOMAIN_USAGE_HANDLED__")
531
539
  }
532
540
  const legacyCommands = new Set([
533
- "review", "narrative", "deck", "brief", "edit", "inspect", "remember",
541
+ "narrative", "deck", "brief", "edit", "inspect", "story", "remember",
534
542
  "designs", "designs-new", "designs-edit", "designs-preview", "designs-add", "designs-rm",
535
543
  "domains", "domains-add", "domains-rm", "pdf", "pptx",
536
544
  ])
@@ -551,35 +559,19 @@ const server: Plugin = (async (pluginCtx) => {
551
559
  }
552
560
  if (sub === "research") {
553
561
  if (param) {
554
- 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.")
562
+ await send("`/revela research` does not accept arguments yet. Add the research question in normal chat, or run it to work from deck inputs and unresolved source needs.")
555
563
  throw new Error("__REVELA_RESEARCH_USAGE_HANDLED__")
556
564
  }
557
565
  queueWorkflowCommand({
558
566
  sessionID,
559
567
  name: "research",
560
568
  mode: "narrative",
561
- visibleText: "Research Revela story gaps.",
569
+ visibleText: "Research Revela deck inputs.",
562
570
  hiddenPrompt: buildResearchPrompt({ exists: hasDecksState(workspaceRoot), workspaceRoot }),
563
571
  output,
564
572
  })
565
573
  return
566
574
  }
567
- if (sub === "story") {
568
- const parsed = parseStoryArgs(param)
569
- if (!parsed.ok) {
570
- await send(parsed.error)
571
- throw new Error("__REVELA_STORY_USAGE_HANDLED__")
572
- }
573
- queueWorkflowCommand({
574
- sessionID,
575
- name: "story",
576
- mode: "narrative",
577
- visibleText: "Open Revela story workspace.",
578
- hiddenPrompt: buildNarrativeViewPrompt({ workspaceRoot, language: parsed.args.language }),
579
- output,
580
- })
581
- return
582
- }
583
575
 
584
576
  await send(`**Unknown sub-command:** \`${sub}\`\nRun \`/revela\` to see available commands.`)
585
577
  throw new Error("__REVELA_UNKNOWN_HANDLED__")
@@ -596,9 +588,6 @@ const server: Plugin = (async (pluginCtx) => {
596
588
  "revela-media-save": mediaSaveTool,
597
589
  "revela-research-images-list": researchImagesListTool,
598
590
  "revela-research-save": researchSaveTool,
599
- "revela-inspection-context": inspectionContextTool,
600
- "revela-inspection-result": inspectionResultTool,
601
- "revela-narrative-view": narrativeViewTool,
602
591
  "revela-workspace-scan": workspaceScanTool,
603
592
  "revela-extract-document-materials": extractDocumentMaterialsTool,
604
593
  "revela-qa": qaTool,
@@ -20,7 +20,7 @@
20
20
  "interface": {
21
21
  "displayName": "Revela",
22
22
  "shortDescription": "Trusted narrative artifacts from local sources and research.",
23
- "longDescription": "Revela helps Codex initialize a narrative vault, bind evidence, plan decks, generate artifact foundations, run QA, and export decision artifacts while preserving source traceability.",
23
+ "longDescription": "Revela helps Codex ingest local materials, save research findings, plan decks, generate HTML deck artifacts, review them, and export PDF/PPTX/PNG outputs while preserving source traceability.",
24
24
  "developerName": "cyber-dash-tech",
25
25
  "category": "Productivity",
26
26
  "capabilities": [
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "defaultPrompt": [
31
31
  "Use Revela to initialize this workspace.",
32
- "Use Revela to make a deck from the narrative.",
32
+ "Use Revela to make a deck from the deck plan.",
33
33
  "Use Revela to review this deck artifact."
34
34
  ],
35
35
  "brandColor": "#2563EB"
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "revela": {
4
4
  "command": "npx",
5
- "args": ["-y", "@cyber-dash-tech/revela@0.17.23", "mcp"]
5
+ "args": ["-y", "@cyber-dash-tech/revela@0.18.2", "mcp"]
6
6
  }
7
7
  }
8
8
  }
@@ -10,13 +10,13 @@ type JsonRpcRequest = {
10
10
 
11
11
  type RuntimeModule = {
12
12
  doctor(input?: any): any
13
- compileNarrative(input?: any): any
14
- markdownQa(input?: any): any
15
13
  readDeckPlan(input?: any): any
14
+ upsertDeckPlanSlide(input: any): any
16
15
  createDeckFoundation(input: any): any
17
16
  runDeckQa(input: any): Promise<any>
18
17
  exportPdf(input: any): Promise<any>
19
18
  exportPptx(input: any): Promise<any>
19
+ exportPng(input: any): Promise<any>
20
20
  designList(): any
21
21
  designRead(input?: any): any
22
22
  designInventory(input?: any): any
@@ -36,13 +36,9 @@ type RuntimeModule = {
36
36
  domainDraftCreate(input: any): any
37
37
  domainDraftValidate(input: any): any
38
38
  domainDraftInstall(input: any): any
39
- storyRead(input?: any): any
40
39
  reviewDeckRead(input: any): Promise<any>
41
40
  reviewDeckOpen(input: any): Promise<any>
42
- researchTargets(input?: any): any
43
41
  researchSave(input: any): any
44
- evaluateResearchFindings(input: any): any
45
- bindResearchFindings(input: any): any
46
42
  prepareLocalMaterials(input: any): Promise<any>
47
43
  extractMaterial(input: any): Promise<any>
48
44
  recordMaterialReview(input: any): any
@@ -58,24 +54,30 @@ const tools = [
58
54
  inputSchema: objectSchema({ workspaceRoot: stringProp("Optional workspace root.") }),
59
55
  },
60
56
  {
61
- name: "revela_compile_narrative",
62
- description: "Compile revela-narrative/ Markdown into canonical NarrativeStateV1 diagnostics.",
57
+ name: "revela_read_deck_plan",
58
+ description: "Read canonical deck-plan.md projection and diagnostics, with legacy deck-plan/ fallback support.",
63
59
  inputSchema: objectSchema({ workspaceRoot: stringProp("Optional workspace root.") }),
64
60
  },
65
61
  {
66
- name: "revela_markdown_qa",
67
- description: "Run Markdown QA for the Revela narrative vault.",
62
+ name: "revela_upsert_deck_plan_slide",
63
+ description: "Compatibility/repair helper for creating or updating one slide block in canonical deck-plan.md with active/requested design vocabulary validation. Normal planning should write deck-plan.md directly and use revela_read_deck_plan for diagnostics.",
68
64
  inputSchema: objectSchema({
69
65
  workspaceRoot: stringProp("Optional workspace root."),
70
- scope: enumProp(["touched", "affected", "full"], "QA scope."),
71
- strictness: enumProp(["authoring", "readiness", "render"], "QA strictness."),
72
- touched: arrayProp("Touched vault files."),
73
- }),
74
- },
75
- {
76
- name: "revela_read_deck_plan",
77
- description: "Read the file-native deck-plan/ projection and diagnostics.",
78
- inputSchema: objectSchema({ workspaceRoot: stringProp("Optional workspace root.") }),
66
+ designName: stringProp("Optional design name. Defaults to the active design."),
67
+ outputPath: stringProp("Optional workspace-relative HTML output path."),
68
+ slideIndex: requiredNumberProp("Positive 1-based slide index."),
69
+ id: stringProp("Optional stable slide node id."),
70
+ title: requiredStringProp("Slide title."),
71
+ chapter: requiredStringProp("Chapter name."),
72
+ narrativeRole: requiredStringProp("Slide's communication job."),
73
+ structural: booleanProp("Whether this is a structural slide such as cover, TOC, divider, or closing."),
74
+ layout: requiredStringProp("Design layout name from inventory."),
75
+ components: componentPlanArrayProp(),
76
+ visualIntent: visualIntentProp(),
77
+ sourceLinks: sourceLinksProp(),
78
+ narrativeLinks: narrativeLinksProp(),
79
+ caveats: arrayProp("Optional caveats to keep visible in the slide plan."),
80
+ }, ["slideIndex", "title", "chapter", "narrativeRole", "layout", "components", "visualIntent"]),
79
81
  },
80
82
  {
81
83
  name: "revela_create_deck_foundation",
@@ -114,6 +116,15 @@ const tools = [
114
116
  file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
115
117
  }, ["file"]),
116
118
  },
119
+ {
120
+ name: "revela_export_png",
121
+ description: "Export a Revela HTML deck to one PNG file per slide.",
122
+ inputSchema: objectSchema({
123
+ workspaceRoot: stringProp("Optional workspace root."),
124
+ file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
125
+ outputDir: stringProp("Optional workspace-relative output directory."),
126
+ }, ["file"]),
127
+ },
117
128
  {
118
129
  name: "revela_design_list",
119
130
  description: "List installed Revela designs and the active design.",
@@ -257,17 +268,9 @@ const tools = [
257
268
  overwrite: booleanProp("Whether to replace an existing user-level domain package. Defaults to false."),
258
269
  }, ["name"]),
259
270
  },
260
- {
261
- name: "revela_story_read",
262
- description: "Read a deterministic Revela Story map and optional Markdown view from the canonical narrative vault without mutating files.",
263
- inputSchema: objectSchema({
264
- workspaceRoot: stringProp("Optional workspace root."),
265
- format: enumProp(["map", "markdown"], "Return only the map, or include a formatted Markdown reading view."),
266
- }),
267
- },
268
271
  {
269
272
  name: "revela_review_deck_read",
270
- description: "Read-only aggregate Review diagnostics for a Revela HTML deck: artifact QA, deck-plan diagnostics, narrative/vault diagnostics, artifact coverage, and available evidence trace.",
273
+ description: "Read-only aggregate Review diagnostics for a Revela HTML deck: artifact QA, deck-plan diagnostics, and export/readiness signals.",
271
274
  inputSchema: objectSchema({
272
275
  workspaceRoot: stringProp("Optional workspace root."),
273
276
  file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
@@ -280,18 +283,13 @@ const tools = [
280
283
  inputSchema: objectSchema({
281
284
  workspaceRoot: stringProp("Optional workspace root."),
282
285
  file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
283
- bridge: enumProp(["codex-exec"], "Prompt bridge for browser Insight and Comment interactions."),
286
+ bridge: enumProp(["codex-exec"], "Prompt bridge for browser Comment and Apply Fix interactions."),
284
287
  openBrowser: booleanProp("Whether the tool should open the browser itself. Defaults to true when omitted."),
285
288
  }, ["file"]),
286
289
  },
287
- {
288
- name: "revela_research_targets",
289
- description: "Derive current Revela research targets from canonical narrative state, saved findings, and evidence gaps.",
290
- inputSchema: objectSchema({ workspaceRoot: stringProp("Optional workspace root.") }),
291
- },
292
290
  {
293
291
  name: "revela_research_save",
294
- description: "Save research findings under researches/{topic}/{filename}.md and evaluate binding readiness when workspace state exists.",
292
+ description: "Save source-linked research findings under researches/{topic}/{filename}.md for deck-plan use.",
295
293
  inputSchema: objectSchema({
296
294
  workspaceRoot: stringProp("Optional workspace root."),
297
295
  topic: requiredStringProp("Research topic key."),
@@ -300,23 +298,6 @@ const tools = [
300
298
  sources: arrayProp("Source URLs or workspace files for YAML frontmatter."),
301
299
  }, ["topic", "filename", "content"]),
302
300
  },
303
- {
304
- name: "revela_evaluate_research_findings",
305
- description: "Evaluate whether a saved researches/**/*.md findings file is safely bindable as canonical evidence.",
306
- inputSchema: objectSchema({
307
- workspaceRoot: stringProp("Optional workspace root."),
308
- findingsFile: requiredStringProp("Workspace-relative researches/**/*.md findings file."),
309
- }, ["findingsFile"]),
310
- },
311
- {
312
- name: "revela_bind_research_findings",
313
- description: "Bind a safely evaluated findings file into canonical revela-narrative/evidence/*.md evidence.",
314
- inputSchema: objectSchema({
315
- workspaceRoot: stringProp("Optional workspace root."),
316
- findingsFile: requiredStringProp("Workspace-relative researches/**/*.md findings file."),
317
- evidenceId: stringProp("Optional canonical evidence node id override."),
318
- }, ["findingsFile"]),
319
- },
320
301
  {
321
302
  name: "revela_prepare_local_materials",
322
303
  description: "Scan local workspace source materials, create/update the material-intake registry, and optionally extract Office/PDF files into read views.",
@@ -411,13 +392,13 @@ async function handle(req: JsonRpcRequest): Promise<any | undefined> {
411
392
  async function callTool(name: string, args: any): Promise<any> {
412
393
  const r = await runtime()
413
394
  if (name === "revela_doctor") return r.doctor(args)
414
- if (name === "revela_compile_narrative") return r.compileNarrative(args)
415
- if (name === "revela_markdown_qa") return r.markdownQa(args)
416
395
  if (name === "revela_read_deck_plan") return r.readDeckPlan(args)
396
+ if (name === "revela_upsert_deck_plan_slide") return r.upsertDeckPlanSlide(args)
417
397
  if (name === "revela_create_deck_foundation") return r.createDeckFoundation(args)
418
398
  if (name === "revela_run_deck_qa") return r.runDeckQa(args)
419
399
  if (name === "revela_export_pdf") return r.exportPdf(args)
420
400
  if (name === "revela_export_pptx") return r.exportPptx(args)
401
+ if (name === "revela_export_png") return r.exportPng(args)
421
402
  if (name === "revela_design_list") return r.designList()
422
403
  if (name === "revela_design_read") return r.designRead(args)
423
404
  if (name === "revela_design_inventory") return r.designInventory(args)
@@ -437,13 +418,9 @@ async function callTool(name: string, args: any): Promise<any> {
437
418
  if (name === "revela_domain_draft_create") return r.domainDraftCreate(args)
438
419
  if (name === "revela_domain_draft_validate") return r.domainDraftValidate(args)
439
420
  if (name === "revela_domain_draft_install") return r.domainDraftInstall(args)
440
- if (name === "revela_story_read") return r.storyRead(args)
441
421
  if (name === "revela_review_deck_read") return r.reviewDeckRead(args)
442
422
  if (name === "revela_review_deck_open") return r.reviewDeckOpen(args)
443
- if (name === "revela_research_targets") return r.researchTargets(args)
444
423
  if (name === "revela_research_save") return r.researchSave(args)
445
- if (name === "revela_evaluate_research_findings") return r.evaluateResearchFindings(args)
446
- if (name === "revela_bind_research_findings") return r.bindResearchFindings(args)
447
424
  if (name === "revela_prepare_local_materials") return r.prepareLocalMaterials(args)
448
425
  if (name === "revela_extract_document_materials") return r.extractMaterial(args)
449
426
  if (name === "revela_record_material_review") return r.recordMaterialReview(args)
@@ -479,6 +456,10 @@ function numberProp(description: string) {
479
456
  return { type: "number", description }
480
457
  }
481
458
 
459
+ function requiredNumberProp(description: string) {
460
+ return { type: "number", description }
461
+ }
462
+
482
463
  function enumProp(values: string[], description: string) {
483
464
  return { type: "string", enum: values, description }
484
465
  }
@@ -514,6 +495,85 @@ function arrayObjectProp(description: string) {
514
495
  }
515
496
  }
516
497
 
498
+ function componentPlanArrayProp() {
499
+ const childSchema: any = {
500
+ type: "object",
501
+ properties: {
502
+ name: { type: "string", description: "Design component name." },
503
+ slot: { type: "string", description: "Layout semantic slot from design inventory, such as left, right, top, bottom, fullbleed, or a numbered slot." },
504
+ position: { type: "string", description: "Slot-local kebab-case anchor, such as left-top, center, or overlay-top-right." },
505
+ purpose: { type: "string", description: "Component communication job." },
506
+ content: { type: "string", description: "Exact text, data, or structure to render." },
507
+ claimIds: { type: "array", items: { type: "string" } },
508
+ evidenceIds: { type: "array", items: { type: "string" } },
509
+ sourceNotes: { type: "array", items: { type: "string" } },
510
+ renderNotes: { type: "array", items: { type: "string" } },
511
+ placementNote: { type: "string" },
512
+ },
513
+ required: ["name", "slot", "position", "purpose", "content"],
514
+ additionalProperties: false,
515
+ }
516
+ const componentSchema: any = JSON.parse(JSON.stringify(childSchema))
517
+ componentSchema.properties.children = {
518
+ type: "array",
519
+ description: "Nested child components. Use box as the semantic container for grouped child content.",
520
+ items: childSchema,
521
+ }
522
+ return {
523
+ type: "array",
524
+ description: "Structured component plan entries.",
525
+ items: componentSchema,
526
+ }
527
+ }
528
+
529
+ function visualIntentProp() {
530
+ return {
531
+ anyOf: [
532
+ { type: "string" },
533
+ {
534
+ type: "object",
535
+ properties: {
536
+ kind: { type: "string" },
537
+ component: { type: "string" },
538
+ rationale: { type: "string" },
539
+ brief: { type: "string" },
540
+ },
541
+ additionalProperties: false,
542
+ },
543
+ ],
544
+ description: "Visual plan or structured visual intent. If component is set, it must exist in components[].name.",
545
+ }
546
+ }
547
+
548
+ function narrativeLinksProp() {
549
+ return {
550
+ type: "object",
551
+ properties: {
552
+ claimIds: { type: "array", items: { type: "string" } },
553
+ evidenceIds: { type: "array", items: { type: "string" } },
554
+ riskIds: { type: "array", items: { type: "string" } },
555
+ objectionIds: { type: "array", items: { type: "string" } },
556
+ gapIds: { type: "array", items: { type: "string" } },
557
+ },
558
+ additionalProperties: false,
559
+ }
560
+ }
561
+
562
+ function sourceLinksProp() {
563
+ return {
564
+ type: "object",
565
+ description: "Deck-first source links. Use these instead of narrativeLinks for new plans.",
566
+ properties: {
567
+ materials: { type: "array", items: { type: "string" } },
568
+ findings: { type: "array", items: { type: "string" } },
569
+ assets: { type: "array", items: { type: "string" } },
570
+ urls: { type: "array", items: { type: "string" } },
571
+ caveats: { type: "array", items: { type: "string" } },
572
+ },
573
+ additionalProperties: false,
574
+ }
575
+ }
576
+
517
577
  function writeMessage(message: any, mode: MessageMode = activeResponseMode): void {
518
578
  activeResponseMode = mode
519
579
  const body = JSON.stringify(message)
@@ -11,7 +11,7 @@ Use this skill when the user asks about Revela designs or when generating deck H
11
11
 
12
12
  1. Call `revela_design_list` to inspect installed designs.
13
13
  2. Call `revela_design_read` with `section: "rules"` before writing or patching `decks/*.html`; this records the Codex hook context required for deck writes.
14
- 3. Call `revela_design_inventory` before authoring or repairing `deck-plan/` so planned layout/component names come from the active design.
14
+ 3. Call `revela_design_inventory` before authoring or repairing `deck-plan.md` so planned layout names, slots, component names, and nesting hints come from the active design. Write slide plan Markdown directly, then call `revela_read_deck_plan` for diagnostics.
15
15
  4. Read required details with `revela_design_read_layout` and `revela_design_read_component` before writing slide HTML that uses those layouts/components.
16
16
  5. When the user asks to switch designs for future work, call `revela_design_activate` with the requested design name, then read the active design again.
17
17
  6. For one-off deck generation with a requested design, read that design by name, call `revela_design_inventory` with that name, and pass `designName` to `revela_create_deck_foundation` without changing active design unless the user asked to switch.
@@ -23,6 +23,14 @@ Deck HTML must keep exactly one direct `.slide-canvas` child inside every `<sect
23
23
 
24
24
  Design changes are visual/artifact-level unless they change claim meaning, evidence boundaries, decision, or recommendation.
25
25
 
26
+ ## Inventory-First Planning
27
+
28
+ Deck planning uses design vocabulary before HTML. Inspect the inventory, choose a valid layout for each slide, and choose valid component names for each planned element. Every top-level component plan must use a `slot` returned by the selected layout's inventory entry, plus a non-empty kebab-case `position` such as `left-top`, `left-middle`, `right-bottom`, `center`, or `overlay-top-right`.
29
+
30
+ Use `box` as the semantic container when several child components support one idea. Put children under `box.children`; do not repeat those child components as separate top-level component plan entries. `hero` is fullbleed-only, while `page-number` and `brand-watermark` are utilities.
31
+
32
+ Use `placementNote` for natural-language placement detail when slot and position are not enough. Slot and position are planning anchors; before HTML generation, fetch the actual layout/component definitions and implement the final structure with the design's CSS and markup.
33
+
26
34
  ## Creating Or Editing Designs
27
35
 
28
36
  When the user asks to create a new design, use `starter` as the default base design unless they specify another base. Interview the user before saving anything: collect visual references such as images, webpages, brands, decks, or text descriptions, plus must-have and must-avoid constraints. Summarize the design brief and visual schema, then wait for the user to confirm before creating files.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: revela-domain
3
- description: Use or switch Revela narrative domain guidance in Codex for init, research, and story work.
3
+ description: Use or switch Revela domain guidance in Codex for init, research, and deck planning work.
4
4
  ---
5
5
 
6
6
  # Revela Domain
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: revela-export
3
- description: Export Revela deck artifacts from Codex to PDF or PPTX.
3
+ description: Export Revela deck artifacts from Codex to PDF, PPTX, or PNG.
4
4
  ---
5
5
 
6
6
  # Revela Export
@@ -12,10 +12,9 @@ Use this skill when the user asks to export a Revela deck.
12
12
  1. Resolve the target HTML deck path.
13
13
  2. For PDF, call `revela_export_pdf`.
14
14
  3. For PPTX, call `revela_export_pptx`.
15
- 4. Report output path or export errors.
15
+ 4. For per-slide PNG files, call `revela_export_png`.
16
+ 5. Report output path(s), slide count, or export errors.
16
17
 
17
- `revela_run_deck_qa`, `revela_export_pdf`, and `revela_export_pptx` may launch a browser. In sandboxed Codex sessions, request user-approved command escalation when the browser cannot start inside the default sandbox.
18
+ `revela_run_deck_qa`, `revela_export_pdf`, `revela_export_pptx`, and `revela_export_png` may launch a browser. In sandboxed Codex sessions, request user-approved command escalation when the browser cannot start inside the default sandbox.
18
19
 
19
20
  Post-write hooks and explicit QA tools surface Artifact QA failures. If the latest visible QA result has hard errors, repair them before treating the deck as export-ready.
20
-
21
- Do not treat narrative gaps as export blockers unless they affect technical artifact validity or data safety.
@@ -1,46 +1,31 @@
1
1
  ---
2
2
  name: revela-init
3
- description: Initialize or refresh a Revela narrative workspace in Codex from local source materials, preserving source traceability and file-native state.
3
+ description: Initialize a Revela deck-first workspace in Codex from local source materials and material reviews.
4
4
  ---
5
5
 
6
6
  # Revela Init
7
7
 
8
- Use this skill when the user asks to start Revela, initialize the workspace, ingest local materials, or prepare a trusted narrative graph.
8
+ Use this skill when the user asks to start Revela, initialize the workspace, ingest local materials, or prepare source inputs for a deck.
9
9
 
10
10
  ## Product Contract
11
11
 
12
- - `revela-narrative/` is the editable source of truth for communication meaning when present.
13
- - `NarrativeStateV1` is the compiled internal interface.
14
- - `deck-plan/` is render planning, not canonical meaning.
15
- - `decks/*.html` are artifacts.
16
- - `DECKS.json` is compatibility/cache state, not workflow authority.
17
- - Do not invent quotes, source paths, URLs, page references, caveats, claim ids, evidence ids, or artifact coverage.
12
+ - Init prepares local source material intake; it does not create a Narrative Vault.
13
+ - Durable deck-first state is local material intake, material review files, `researches/`, `deck-plan.md`, `assets/`, and `decks/*.html`.
14
+ - Scan results prove only that files exist. A material is usable only after its direct text or extracted read view has been reviewed.
15
+ - Do not invent quotes, source paths, URLs, page references, caveats, licenses, or artifact coverage.
18
16
 
19
17
  ## Workflow
20
18
 
21
- 1. Call `revela_prepare_local_materials` first. Treat scan results as an intake registry and task list, not as source content.
22
- 2. For any registry entry with `requiresExtraction: true`, do not read the original Office/PDF file directly for narrative intake. Use the returned `allowedReadPath` / `read_view_path`; if missing, call `revela_extract_document_materials` first.
23
- 3. Prefer local source materials first: Markdown, text, CSV, PDFs, Office files, existing `researches/`, existing `revela-narrative/`, `deck-plan/`, and `decks/`.
24
- 4. After reading extracted material views, call `revela_record_material_review` for each considered Office/PDF source. Record what was merged, deferred, ignored, or left as a gap.
25
- 5. Call `revela_domain_list` and `revela_domain_read` for active domain guidance before authoring narrative meaning. Treat domain guidance as framing guidance, never as evidence.
26
- 6. If `revela-narrative/` exists, call `revela_markdown_qa` and `revela_compile_narrative`.
27
- 7. If the narrative vault is missing, create the initial `revela-narrative/` Markdown nodes directly with valid frontmatter and plain wikilink relations.
28
- 8. Evidence nodes must preserve source, quote/snippet, support scope, unsupported scope, caveat, and strength before being treated as support.
29
- 9. After writing narrative Markdown, call `revela_markdown_qa` and `revela_compile_narrative` again.
30
- 10. Before the final report, call `revela_check_material_intake` and surface any warnings about scanned-but-unextracted, extracted-but-unreviewed, unsupported, failed, or text-only sources.
31
- 11. End with a concise init report: local materials found, active domain, narrative graph status, material intake status, open gaps, Markdown QA status, and next command/action.
32
-
33
- ## Material Intake Rules
34
-
35
- - Scan results only prove that files exist; they do not prove file content.
36
- - For `.docx`, `.pptx`, `.xlsx`, and `.pdf`, read the extracted `read_view_path` instead of using Codex/textutil/raw reads of the original file.
37
- - Extracted images are candidate materials only. Do not interpret them as evidence unless image meaning is explicitly reviewed or supplied by the user.
38
- - If a user explicitly asks for text-only inspection, report it as degraded intake and do not treat it as complete source review.
39
-
40
- ## Markdown Rules
41
-
42
- - Use node types: `index`, `audience`, `decision`, `thesis`, `claim`, `evidence`, `objection`, `risk`, `research-gap`.
43
- - Use one leading frontmatter block per file.
44
- - Use `## Relations` with plain node-id wikilinks, such as `- supports: [[claim-recommendation]]`.
45
- - Do not use typed wikilinks such as `[[claim:claim-recommendation]]`.
46
- - Do not duplicate stable headings like `## Evidence`, `## Caveats`, `## Relations`, `## Response`, or `## Mitigation`.
19
+ 1. Call `revela_prepare_local_materials` first. Treat the result as an intake registry and task list.
20
+ 2. For Office/PDF sources, read `allowedReadPath` / `read_view_path`; if missing, call `revela_extract_document_materials`.
21
+ 3. Prefer local source materials first: Markdown, text, CSV, PDFs, Office files, existing `researches/`, `deck-plan.md`, `assets/`, and `decks/`.
22
+ 4. After reading extracted material views, call `revela_record_material_review` for each considered Office/PDF source.
23
+ 5. Call `revela_check_material_intake` before the final report and surface scanned-but-unreviewed, unsupported, failed, or text-only limitations.
24
+ 6. Ask only high-impact intent questions: audience, objective, decision/action, scope, language, source priority, or whether public research is allowed.
25
+ 7. End with an intake report: local materials found, read views reviewed, material reviews recorded, source limitations, captured user intent, and next command.
26
+
27
+ ## Report
28
+
29
+ - Recommend `/revela research` when public/source support is still needed.
30
+ - Recommend `/revela plan --deck` when enough local/research inputs exist.
31
+ - Do not ask for layout, visual style, output path, export format, or approval during init.