@cyber-dash-tech/revela 0.19.7 → 0.19.9
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 +37 -54
- package/README.zh-CN.md +36 -53
- package/designs/lucent/design.css +10 -7
- package/designs/lucent-dark/design.css +16 -13
- package/designs/monet/design.css +38 -12
- package/designs/starter/design.css +14 -11
- package/designs/summit/design.css +14 -11
- package/lib/deck-html/foundation.ts +16 -2
- package/lib/design/designs.ts +13 -1
- package/lib/page-templates/render.ts +10 -7
- package/lib/pptx/export.ts +154 -2
- package/lib/runtime/index.ts +95 -3
- package/lib/runtime/open-deck.ts +190 -0
- package/package.json +1 -1
- package/plugins/revela/.codex-plugin/plugin.json +4 -3
- package/plugins/revela/mcp/revela-server.ts +17 -6
- package/plugins/revela/skills/revela/SKILL.md +1 -1
- package/plugins/revela/skills/revela-design/SKILL.md +5 -4
- package/plugins/revela/skills/revela-helper/SKILL.md +1 -1
- package/plugins/revela/skills/revela-review/SKILL.md +57 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { existsSync, statSync } from "fs"
|
|
2
|
+
import { extname, resolve, sep } from "path"
|
|
3
|
+
import { openUrl as systemOpenUrl } from "../edit/open"
|
|
4
|
+
import { workspaceRelative } from "../workspace-state/rendered-artifacts"
|
|
5
|
+
|
|
6
|
+
export interface OpenDeckInput {
|
|
7
|
+
workspaceRoot?: string
|
|
8
|
+
file: string
|
|
9
|
+
openBrowser?: boolean
|
|
10
|
+
openUrl?: (url: string) => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface DirectDeckServer {
|
|
14
|
+
server: ReturnType<typeof Bun.serve>
|
|
15
|
+
baseUrl: string
|
|
16
|
+
workspaceRoot: string
|
|
17
|
+
idleTimer?: Timer
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const servers = new Map<string, DirectDeckServer>()
|
|
21
|
+
const IDLE_STOP_MS = 30 * 60 * 1000
|
|
22
|
+
const FALLBACK_PORT_START = 8765
|
|
23
|
+
const FALLBACK_PORT_END = 8899
|
|
24
|
+
|
|
25
|
+
export function openDeck(input: OpenDeckInput): any {
|
|
26
|
+
const workspaceRoot = resolve(input.workspaceRoot || process.cwd())
|
|
27
|
+
const requestedFile = input.file?.trim()
|
|
28
|
+
if (!requestedFile) {
|
|
29
|
+
return {
|
|
30
|
+
ok: false,
|
|
31
|
+
file: "",
|
|
32
|
+
error: "Missing required file.",
|
|
33
|
+
diagnostics: [{ severity: "error", code: "missing_file", message: "Provide a workspace-relative or absolute deck HTML file." }],
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const absoluteFile = resolve(workspaceRoot, requestedFile)
|
|
38
|
+
const file = workspaceRelative(workspaceRoot, absoluteFile)
|
|
39
|
+
if (!isInside(workspaceRoot, absoluteFile)) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
file,
|
|
43
|
+
error: `Deck HTML file is outside the workspace: ${file}`,
|
|
44
|
+
diagnostics: [{ severity: "error", code: "file_outside_workspace", message: `Deck HTML file is outside the workspace: ${file}` }],
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!existsSync(absoluteFile) || !statSync(absoluteFile).isFile()) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
file,
|
|
51
|
+
error: `Deck HTML file not found: ${file}`,
|
|
52
|
+
diagnostics: [{ severity: "error", code: "file_not_found", message: `Deck HTML file not found: ${file}` }],
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!file.startsWith("decks/") || !file.endsWith(".html")) {
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
file,
|
|
59
|
+
error: `Deck HTML file must be under decks/*.html: ${file}`,
|
|
60
|
+
diagnostics: [{ severity: "error", code: "invalid_deck_path", message: `Deck HTML file must be under decks/*.html: ${file}` }],
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const deckServer = startDeckStaticServer(workspaceRoot)
|
|
66
|
+
const url = `${deckServer.baseUrl}/${file.split("/").map(encodeURIComponent).join("/")}`
|
|
67
|
+
const openedBrowser = input.openBrowser !== false
|
|
68
|
+
if (openedBrowser) (input.openUrl ?? systemOpenUrl)(url)
|
|
69
|
+
return {
|
|
70
|
+
ok: true,
|
|
71
|
+
file,
|
|
72
|
+
url,
|
|
73
|
+
serveRoot: workspaceRoot,
|
|
74
|
+
openedBrowser,
|
|
75
|
+
mode: "direct",
|
|
76
|
+
readOnly: true,
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
const message = e instanceof Error ? e.message : String(e)
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
file,
|
|
83
|
+
error: message,
|
|
84
|
+
diagnostics: [{ severity: "error", code: "open_deck_failed", message }],
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function stopOpenDeckServers(): void {
|
|
90
|
+
for (const item of servers.values()) {
|
|
91
|
+
if (item.idleTimer) clearTimeout(item.idleTimer)
|
|
92
|
+
item.server.stop()
|
|
93
|
+
}
|
|
94
|
+
servers.clear()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function startDeckStaticServer(workspaceRoot: string): DirectDeckServer {
|
|
98
|
+
const existing = servers.get(workspaceRoot)
|
|
99
|
+
if (existing) {
|
|
100
|
+
scheduleIdleStop(existing)
|
|
101
|
+
return existing
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const server = serveWithFallback(workspaceRoot)
|
|
105
|
+
const item: DirectDeckServer = {
|
|
106
|
+
server,
|
|
107
|
+
baseUrl: `http://127.0.0.1:${server.port}`,
|
|
108
|
+
workspaceRoot,
|
|
109
|
+
}
|
|
110
|
+
;(server as any).unref?.()
|
|
111
|
+
servers.set(workspaceRoot, item)
|
|
112
|
+
scheduleIdleStop(item)
|
|
113
|
+
return item
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function serveWithFallback(workspaceRoot: string): ReturnType<typeof Bun.serve> {
|
|
117
|
+
const ports = [0, ...Array.from({ length: FALLBACK_PORT_END - FALLBACK_PORT_START + 1 }, (_, index) => FALLBACK_PORT_START + index)]
|
|
118
|
+
const failures: string[] = []
|
|
119
|
+
for (const port of ports) {
|
|
120
|
+
try {
|
|
121
|
+
return Bun.serve({
|
|
122
|
+
hostname: "127.0.0.1",
|
|
123
|
+
port,
|
|
124
|
+
fetch: (req) => handleStaticRequest(workspaceRoot, req),
|
|
125
|
+
})
|
|
126
|
+
} catch (e) {
|
|
127
|
+
failures.push(`port ${port}: ${e instanceof Error ? e.message : String(e)}`)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
throw new Error(`Failed to start direct deck server. ${failures.slice(0, 3).join(" ")}`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function handleStaticRequest(workspaceRoot: string, req: Request): Promise<Response> {
|
|
134
|
+
const url = new URL(req.url)
|
|
135
|
+
if (req.method !== "GET" && req.method !== "HEAD") return new Response("Method not allowed", { status: 405 })
|
|
136
|
+
if (url.pathname === "/health") return new Response("ok", { status: 200 })
|
|
137
|
+
const pathPart = decodeURIComponent(url.pathname.replace(/^\/+/, ""))
|
|
138
|
+
if (!pathPart) return new Response("Not found", { status: 404 })
|
|
139
|
+
const absolutePath = resolve(workspaceRoot, pathPart)
|
|
140
|
+
if (!isInside(workspaceRoot, absolutePath)) return new Response("Forbidden", { status: 403 })
|
|
141
|
+
if (!existsSync(absolutePath) || !statSync(absolutePath).isFile()) return new Response("Not found", { status: 404 })
|
|
142
|
+
const file = Bun.file(absolutePath)
|
|
143
|
+
const headers = new Headers({ "content-type": contentType(absolutePath) })
|
|
144
|
+
if (req.method === "HEAD") return new Response(null, { status: 200, headers })
|
|
145
|
+
return new Response(file, { headers })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function scheduleIdleStop(item: DirectDeckServer): void {
|
|
149
|
+
if (item.idleTimer) clearTimeout(item.idleTimer)
|
|
150
|
+
item.idleTimer = setTimeout(() => {
|
|
151
|
+
item.server.stop()
|
|
152
|
+
servers.delete(item.workspaceRoot)
|
|
153
|
+
}, IDLE_STOP_MS)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function isInside(root: string, candidate: string): boolean {
|
|
157
|
+
const normalizedRoot = resolve(root)
|
|
158
|
+
const normalizedCandidate = resolve(candidate)
|
|
159
|
+
return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(normalizedRoot.endsWith(sep) ? normalizedRoot : normalizedRoot + sep)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function contentType(filePath: string): string {
|
|
163
|
+
switch (extname(filePath).toLowerCase()) {
|
|
164
|
+
case ".html":
|
|
165
|
+
return "text/html; charset=utf-8"
|
|
166
|
+
case ".css":
|
|
167
|
+
return "text/css; charset=utf-8"
|
|
168
|
+
case ".js":
|
|
169
|
+
return "application/javascript; charset=utf-8"
|
|
170
|
+
case ".json":
|
|
171
|
+
return "application/json; charset=utf-8"
|
|
172
|
+
case ".svg":
|
|
173
|
+
return "image/svg+xml"
|
|
174
|
+
case ".png":
|
|
175
|
+
return "image/png"
|
|
176
|
+
case ".jpg":
|
|
177
|
+
case ".jpeg":
|
|
178
|
+
return "image/jpeg"
|
|
179
|
+
case ".webp":
|
|
180
|
+
return "image/webp"
|
|
181
|
+
case ".gif":
|
|
182
|
+
return "image/gif"
|
|
183
|
+
case ".woff":
|
|
184
|
+
return "font/woff"
|
|
185
|
+
case ".woff2":
|
|
186
|
+
return "font/woff2"
|
|
187
|
+
default:
|
|
188
|
+
return "application/octet-stream"
|
|
189
|
+
}
|
|
190
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "revela",
|
|
3
|
-
"version": "0.19.
|
|
4
|
-
|
|
3
|
+
"version": "0.19.9",
|
|
4
|
+
"description": "Use Revela in Codex to specify, research, plan, make, review, 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, open them in Codex Browser
|
|
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 directly in Codex Browser, and export PDF/PPTX/PNG outputs while preserving source traceability.",
|
|
24
24
|
"developerName": "cyber-dash-tech",
|
|
25
25
|
"category": "Productivity",
|
|
26
26
|
"capabilities": [
|
|
@@ -31,6 +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 in Codex Browser.",
|
|
34
35
|
"Use Revela to export this deck artifact."
|
|
35
36
|
],
|
|
36
37
|
"brandColor": "#2563EB"
|
|
@@ -30,6 +30,7 @@ type RuntimeModule = {
|
|
|
30
30
|
designReadLayout(input: any): any
|
|
31
31
|
designReadComponent(input: any): any
|
|
32
32
|
designActivate(input: any): any
|
|
33
|
+
switchDeckDesign(input: any): any
|
|
33
34
|
designCreate(input: any): any
|
|
34
35
|
designValidate(input: any): any
|
|
35
36
|
designPreview(input: any): any
|
|
@@ -47,7 +48,7 @@ type RuntimeModule = {
|
|
|
47
48
|
domainDraftValidate(input: any): any
|
|
48
49
|
domainDraftInstall(input: any): any
|
|
49
50
|
reviewDeckRead(input: any): Promise<any>
|
|
50
|
-
|
|
51
|
+
openDeck(input: any): Promise<any>
|
|
51
52
|
researchSave(input: any): any
|
|
52
53
|
prepareLocalMaterials(input: any): Promise<any>
|
|
53
54
|
extractMaterial(input: any): Promise<any>
|
|
@@ -242,6 +243,16 @@ const tools = [
|
|
|
242
243
|
description: "Activate a Revela design for future deck planning and artifact generation.",
|
|
243
244
|
inputSchema: objectSchema({ name: requiredStringProp("Design name to activate.") }, ["name"]),
|
|
244
245
|
},
|
|
246
|
+
{
|
|
247
|
+
name: "revela_switch_deck_design",
|
|
248
|
+
description: "Switch one existing decks/*.html artifact to a design by refreshing its deck-local active design snapshot without rewriting slide content.",
|
|
249
|
+
inputSchema: objectSchema({
|
|
250
|
+
workspaceRoot: stringProp("Optional workspace root."),
|
|
251
|
+
file: requiredStringProp("Workspace-relative or absolute decks/*.html file."),
|
|
252
|
+
name: requiredStringProp("Design name to use for this deck."),
|
|
253
|
+
openBrowser: booleanProp("Whether to open the switched deck in Codex Browser. Defaults to true."),
|
|
254
|
+
}, ["file", "name"]),
|
|
255
|
+
},
|
|
245
256
|
{
|
|
246
257
|
name: "revela_design_create",
|
|
247
258
|
description: "Create and validate a local Revela design package from complete DESIGN.md, design.css, and optional legacy preview.html content.",
|
|
@@ -380,7 +391,7 @@ const tools = [
|
|
|
380
391
|
},
|
|
381
392
|
{
|
|
382
393
|
name: "revela_review_deck_read",
|
|
383
|
-
description: "
|
|
394
|
+
description: "Read optional Review diagnostics for a Revela HTML deck: artifact QA, deck-plan diagnostics, and export/readiness signals.",
|
|
384
395
|
inputSchema: objectSchema({
|
|
385
396
|
workspaceRoot: stringProp("Optional workspace root."),
|
|
386
397
|
file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
|
|
@@ -388,12 +399,11 @@ const tools = [
|
|
|
388
399
|
}, ["file"]),
|
|
389
400
|
},
|
|
390
401
|
{
|
|
391
|
-
name: "
|
|
392
|
-
description: "
|
|
402
|
+
name: "revela_open_deck",
|
|
403
|
+
description: "Open a Revela HTML deck directly in Codex Browser through a read-only localhost URL for user review.",
|
|
393
404
|
inputSchema: objectSchema({
|
|
394
405
|
workspaceRoot: stringProp("Optional workspace root."),
|
|
395
406
|
file: requiredStringProp("Workspace-relative or absolute HTML deck path."),
|
|
396
|
-
bridge: enumProp(["codex-exec"], "Prompt bridge for browser saved-comment Apply interactions."),
|
|
397
407
|
openBrowser: booleanProp("Whether the tool should open the browser itself. Defaults to true when omitted."),
|
|
398
408
|
}, ["file"]),
|
|
399
409
|
},
|
|
@@ -524,6 +534,7 @@ async function callTool(name: string, args: any): Promise<any> {
|
|
|
524
534
|
if (name === "revela_design_read_layout") return r.designReadLayout(args)
|
|
525
535
|
if (name === "revela_design_read_component") return r.designReadComponent(args)
|
|
526
536
|
if (name === "revela_design_activate") return r.designActivate(args)
|
|
537
|
+
if (name === "revela_switch_deck_design") return r.switchDeckDesign(args)
|
|
527
538
|
if (name === "revela_design_create") return r.designCreate(args)
|
|
528
539
|
if (name === "revela_design_validate") return r.designValidate(args)
|
|
529
540
|
if (name === "revela_design_draft_create") return r.designDraftCreate(args)
|
|
@@ -541,7 +552,7 @@ async function callTool(name: string, args: any): Promise<any> {
|
|
|
541
552
|
if (name === "revela_domain_draft_validate") return r.domainDraftValidate(args)
|
|
542
553
|
if (name === "revela_domain_draft_install") return r.domainDraftInstall(args)
|
|
543
554
|
if (name === "revela_review_deck_read") return r.reviewDeckRead(args)
|
|
544
|
-
if (name === "
|
|
555
|
+
if (name === "revela_open_deck") return r.openDeck(args)
|
|
545
556
|
if (name === "revela_research_save") return r.researchSave(args)
|
|
546
557
|
if (name === "revela_prepare_local_materials") return r.prepareLocalMaterials(args)
|
|
547
558
|
if (name === "revela_extract_document_materials") return r.extractMaterial(args)
|
|
@@ -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, annotate, diagnose, QA,
|
|
32
|
+
- Existing deck artifact and the user asks to review, annotate, diagnose, QA, inspect, comment, or refine: use `revela-review`.
|
|
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
|
|
|
@@ -27,7 +27,8 @@ For status, inspection, activation, or selection:
|
|
|
27
27
|
|
|
28
28
|
1. Call `revela_design_list`.
|
|
29
29
|
2. Call `revela_design_read`, `revela_design_inventory`, `revela_design_read_layout`, `revela_design_read_component`, or `revela_page_template_foundation` as needed.
|
|
30
|
-
3. Call `revela_design_activate` only when the user asks to use a design.
|
|
30
|
+
3. Call `revela_design_activate` only when the user asks to use a design for future planning/rendering.
|
|
31
|
+
4. For an existing `decks/*.html` artifact, call `revela_switch_deck_design` with the deck file and design name. This refreshes the deck-local active design snapshot and can reopen the deck without rewriting slide content.
|
|
31
32
|
|
|
32
33
|
For new or edited designs:
|
|
33
34
|
|
|
@@ -41,7 +42,7 @@ For new or edited designs:
|
|
|
41
42
|
8. Call `revela_design_preview` for the draft, start a read-only local static server from the returned `browserHandoff.serveRoot`, and reply with the resulting localhost preview link for the user to open in Codex Browser.
|
|
42
43
|
9. If validation or preview review fails, revise the draft content and repeat draft create/validate/preview.
|
|
43
44
|
10. Call `revela_design_draft_install` only after the draft validates and the user intent is to install it.
|
|
44
|
-
11. Call `revela_design_activate` only when the user asks to make it active.
|
|
45
|
+
11. Call `revela_design_activate` only when the user asks to make it active for future work; use `revela_switch_deck_design` for an already-rendered deck.
|
|
45
46
|
|
|
46
47
|
For sharing or installing design archives:
|
|
47
48
|
|
|
@@ -78,13 +79,13 @@ Use `revela_design_create` only when the user explicitly requests direct local c
|
|
|
78
79
|
- Asset metadata surfaced by read/inventory tools when `assets/**` exists.
|
|
79
80
|
- Saved asset paths and intended uses, for example `assets/cover-background.png -> cover hero background`.
|
|
80
81
|
- Validation result and any remaining diagnostics.
|
|
81
|
-
- Whether the design was activated.
|
|
82
|
+
- Whether the design was activated or an existing deck was switched to that design.
|
|
82
83
|
- Next step, usually `revela-research` for planning with the design or `revela-make-deck` when a valid `deck-plan.md` already exists.
|
|
83
84
|
|
|
84
85
|
## Must Not
|
|
85
86
|
|
|
86
87
|
- Do not write `deck-plan.md`.
|
|
87
|
-
- Do not
|
|
88
|
+
- Do not rewrite slide content in `decks/*.html` while switching design; use `revela_switch_deck_design` to refresh the deck-local active CSS/assets snapshot.
|
|
88
89
|
- Do not patch `decks/_revela-design/**/design.css`; those files are regenerated deck-local snapshots.
|
|
89
90
|
- Do not install or activate a design unless the user requested that outcome.
|
|
90
91
|
- Do not invent licenses, asset provenance, or brand permissions.
|
|
@@ -46,7 +46,7 @@ Report:
|
|
|
46
46
|
- `spec.md` exists but no `researches/`: run `revela-research`.
|
|
47
47
|
- Research exists but no `deck-plan.md`: continue `revela-research` to the Planning Handoff.
|
|
48
48
|
- Valid `deck-plan.md` but no deck artifact: run `revela-make-deck`.
|
|
49
|
-
- Existing deck artifact:
|
|
49
|
+
- Existing deck artifact: run `revela-review` to open the HTML deck directly in Codex Browser, or run `revela-export` for PDF/PPTX/PNG.
|
|
50
50
|
|
|
51
51
|
## Must Not
|
|
52
52
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: revela-review
|
|
3
|
+
description: Open an existing Revela HTML deck directly in Codex Browser for user inspection.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Revela Review
|
|
7
|
+
|
|
8
|
+
Use this skill when the user asks to review, open, inspect, or look at an existing Revela HTML deck artifact in Codex Browser.
|
|
9
|
+
|
|
10
|
+
## Contract
|
|
11
|
+
|
|
12
|
+
- Review is the user-facing browser step after a deck exists.
|
|
13
|
+
- The default path opens the HTML deck itself in Codex Browser without running QA first.
|
|
14
|
+
- Diagnostics are optional: call `revela_review_deck_read` only when the user explicitly asks for QA, readiness, diagnostics, or a written review summary.
|
|
15
|
+
- This skill does not open the legacy comment/apply browser surface, render new decks, or export PDF/PPTX/PNG.
|
|
16
|
+
|
|
17
|
+
## Preconditions
|
|
18
|
+
|
|
19
|
+
- Required: a readable `decks/*.html` file or a user-provided deck HTML file path.
|
|
20
|
+
- If the user gives `@decks/<file>.html`, use that file.
|
|
21
|
+
- If the user asks to review "the deck" and exactly one `decks/*.html` file is present, use it.
|
|
22
|
+
- If multiple deck HTML files are present and the target is unclear, ask the user which deck to open.
|
|
23
|
+
|
|
24
|
+
## Required Tool
|
|
25
|
+
|
|
26
|
+
Call `revela_open_deck` with:
|
|
27
|
+
|
|
28
|
+
- `workspaceRoot` when known.
|
|
29
|
+
- `file` set to the workspace-relative or absolute HTML deck path.
|
|
30
|
+
- `openBrowser` omitted or `true` for the normal user-facing flow.
|
|
31
|
+
|
|
32
|
+
## Optional Diagnostics
|
|
33
|
+
|
|
34
|
+
When the user explicitly asks for QA, readiness, diagnostics, or a written review summary:
|
|
35
|
+
|
|
36
|
+
1. Call `revela_review_deck_read` with the target deck file.
|
|
37
|
+
2. Report artifact QA and deck-plan diagnostics concisely.
|
|
38
|
+
3. Still open Review unless the file is missing or the user asked only for diagnostics.
|
|
39
|
+
|
|
40
|
+
## Output
|
|
41
|
+
|
|
42
|
+
Report:
|
|
43
|
+
|
|
44
|
+
- The deck file opened.
|
|
45
|
+
- The direct deck URL returned by `revela_open_deck`.
|
|
46
|
+
- Whether Codex opened the browser.
|
|
47
|
+
- A short user prompt for what to inspect: copy, argument flow, hierarchy, spacing, charts/tables, visuals, and export readiness.
|
|
48
|
+
- If diagnostics were requested, include the concise diagnostic summary.
|
|
49
|
+
|
|
50
|
+
## Must Not
|
|
51
|
+
|
|
52
|
+
- Do not run QA before opening Review unless the user explicitly asks for diagnostics.
|
|
53
|
+
- Do not open any legacy comment/apply browser surface or token-based review UI.
|
|
54
|
+
- Do not call export tools; route PDF/PPTX/PNG requests to `revela-export`.
|
|
55
|
+
- Do not generate or rewrite `deck-plan.md`.
|
|
56
|
+
- Do not generate a new HTML deck; route rendering requests to `revela-make-deck`.
|
|
57
|
+
- Do not open local deck files directly with `file://`; use the direct deck opener.
|