@cyber-dash-tech/revela 0.18.15 → 0.19.0

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 (103) hide show
  1. package/README.md +48 -45
  2. package/README.zh-CN.md +48 -45
  3. package/assets/img/lucent-01.jpg +0 -0
  4. package/assets/img/lucent-02.jpg +0 -0
  5. package/assets/img/lucent-03.jpg +0 -0
  6. package/assets/img/lucent-dark-01.jpg +0 -0
  7. package/assets/img/lucent-dark-02.jpg +0 -0
  8. package/assets/img/lucent-dark-03.jpg +0 -0
  9. package/assets/img/monet-01.jpg +0 -0
  10. package/assets/img/monet-02.jpg +0 -0
  11. package/assets/img/monet-03.jpg +0 -0
  12. package/assets/img/starter-01.jpg +0 -0
  13. package/assets/img/starter-02.jpg +0 -0
  14. package/assets/img/starter-03.jpg +0 -0
  15. package/assets/img/summit-01.jpg +0 -0
  16. package/assets/img/summit-02.jpg +0 -0
  17. package/assets/img/summit-03.jpg +0 -0
  18. package/designs/lucent/DESIGN.md +108 -1
  19. package/designs/lucent/design.css +283 -0
  20. package/designs/lucent-dark/DESIGN.md +278 -0
  21. package/designs/lucent-dark/assets/card-lens.jpg +0 -0
  22. package/designs/lucent-dark/assets/closing-background.jpg +0 -0
  23. package/designs/lucent-dark/assets/cover-background.jpg +0 -0
  24. package/designs/lucent-dark/assets/report-visual.jpg +0 -0
  25. package/designs/lucent-dark/assets/soft-texture.jpg +0 -0
  26. package/designs/lucent-dark/assets/toc-orb.png +0 -0
  27. package/designs/lucent-dark/design.css +417 -0
  28. package/designs/monet/DESIGN.md +53 -9
  29. package/designs/monet/assets/card-lens.jpg +0 -0
  30. package/designs/monet/assets/closing-background.jpg +0 -0
  31. package/designs/monet/assets/cover-background.jpg +0 -0
  32. package/designs/monet/assets/report-visual.jpg +0 -0
  33. package/designs/monet/assets/soft-texture.jpg +0 -0
  34. package/designs/monet/assets/toc-orb.png +0 -0
  35. package/designs/monet/design.css +340 -0
  36. package/designs/starter/DESIGN.md +22 -5
  37. package/designs/starter/assets/card-lens.jpg +0 -0
  38. package/designs/starter/assets/closing-background.jpg +0 -0
  39. package/designs/starter/assets/cover-background.jpg +0 -0
  40. package/designs/starter/assets/report-visual.jpg +0 -0
  41. package/designs/starter/assets/soft-texture.jpg +0 -0
  42. package/designs/starter/assets/toc-orb.png +0 -0
  43. package/designs/starter/design.css +322 -0
  44. package/designs/summit/DESIGN.md +54 -9
  45. package/designs/summit/assets/card-lens.jpg +0 -0
  46. package/designs/summit/assets/closing-background.jpg +0 -0
  47. package/designs/summit/assets/cover-background.jpg +0 -0
  48. package/designs/summit/assets/report-visual.jpg +0 -0
  49. package/designs/summit/assets/soft-texture.jpg +0 -0
  50. package/designs/summit/assets/toc-orb.png +0 -0
  51. package/designs/summit/design.css +334 -0
  52. package/lib/commands/designs-new.ts +18 -21
  53. package/lib/commands/designs-preview.ts +3 -8
  54. package/lib/deck-html/foundation.ts +8 -8
  55. package/lib/design/designs.ts +385 -14
  56. package/lib/narrative-state/deck-plan-artifact.ts +40 -3
  57. package/lib/page-templates/built-in-preview.html +373 -0
  58. package/lib/page-templates/contracts.ts +2 -0
  59. package/lib/page-templates/css.ts +2 -0
  60. package/lib/page-templates/foundation.ts +41 -0
  61. package/lib/page-templates/index.ts +6 -0
  62. package/lib/page-templates/registry.ts +3 -0
  63. package/lib/page-templates/render.ts +1202 -0
  64. package/lib/page-templates/templates/agenda.ts +4 -0
  65. package/lib/page-templates/templates/chart-takeaways.ts +4 -0
  66. package/lib/page-templates/templates/claim-supporting-visual.ts +4 -0
  67. package/lib/page-templates/templates/closing.ts +4 -0
  68. package/lib/page-templates/templates/cover.ts +4 -0
  69. package/lib/page-templates/templates/executive-summary.ts +4 -0
  70. package/lib/page-templates/templates/index.ts +19 -0
  71. package/lib/page-templates/templates/key-message-evidence.ts +4 -0
  72. package/lib/page-templates/templates/metric-highlight.ts +4 -0
  73. package/lib/page-templates/templates/problem-context.ts +4 -0
  74. package/lib/page-templates/templates/process-steps.ts +4 -0
  75. package/lib/page-templates/templates/recommendation-decision.ts +4 -0
  76. package/lib/page-templates/templates/risks-tradeoffs.ts +4 -0
  77. package/lib/page-templates/templates/section-divider.ts +4 -0
  78. package/lib/page-templates/templates/shared.ts +11 -0
  79. package/lib/page-templates/templates/table-comparison.ts +4 -0
  80. package/lib/page-templates/templates/timeline-roadmap.ts +4 -0
  81. package/lib/page-templates/vocabulary.ts +158 -0
  82. package/lib/prompt-builder.ts +9 -5
  83. package/lib/qa/artifact.ts +117 -7
  84. package/lib/qa/checks.ts +1 -1
  85. package/lib/qa/compliance.ts +5 -1
  86. package/lib/qa/component-contracts.ts +90 -0
  87. package/lib/runtime/index.ts +99 -3
  88. package/package.json +7 -15
  89. package/plugins/revela/.codex-plugin/plugin.json +4 -4
  90. package/plugins/revela/hooks/revela_guard.ts +35 -0
  91. package/plugins/revela/hooks/revela_post_write_notice.ts +39 -9
  92. package/plugins/revela/mcp/revela-server.ts +103 -7
  93. package/plugins/revela/skills/revela/SKILL.md +3 -3
  94. package/plugins/revela/skills/revela-design/SKILL.md +25 -14
  95. package/plugins/revela/skills/revela-helper/SKILL.md +3 -3
  96. package/plugins/revela/skills/revela-make-deck/SKILL.md +27 -12
  97. package/plugins/revela/skills/revela-research/SKILL.md +1 -0
  98. package/skill/SKILL.md +11 -2
  99. package/designs/lucent/preview.html +0 -612
  100. package/designs/monet/preview.html +0 -2293
  101. package/designs/starter/preview.html +0 -314
  102. package/designs/summit/preview.html +0 -2284
  103. package/plugins/revela/skills/revela-review/SKILL.md +0 -46
@@ -15,6 +15,7 @@ import {
15
15
  installDesignDraftPackage,
16
16
  listDesignAssets,
17
17
  listDesigns,
18
+ materializeDesignPreview,
18
19
  packDesignPackage,
19
20
  seedBuiltinDesigns,
20
21
  validateDesignDraftPackage,
@@ -30,6 +31,7 @@ import { runNarrativeMarkdownQa, type MarkdownQaOptions } from "../narrative-vau
30
31
  import { formatArtifactQaUserNotice, formatMarkdownQaUserNotice } from "../hook-notifications"
31
32
  import { deckPlanDesignDiagnostics, readDeckPlanArtifact, upsertDeckPlanSlideArtifact, type DeckPlanSlideUpsertInput } from "../narrative-state/deck-plan-artifact"
32
33
  import { extractDesignClasses } from "../design/designs"
34
+ import { addTemplateScaffold as addPageTemplateScaffold, addTemplateSlide as addPageTemplateSlide, getPageTemplateFoundation, getPageTemplateVocabulary, listPageTemplates as listBuiltinPageTemplates, renderTemplateScaffold as renderPageTemplateScaffold, renderTemplateSlide as renderPageTemplateSlide } from "../page-templates"
33
35
  import { recordRenderedArtifact, workspaceRelative } from "../workspace-state/rendered-artifacts"
34
36
  import { existingWorkspaceMetaPath, workspaceMetaPath } from "../workspace-meta"
35
37
  import { checkMaterialIntake, extractMaterial, materialIntakeNoticeForCommand, prepareLocalMaterials, recordMaterialReview } from "../material-intake"
@@ -84,17 +86,49 @@ export interface RuntimeDeckPlanSlideUpsertInput extends RuntimeWorkspaceInput,
84
86
  designName?: string
85
87
  }
86
88
 
89
+ export interface RuntimeTemplateSlideInput extends RuntimeWorkspaceInput {
90
+ templateId: string
91
+ slideIndex: number
92
+ content: Record<string, any>
93
+ designName?: string
94
+ }
95
+
96
+ export interface RuntimeTemplateSlideAddInput extends RuntimeTemplateSlideInput {
97
+ outputPath: string
98
+ }
99
+
100
+ export interface RuntimeTemplateScaffoldInput extends RuntimeWorkspaceInput {
101
+ templateId: string
102
+ slideIndex: number
103
+ seed?: Record<string, any>
104
+ designName?: string
105
+ }
106
+
107
+ export interface RuntimeTemplateScaffoldAddInput extends RuntimeTemplateScaffoldInput {
108
+ outputPath: string
109
+ }
110
+
111
+ export interface RuntimePageTemplateReadInput {
112
+ templateId: string
113
+ }
114
+
87
115
  export interface RuntimeDesignCreateInput {
88
116
  name: string
89
117
  base?: string
90
118
  designMd: string
91
- previewHtml: string
119
+ designCss?: string
120
+ previewHtml?: string
92
121
  assets?: DesignPackageAssetInput[]
93
122
  overwrite?: boolean
94
123
  }
95
124
 
96
125
  export interface RuntimeDesignDraftCreateInput extends RuntimeDesignCreateInput, RuntimeWorkspaceInput {}
97
126
 
127
+ export interface RuntimeDesignPreviewInput extends RuntimeWorkspaceInput {
128
+ name: string
129
+ source?: "draft" | "installed" | "builtin"
130
+ }
131
+
98
132
  export interface RuntimeDomainCreateInput {
99
133
  name: string
100
134
  domainMd: string
@@ -218,6 +252,58 @@ export function createDeckFoundation(input: RuntimeDeckFoundationInput) {
218
252
  })
219
253
  }
220
254
 
255
+ export function listPageTemplates() {
256
+ return listBuiltinPageTemplates()
257
+ }
258
+
259
+ export function renderTemplateSlide(input: RuntimeTemplateSlideInput) {
260
+ return renderPageTemplateSlide({
261
+ templateId: requiredString(input?.templateId, "templateId"),
262
+ slideIndex: input.slideIndex,
263
+ content: input.content ?? {},
264
+ designName: input.designName || activeDesign(),
265
+ })
266
+ }
267
+
268
+ export function renderTemplateScaffold(input: RuntimeTemplateScaffoldInput) {
269
+ return renderPageTemplateScaffold({
270
+ templateId: requiredString(input?.templateId, "templateId"),
271
+ slideIndex: input.slideIndex,
272
+ seed: input.seed ?? {},
273
+ designName: input.designName || activeDesign(),
274
+ })
275
+ }
276
+
277
+ export function addTemplateSlide(input: RuntimeTemplateSlideAddInput) {
278
+ return addPageTemplateSlide({
279
+ workspaceRoot: root(input.workspaceRoot),
280
+ outputPath: requiredString(input?.outputPath, "outputPath"),
281
+ templateId: requiredString(input?.templateId, "templateId"),
282
+ slideIndex: input.slideIndex,
283
+ content: input.content ?? {},
284
+ designName: input.designName || activeDesign(),
285
+ })
286
+ }
287
+
288
+ export function addTemplateScaffold(input: RuntimeTemplateScaffoldAddInput) {
289
+ return addPageTemplateScaffold({
290
+ workspaceRoot: root(input.workspaceRoot),
291
+ outputPath: requiredString(input?.outputPath, "outputPath"),
292
+ templateId: requiredString(input?.templateId, "templateId"),
293
+ slideIndex: input.slideIndex,
294
+ seed: input.seed ?? {},
295
+ designName: input.designName || activeDesign(),
296
+ })
297
+ }
298
+
299
+ export function pageTemplateFoundation(input: RuntimePageTemplateReadInput) {
300
+ return { ok: true, foundation: getPageTemplateFoundation(requiredString(input?.templateId, "templateId")) }
301
+ }
302
+
303
+ export function pageTemplateVocabulary(input: RuntimePageTemplateReadInput) {
304
+ return { ok: true, vocabulary: getPageTemplateVocabulary(requiredString(input?.templateId, "templateId")) }
305
+ }
306
+
221
307
  export async function runDeckQa(input: RuntimeFileInput) {
222
308
  const { formatArtifactQAReport, runArtifactQA } = await import("../qa/artifact")
223
309
  const workspaceRoot = root(input.workspaceRoot)
@@ -362,7 +448,8 @@ export function designCreate(input: RuntimeDesignCreateInput) {
362
448
  name: requiredString(input?.name, "design name"),
363
449
  base: input.base,
364
450
  designMd: requiredString(input?.designMd, "designMd"),
365
- previewHtml: requiredString(input?.previewHtml, "previewHtml"),
451
+ designCss: input.designCss,
452
+ previewHtml: input.previewHtml,
366
453
  assets: input.assets,
367
454
  overwrite: input.overwrite ?? false,
368
455
  })
@@ -378,7 +465,8 @@ export function designDraftCreate(input: RuntimeDesignDraftCreateInput) {
378
465
  name: requiredString(input?.name, "design name"),
379
466
  base: input.base,
380
467
  designMd: requiredString(input?.designMd, "designMd"),
381
- previewHtml: requiredString(input?.previewHtml, "previewHtml"),
468
+ designCss: input.designCss,
469
+ previewHtml: input.previewHtml,
382
470
  assets: input.assets,
383
471
  overwrite: input.overwrite ?? false,
384
472
  })
@@ -388,6 +476,14 @@ export function designDraftValidate(input: RuntimeWorkspaceInput & RuntimeNameIn
388
476
  return validateDesignDraftPackage(root(input.workspaceRoot), requiredName(input, "design draft"))
389
477
  }
390
478
 
479
+ export function designPreview(input: RuntimeDesignPreviewInput) {
480
+ return materializeDesignPreview({
481
+ workspaceRoot: root(input.workspaceRoot),
482
+ name: requiredName(input, "design"),
483
+ source: input.source,
484
+ })
485
+ }
486
+
391
487
  export function designDraftInstall(input: RuntimeDraftInstallInput) {
392
488
  seedBuiltinDesigns()
393
489
  return installDesignDraftPackage({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyber-dash-tech/revela",
3
- "version": "0.18.15",
3
+ "version": "0.19.0",
4
4
  "description": "Codex-first CLI/MCP workspace for trusted narrative artifacts from local sources, research, and evidence",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -11,11 +11,7 @@
11
11
  ".": "./index.ts"
12
12
  },
13
13
  "files": [
14
- "assets/img/logo.png",
15
- "assets/img/logo-64.png",
16
- "assets/img/logo-256.png",
17
- "assets/img/logo-wordmark.png",
18
- "assets/img/review-ui.png",
14
+ "assets/img/",
19
15
  "bin/",
20
16
  "plugin.ts",
21
17
  "lib/",
@@ -23,15 +19,11 @@
23
19
  "tools/",
24
20
  "skill/",
25
21
  "designs/aurora/DESIGN.md",
26
- "designs/starter/DESIGN.md",
27
- "designs/starter/preview.html",
28
- "designs/summit/DESIGN.md",
29
- "designs/summit/preview.html",
30
- "designs/monet/DESIGN.md",
31
- "designs/monet/preview.html",
32
- "designs/lucent/DESIGN.md",
33
- "designs/lucent/preview.html",
34
- "designs/lucent/assets/",
22
+ "designs/starter/",
23
+ "designs/summit/",
24
+ "designs/monet/",
25
+ "designs/lucent/",
26
+ "designs/lucent-dark/",
35
27
  "domains/general/INDUSTRY.md",
36
28
  "domains/deeptech-investment/INDUSTRY.md",
37
29
  "domains/consulting/INDUSTRY.md",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "revela",
3
- "version": "0.18.15",
4
- "description": "Use Revela in Codex to specify, research, plan, make, review, and export trusted narrative decision artifacts.",
3
+ "version": "0.19.0",
4
+ "description": "Use Revela in Codex to specify, research, plan, make, and export trusted narrative decision artifacts.",
5
5
  "author": {
6
6
  "name": "cyber-dash-tech",
7
7
  "url": "https://github.com/cyber-dash-tech"
@@ -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 route workspace workflows, capture requirements in spec.md, ingest local materials, save research findings, plan decks, generate HTML deck artifacts, review them, and export PDF/PPTX/PNG outputs while preserving source traceability.",
23
+ "longDescription": "Revela helps Codex route workspace workflows, capture requirements in spec.md, ingest local materials, save research findings, plan decks, generate HTML deck artifacts, open them in Codex Browser for annotation, and export PDF/PPTX/PNG outputs while preserving source traceability.",
24
24
  "developerName": "cyber-dash-tech",
25
25
  "category": "Productivity",
26
26
  "capabilities": [
@@ -31,7 +31,7 @@
31
31
  "Use Revela to route the next workflow step for this workspace.",
32
32
  "Use Revela to write a spec.md for this deck objective.",
33
33
  "Use Revela to make a deck from the deck plan.",
34
- "Use Revela to review this deck artifact."
34
+ "Use Revela to export this deck artifact."
35
35
  ],
36
36
  "brandColor": "#2563EB"
37
37
  }
@@ -26,6 +26,16 @@ export async function runPreWriteChecks(input: string): Promise<HookResult> {
26
26
  ].join("\n"))
27
27
  }
28
28
 
29
+ const protectedDesignCssTargets = extractProtectedDesignCssPatchTargets(input)
30
+ if (protectedDesignCssTargets.length > 0) {
31
+ messages.push([
32
+ "Revela design CSS patches are blocked outside the design draft workflow.",
33
+ `Protected target(s): ${protectedDesignCssTargets.map((target) => `\`${target}\``).join(", ")}`,
34
+ "Create or edit designs under `.revela/drafts/designs/<name>/design.css`, then validate and install the draft.",
35
+ "Deck-local `decks/_revela-design/**/design.css` files are render snapshots and should be regenerated, not patched.",
36
+ ].join("\n"))
37
+ }
38
+
29
39
  const deckTargets = extractDeckHtmlPatchTargets(input)
30
40
  if (deckTargets.length > 0) {
31
41
  const pluginRoot = resolve(process.env.PLUGIN_ROOT || dirname(dirname(fileURLToPath(import.meta.url))))
@@ -74,6 +84,31 @@ export function extractNarrativeCachePatchTargets(input: string): string[] {
74
84
  return [...targets].sort((a, b) => a.localeCompare(b))
75
85
  }
76
86
 
87
+ export function extractProtectedDesignCssPatchTargets(input: string): string[] {
88
+ const targets = new Set<string>()
89
+ for (const patch of patchPayloads(input)) {
90
+ const pattern = /(?:^\*\*\* Update File: |^\*\*\* Add File: |^\*\*\* Delete File: |^\*\*\* Move to: )([^\r\n]*design\.css)\s*$/gm
91
+ let match: RegExpExecArray | null
92
+ while ((match = pattern.exec(patch))) {
93
+ const target = match[1].trim().replace(/\\/g, "/")
94
+ if (isAllowedDesignDraftCssTarget(target)) continue
95
+ if (isProtectedDesignCssTarget(target)) targets.add(target)
96
+ }
97
+ }
98
+ return [...targets].sort((a, b) => a.localeCompare(b))
99
+ }
100
+
101
+ function isAllowedDesignDraftCssTarget(target: string): boolean {
102
+ return /(^|\/)\.revela\/drafts\/designs\/[^/]+\/design\.css$/.test(target)
103
+ }
104
+
105
+ function isProtectedDesignCssTarget(target: string): boolean {
106
+ return /(^|\/)designs\/[^/]+\/design\.css$/.test(target)
107
+ || /(^|\/)decks\/_revela-design\/[^/]+\/design\.css$/.test(target)
108
+ || /(^|\/)_revela-design\/[^/]+\/design\.css$/.test(target)
109
+ || /(^|\/)\.config\/revela\/designs\/[^/]+\/design\.css$/.test(target)
110
+ }
111
+
77
112
  function patchPayloads(input: string): string[] {
78
113
  try {
79
114
  const parsed = JSON.parse(input)
@@ -1,4 +1,5 @@
1
- import { dirname, resolve } from "path"
1
+ import { basename, dirname, resolve } from "path"
2
+ import { existsSync, readFileSync } from "fs"
2
3
  import { fileURLToPath, pathToFileURL } from "url"
3
4
  import { resolveRevelaRuntime } from "../mcp/runtime-resolver"
4
5
 
@@ -9,15 +10,13 @@ interface HookResult {
9
10
 
10
11
  export function extractDeckHtmlTargets(input: string): string[] {
11
12
  const targets = new Set<string>()
12
- const patterns = [
13
- /\bdecks\/[^\s"'`<>]+\.html\b/g,
14
- /(?:^\*\*\* Update File: |^\*\*\* Add File: )([^\r\n]+decks\/[^\r\n]+\.html)\s*$/gm,
15
- ]
13
+ const pattern = /(?:^\*\*\* Update File: |^\*\*\* Add File: )((?:[^\r\n]*\/)?decks\/[^\s"'`<>*?\r\n]+\.html)\s*$/gm
16
14
 
17
- for (const pattern of patterns) {
15
+ for (const patch of patchPayloadsFromInput(input)) {
18
16
  let match: RegExpExecArray | null
19
- while ((match = pattern.exec(input))) {
20
- targets.add((match[1] ?? match[0]).trim())
17
+ while ((match = pattern.exec(patch))) {
18
+ const target = match[1].trim()
19
+ if (!target.includes("*") && !target.includes("?")) targets.add(target)
21
20
  }
22
21
  }
23
22
 
@@ -59,6 +58,32 @@ export function workspaceRootFromInput(input: string): string {
59
58
  return resolve(process.env.CODEX_WORKSPACE_ROOT || process.env.PWD || process.cwd())
60
59
  }
61
60
 
61
+ function titleFromDeckHtml(absolutePath: string): string {
62
+ try {
63
+ if (!existsSync(absolutePath)) return basename(absolutePath)
64
+ const html = readFileSync(absolutePath, "utf-8")
65
+ const title = html.match(/<title[^>]*>([^<]+)<\/title>/i)?.[1]?.trim()
66
+ return title || basename(absolutePath)
67
+ } catch {
68
+ return basename(absolutePath)
69
+ }
70
+ }
71
+
72
+ export function formatDeckWebsiteCardHandoffNotice(workspaceRoot: string, target: string): string {
73
+ const absolutePath = resolve(workspaceRoot, target)
74
+ const deckUrl = pathToFileURL(absolutePath).href
75
+ const title = titleFromDeckHtml(absolutePath)
76
+ return [
77
+ "**Deck website card ready**",
78
+ "",
79
+ `Artifact QA passed for \`${target}\`. Reply with this standalone deck link so Codex renders an Open in Browser website card:`,
80
+ "",
81
+ `[${title}](${deckUrl})`,
82
+ "",
83
+ `If the card or direct \`file://\` navigation is unavailable, start a read-only local static server from the workspace root and link to \`http://127.0.0.1:<port>/${target}\` instead.`,
84
+ ].join("\n")
85
+ }
86
+
62
87
  export async function runPostWriteChecks(input: string): Promise<HookResult> {
63
88
  const messages: string[] = []
64
89
  const deckTargets = extractDeckHtmlTargets(input)
@@ -97,11 +122,16 @@ export async function runPostWriteChecks(input: string): Promise<HookResult> {
97
122
  }
98
123
 
99
124
  for (const target of deckTargets) {
125
+ if (!existsSync(resolve(workspaceRoot, target))) continue
100
126
  const result = await runtimeModule.runDeckQa({ workspaceRoot, file: target })
101
127
  messages.push(result.markdown ?? JSON.stringify(result, null, 2))
102
128
  const notice = runtimeModule.formatArtifactQaUserNotice?.(result.report)
103
129
  if (notice) messages.push(notice)
104
- if (!result.ok) ok = false
130
+ if (result.ok) {
131
+ messages.push(formatDeckWebsiteCardHandoffNotice(workspaceRoot, target))
132
+ } else {
133
+ ok = false
134
+ }
105
135
  }
106
136
 
107
137
  return { ok, messages }
@@ -13,6 +13,13 @@ type RuntimeModule = {
13
13
  readDeckPlan(input?: any): any
14
14
  upsertDeckPlanSlide(input: any): any
15
15
  createDeckFoundation(input: any): any
16
+ listPageTemplates(): any
17
+ renderTemplateSlide(input: any): any
18
+ addTemplateSlide(input: any): any
19
+ renderTemplateScaffold(input: any): any
20
+ addTemplateScaffold(input: any): any
21
+ pageTemplateFoundation(input: any): any
22
+ pageTemplateVocabulary(input: any): any
16
23
  runDeckQa(input: any): Promise<any>
17
24
  exportPdf(input: any): Promise<any>
18
25
  exportPptx(input: any): Promise<any>
@@ -25,6 +32,7 @@ type RuntimeModule = {
25
32
  designActivate(input: any): any
26
33
  designCreate(input: any): any
27
34
  designValidate(input: any): any
35
+ designPreview(input: any): any
28
36
  designDraftCreate(input: any): any
29
37
  designDraftValidate(input: any): any
30
38
  designDraftInstall(input: any): any
@@ -94,6 +102,71 @@ const tools = [
94
102
  overwrite: booleanProp("Whether create mode may overwrite an existing file."),
95
103
  }, ["outputPath", "title", "language"]),
96
104
  },
105
+ {
106
+ name: "revela_list_page_templates",
107
+ description: "List built-in Revela page templates with semantic fields, content rules, and template QA contracts.",
108
+ inputSchema: objectSchema({}),
109
+ },
110
+ {
111
+ name: "revela_render_template_slide",
112
+ description: "Render one built-in page template into a stable Revela slide HTML skeleton using the active/requested design.",
113
+ inputSchema: objectSchema({
114
+ workspaceRoot: stringProp("Optional workspace root."),
115
+ designName: stringProp("Optional design name. Defaults to the active design."),
116
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
117
+ slideIndex: requiredNumberProp("Positive 1-based slide index."),
118
+ content: objectProp("Template content fields. The built-in template renderer owns the HTML skeleton."),
119
+ }, ["templateId", "slideIndex", "content"]),
120
+ },
121
+ {
122
+ name: "revela_page_template_foundation",
123
+ description: "Read the built-in template foundation for custom design authoring: scaffold HTML, CSS hooks, slots, and contract notes.",
124
+ inputSchema: objectSchema({
125
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
126
+ }, ["templateId"]),
127
+ },
128
+ {
129
+ name: "revela_page_template_vocabulary",
130
+ description: "Read machine-readable classes, slots, editable regions, replaceable regions, and contract notes for one page template.",
131
+ inputSchema: objectSchema({
132
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
133
+ }, ["templateId"]),
134
+ },
135
+ {
136
+ name: "revela_render_template_scaffold",
137
+ description: "Render one built-in page template scaffold with stable editable slots using minimal seed content.",
138
+ inputSchema: objectSchema({
139
+ workspaceRoot: stringProp("Optional workspace root."),
140
+ designName: stringProp("Optional design name. Defaults to the active design."),
141
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
142
+ slideIndex: requiredNumberProp("Positive 1-based slide index."),
143
+ seed: objectProp("Optional scaffold seed fields. This is not the final authoring interface."),
144
+ }, ["templateId", "slideIndex"]),
145
+ },
146
+ {
147
+ name: "revela_add_template_scaffold",
148
+ description: "Render and append one built-in page template scaffold into an existing Revela deck HTML file between slide markers.",
149
+ inputSchema: objectSchema({
150
+ workspaceRoot: stringProp("Optional workspace root."),
151
+ outputPath: requiredStringProp("Workspace-relative HTML deck path."),
152
+ designName: stringProp("Optional design name. Defaults to the active design."),
153
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
154
+ slideIndex: requiredNumberProp("Positive 1-based slide index."),
155
+ seed: objectProp("Optional scaffold seed fields. LLM should bounded-edit the inserted slide after scaffold creation."),
156
+ }, ["outputPath", "templateId", "slideIndex"]),
157
+ },
158
+ {
159
+ name: "revela_add_template_slide",
160
+ description: "Compatibility path: render and append one built-in page template slide from full content JSON into an existing deck HTML file.",
161
+ inputSchema: objectSchema({
162
+ workspaceRoot: stringProp("Optional workspace root."),
163
+ outputPath: requiredStringProp("Workspace-relative HTML deck path."),
164
+ designName: stringProp("Optional design name. Defaults to the active design."),
165
+ templateId: requiredStringProp("Built-in template id, such as timeline-roadmap."),
166
+ slideIndex: requiredNumberProp("Positive 1-based slide index."),
167
+ content: objectProp("Template content fields. Prefer scaffold-first flow for new deck creation."),
168
+ }, ["outputPath", "templateId", "slideIndex", "content"]),
169
+ },
97
170
  {
98
171
  name: "revela_run_deck_qa",
99
172
  description: "Run Revela artifact QA on a generated HTML deck.",
@@ -171,15 +244,16 @@ const tools = [
171
244
  },
172
245
  {
173
246
  name: "revela_design_create",
174
- description: "Create and validate a local Revela design package from complete DESIGN.md and preview.html content.",
247
+ description: "Create and validate a local Revela design package from complete DESIGN.md, design.css, and optional legacy preview.html content.",
175
248
  inputSchema: objectSchema({
176
249
  name: requiredStringProp("Design name in kebab-case."),
177
250
  base: stringProp("Optional base design used as structural scaffold."),
178
251
  designMd: requiredStringProp("Complete DESIGN.md content."),
179
- previewHtml: requiredStringProp("Complete preview.html content."),
252
+ designCss: stringProp("Complete design.css content. Required for CSS-native designs; omitted only for legacy compatibility."),
253
+ previewHtml: stringProp("Optional legacy preview.html content. Current design previews are generated with revela_design_preview."),
180
254
  assets: designAssetsProp(),
181
255
  overwrite: booleanProp("Whether to replace an existing local design package. Defaults to false."),
182
- }, ["name", "designMd", "previewHtml"]),
256
+ }, ["name", "designMd"]),
183
257
  },
184
258
  {
185
259
  name: "revela_design_validate",
@@ -194,10 +268,11 @@ const tools = [
194
268
  name: requiredStringProp("Design name in kebab-case."),
195
269
  base: stringProp("Optional base design used as structural scaffold."),
196
270
  designMd: requiredStringProp("Complete DESIGN.md content."),
197
- previewHtml: requiredStringProp("Complete preview.html content."),
271
+ designCss: stringProp("Complete design.css content. Required for CSS-native designs; omitted only for legacy compatibility."),
272
+ previewHtml: stringProp("Optional legacy preview.html content. Current design previews are generated with revela_design_preview."),
198
273
  assets: designAssetsProp(),
199
274
  overwrite: booleanProp("Whether to replace an existing workspace draft. Defaults to false."),
200
- }, ["name", "designMd", "previewHtml"]),
275
+ }, ["name", "designMd"]),
201
276
  },
202
277
  {
203
278
  name: "revela_design_draft_validate",
@@ -207,6 +282,15 @@ const tools = [
207
282
  name: requiredStringProp("Design draft name to validate."),
208
283
  }, ["name"]),
209
284
  },
285
+ {
286
+ name: "revela_design_preview",
287
+ description: "Generate a workspace-local preview for a draft, installed, or built-in Revela design using the built-in page template preview fixture plus the design.css file.",
288
+ inputSchema: objectSchema({
289
+ workspaceRoot: stringProp("Optional workspace root."),
290
+ name: requiredStringProp("Design name to preview."),
291
+ source: stringProp("Optional source: draft, installed, or builtin. Defaults to draft when present, otherwise installed/builtin."),
292
+ }, ["name"]),
293
+ },
210
294
  {
211
295
  name: "revela_design_draft_install",
212
296
  description: "Install a validated workspace-local Revela design draft into the user-level design registry.",
@@ -296,7 +380,7 @@ const tools = [
296
380
  },
297
381
  {
298
382
  name: "revela_review_deck_read",
299
- description: "Read-only aggregate Review diagnostics for a Revela HTML deck: artifact QA, deck-plan diagnostics, and export/readiness signals.",
383
+ description: "Compatibility-only read of aggregate Review diagnostics for a Revela HTML deck: artifact QA, deck-plan diagnostics, and export/readiness signals.",
300
384
  inputSchema: objectSchema({
301
385
  workspaceRoot: stringProp("Optional workspace root."),
302
386
  file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
@@ -305,7 +389,7 @@ const tools = [
305
389
  },
306
390
  {
307
391
  name: "revela_review_deck_open",
308
- description: "Open a local Codex-backed Review UI for a Revela HTML deck from the current MCP server process.",
392
+ description: "Compatibility-only opener for the legacy local Codex-backed Review UI for a Revela HTML deck.",
309
393
  inputSchema: objectSchema({
310
394
  workspaceRoot: stringProp("Optional workspace root."),
311
395
  file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
@@ -421,6 +505,13 @@ async function callTool(name: string, args: any): Promise<any> {
421
505
  if (name === "revela_read_deck_plan") return r.readDeckPlan(args)
422
506
  if (name === "revela_upsert_deck_plan_slide") return r.upsertDeckPlanSlide(args)
423
507
  if (name === "revela_create_deck_foundation") return r.createDeckFoundation(args)
508
+ if (name === "revela_list_page_templates") return r.listPageTemplates()
509
+ if (name === "revela_render_template_slide") return r.renderTemplateSlide(args)
510
+ if (name === "revela_add_template_slide") return r.addTemplateSlide(args)
511
+ if (name === "revela_page_template_foundation") return r.pageTemplateFoundation(args)
512
+ if (name === "revela_page_template_vocabulary") return r.pageTemplateVocabulary(args)
513
+ if (name === "revela_render_template_scaffold") return r.renderTemplateScaffold(args)
514
+ if (name === "revela_add_template_scaffold") return r.addTemplateScaffold(args)
424
515
  if (name === "revela_run_deck_qa") return r.runDeckQa(args)
425
516
  if (name === "revela_export_pdf") return r.exportPdf(args)
426
517
  if (name === "revela_export_pptx") return r.exportPptx(args)
@@ -435,6 +526,7 @@ async function callTool(name: string, args: any): Promise<any> {
435
526
  if (name === "revela_design_validate") return r.designValidate(args)
436
527
  if (name === "revela_design_draft_create") return r.designDraftCreate(args)
437
528
  if (name === "revela_design_draft_validate") return r.designDraftValidate(args)
529
+ if (name === "revela_design_preview") return r.designPreview(args)
438
530
  if (name === "revela_design_draft_install") return r.designDraftInstall(args)
439
531
  if (name === "revela_design_pack") return r.designPack(args)
440
532
  if (name === "revela_design_install_archive") return r.designInstallArchive(args)
@@ -496,6 +588,10 @@ function arrayProp(description: string) {
496
588
  return { type: "array", items: { type: "string" }, description }
497
589
  }
498
590
 
591
+ function objectProp(description: string) {
592
+ return { type: "object", description, additionalProperties: true }
593
+ }
594
+
499
595
  function stringOrArrayProp(description: string) {
500
596
  return {
501
597
  anyOf: [
@@ -11,7 +11,7 @@ Use this skill as the main Revela entrypoint in Codex. It should inspect intent
11
11
 
12
12
  - This is a non-mutating router.
13
13
  - It may inspect runtime, active design/domain, and workspace artifact status.
14
- - It must not write `spec.md`, save research findings, write `deck-plan.md`, generate deck HTML, open Review UI, or export artifacts.
14
+ - It must not write `spec.md`, save research findings, write `deck-plan.md`, generate deck HTML, open deck browser views, or export artifacts.
15
15
  - Route quickly once the next workflow is clear.
16
16
 
17
17
  ## Required Tools
@@ -29,7 +29,7 @@ Use this skill as the main Revela entrypoint in Codex. It should inspect intent
29
29
  - `spec.md` exists but source support, material review, or findings are missing: use `revela-research`.
30
30
  - `spec.md` and sufficient findings exist but `deck-plan.md` is missing or needs normal authoring: use `revela-research` Planning Handoff.
31
31
  - Valid `deck-plan.md` exists and the user asks to make, generate, render, or update a deck: use `revela-make-deck`.
32
- - Existing deck artifact and the user asks to review, diagnose, QA, or refine: use `revela-review`.
32
+ - Existing deck artifact and the user asks to review, annotate, diagnose, QA, or refine: use Codex Browser's native browsing/annotation flow. If the deck was not just generated, reply with the existing deck as a website card/link and use native annotations after it opens; route export requests to `revela-export`.
33
33
  - Existing deck artifact and the user asks for PDF, PPTX, or PNG output: use `revela-export`.
34
34
  - If the next step is still ambiguous after inspection, ask the smallest missing question and recommend the safest next specialist skill.
35
35
 
@@ -47,5 +47,5 @@ Report:
47
47
  - Do not write or patch files.
48
48
  - Do not do external web research.
49
49
  - Do not create or repair `spec.md` or `deck-plan.md`.
50
- - Do not generate, review, patch, or export deck artifacts.
50
+ - Do not generate, annotate, patch, or export deck artifacts.
51
51
  - Do not install or activate designs or domains; route those requests to `revela-design` or `revela-domain`.