@cyber-dash-tech/revela 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/skill/SKILL.md CHANGED
@@ -136,8 +136,9 @@ Each axis gets its own dedicated agent with a focused brief. Launch ALL agents
136
136
  in a single message (parallel Task tool calls).
137
137
 
138
138
  **How to decompose:** Look at what the presentation needs to cover. Each major
139
- entity, comparison dimension, or macro question is a separate axis. Typical
140
- decompositions:
139
+ entity, comparison dimension, or macro question is a separate axis. Decompose
140
+ based on topic breadth and the depth each axis warrants — a narrow topic may
141
+ need 2 axes; a complex comparison may need 4 or more. Typical decompositions:
141
142
 
142
143
  | Topic type | Example axes |
143
144
  |---|---|
@@ -146,38 +147,7 @@ decompositions:
146
147
  | Investment thesis | Opportunity metrics, risk factors, comparable deals, macro trends |
147
148
  | Product strategy | User research, competitor features, technology feasibility, go-to-market |
148
149
 
149
- **3+ axes 3+ parallel agents.** Never collapse everything into one brief.
150
-
151
- ##### Invocation Example — Multi-Agent Parallel
152
-
153
- For a topic like "Investment shift from OpenAI to Anthropic":
154
-
155
- ```
156
- Agent 1 (Anthropic):
157
- > Research Anthropic's trajectory for a presentation on AI investment shifts:
158
- > - Funding history: Series rounds, valuations, key investors
159
- > - Revenue and growth: run-rate, enterprise adoption, key products
160
- > - Competitive advantages: safety positioning, developer tools, reliability
161
- > Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
162
-
163
- Agent 2 (OpenAI):
164
- > Research OpenAI's challenges for a presentation on AI investment shifts:
165
- > - Financial: burn rate, profitability timeline, cost structure
166
- > - Operational: API reliability data, outage frequency, enterprise complaints
167
- > - Governance: nonprofit conversion, leadership controversies, investor concerns
168
- > Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
169
-
170
- Agent 3 (Market & Capital Flow):
171
- > Research AI industry capital flow for a presentation on AI investment shifts:
172
- > - VC investment patterns: dual-backing trends, secondary market activity
173
- > - Enterprise adoption: market share shifts, switching patterns
174
- > - Macro trends: agentic AI adoption, market size projections
175
- > Focus on 2025-2026 data. Write findings to researches/ai-investment-shift/
176
- ```
177
-
178
- Launch all agents in **one message** using parallel Task tool calls. Each agent
179
- runs independently and writes its own findings file:
180
- `researches/{topic-slug}/{axis-name}.md`
150
+ Launch ALL agents in a single message (parallel Task tool calls).
181
151
 
182
152
  Each agent's brief should specify:
183
153
  - The topic slug (shared, e.g. `ai-investment-shift`)
@@ -192,20 +162,9 @@ each `.md` file. Each file contains structured `## Data`, `## Cases`,
192
162
  Cross-reference agent findings with workspace documents (Layer 1). Flag any
193
163
  contradictions.
194
164
 
195
- ##### Fallback — ONLY if Research Agent is Unavailable
196
-
197
- If and only if the Task tool with `subagent_type: "revela-research"` is **not
198
- available as a tool** (i.e., it does not exist in your tool list), fall back to
199
- using `webfetch` directly on targeted URLs. Even in fallback mode, structure
200
- your research by axis — do not run a single vague query.
201
-
202
- Note: `websearch` is blocked by the Revela plugin when agents are available.
203
- In fallback mode, use `webfetch` with specific URLs from your knowledge.
204
-
205
165
  **Anti-pattern — NEVER do this:**
206
- - Do NOT use `websearch` directly — it is blocked by the Revela plugin to
207
- enforce systematic research. Use research agents (or `webfetch` for specific
208
- URLs in fallback mode).
166
+ - Do NOT use `websearch` directly — it is blocked by the Revela plugin;
167
+ use research agents instead.
209
168
  - Do NOT run a few quick searches, decide "that's enough data", and skip the
210
169
  research agent. The agent's job is deep, systematic research — ad-hoc
211
170
  fetches cannot replace it.
@@ -273,13 +232,15 @@ A 6-slide deck might be: Cover → Background → Content × 3 → Closing.
273
232
  An 8-slide deck might be: Cover → TOC → Background → Content × 3 → Summary → Closing.
274
233
  Never skip Cover, Background, or Closing regardless of slide count.
275
234
 
276
- **Every `<section class="slide">` must include a `data-slide-type` attribute** declaring its structural role:
235
+ **Every `<section class="slide">` must include a `slide-qa` attribute.** Set
236
+ `slide-qa="true"` for content-heavy layouts (those marked ✓ in the Layout Index
237
+ QA column of the active design). Set `slide-qa="false"` for structural or sparse
238
+ layouts (cover, TOC, closing, quote, summary, etc.). When unsure, use `"false"`.
277
239
 
278
- <!-- @slide-types -->
240
+ Example: `<section class="slide" slide-qa="true" data-index="0">`
279
241
 
280
- Example: `<section class="slide" data-slide-type="cover" data-index="0">`
281
-
282
- The layout QA system uses this to skip fill-ratio and spacing checks on structural slides that are intentionally sparse.
242
+ The layout QA system uses this to skip fill-ratio and spacing checks on slides
243
+ that are intentionally sparse.
283
244
 
284
245
  ### Domain Context
285
246
 
@@ -342,96 +303,17 @@ Follow these rules on every generation. They are non-negotiable.
342
303
 
343
304
  ### Inline Editing
344
305
 
345
- **Always include inline editing** in every generated presentation. This enables
346
- users to click any text element and edit it directly in the browser, then
347
- export the changes.
348
-
349
- Implementation rules:
350
-
351
- - **JS-based hover activation** — attach `mouseenter` / `mouseleave` listeners
352
- on editable elements. After a 400ms hover delay, show a subtle outline to
353
- indicate editability. Click activates `contenteditable`. Click outside or
354
- press Escape to deactivate.
355
- - **Never** use CSS `~` sibling selector (breaks due to `pointer-events: none`
356
- interrupting the hover chain).
357
- - **Editable elements** — only text content: `h1, h2, h3, h4, p, span, li,
358
- blockquote, cite` and design-specific text classes (`.card-title`, `.card-body`,
359
- `.stat-number`, `.stat-label`, `.stat-desc`, `.step-title`, `.step-desc`).
360
- Never make structural containers or images editable.
361
- - **Hover style** — `outline: 1px dashed rgba(128,128,128,0.3)` on hover,
362
- `outline: 2px solid rgba(59,130,246,0.5)` when actively editing. Keep it
363
- subtle — must not interfere with the design aesthetic.
364
- - **`window.getEditedHTML()`** — always define this global function. It returns
365
- the full edited HTML (`'<!DOCTYPE html>\n' + document.documentElement.outerHTML`).
366
- The parent frame calls this to retrieve the full edited HTML for saving.
367
-
368
- Reference implementation (include in the `<script>` block after `SlidePresentation`):
369
-
370
- ```javascript
371
- // --- Inline Editing ---
372
- (function() {
373
- const EDITABLE = 'h1,h2,h3,h4,p,span,li,blockquote,cite,' +
374
- '.card-title,.card-body,.stat-number,.stat-label,.stat-desc,' +
375
- '.step-title,.step-desc';
376
- let hoverTimer = null;
377
- let activeEl = null;
378
-
379
- document.querySelectorAll(EDITABLE).forEach(el => {
380
- el.addEventListener('mouseenter', () => {
381
- hoverTimer = setTimeout(() => {
382
- el.style.outline = '1px dashed rgba(128,128,128,0.3)';
383
- el.style.cursor = 'text';
384
- }, 400);
385
- });
386
- el.addEventListener('mouseleave', () => {
387
- clearTimeout(hoverTimer);
388
- if (el !== activeEl) {
389
- el.style.outline = '';
390
- el.style.cursor = '';
391
- }
392
- });
393
- el.addEventListener('click', (e) => {
394
- if (activeEl && activeEl !== el) {
395
- activeEl.contentEditable = 'false';
396
- activeEl.style.outline = '';
397
- activeEl.style.cursor = '';
398
- }
399
- el.contentEditable = 'true';
400
- el.style.outline = '2px solid rgba(59,130,246,0.5)';
401
- el.style.cursor = 'text';
402
- activeEl = el;
403
- e.stopPropagation();
404
- });
405
- });
406
-
407
- document.addEventListener('click', () => {
408
- if (activeEl) {
409
- activeEl.contentEditable = 'false';
410
- activeEl.style.outline = '';
411
- activeEl.style.cursor = '';
412
- activeEl = null;
413
- }
414
- });
415
- document.addEventListener('keydown', (e) => {
416
- if (e.key === 'Escape' && activeEl) {
417
- activeEl.contentEditable = 'false';
418
- activeEl.style.outline = '';
419
- activeEl.style.cursor = '';
420
- activeEl = null;
421
- }
422
- });
423
-
424
- window.getEditedHTML = () =>
425
- '<!DOCTYPE html>\n' + document.documentElement.outerHTML;
426
- })();
427
- ```
306
+ **Always include inline editing** in every generated presentation. The complete
307
+ reference implementation is provided in the active design's `@design:foundation`
308
+ section. Follow it exactly — pay attention to the hover-delay pattern, editable
309
+ element selector list, and `window.getEditedHTML()` definition.
428
310
 
429
311
  ### Image Rules
430
312
 
431
313
  - Use direct file paths (`src="assets/logo.png"`) in HTML — not base64
432
314
  - Always use the **original** file path in HTML `<img src>` for full-quality rendering
433
315
  - Never repeat the same image on multiple slides (logos: title + closing only)
434
- - Image compression is handled automatically by the server (see File Access Rules below)
316
+ - Image compression is handled automatically by the server
435
317
  - **Use the active design's image components** (`.image-card`, `.card-img`, `.avatar`)
436
318
  for displaying images — they provide proper rounded corners and cropping
437
319
 
@@ -615,62 +497,4 @@ The active design name is in the HTML comment at the top of this prompt:
615
497
  The active design's complete visual specification — Component Library, Layout
616
498
  Primitives, Composition Guide, and Data Visualization rules — is injected
617
499
  below after the `---` separator. This is your sole visual reference for
618
- generating slides.
619
-
620
- ---
621
-
622
- ## What Comes Next in This System Prompt
623
-
624
- After the `---` separators below, two additional sections may appear:
625
-
626
- 1. **Domain definition** (if a domain other than "general" is active) — report
627
- structure, AI logic rules, terminology, and visual preferences for the domain.
628
- 2. **Visual style** (from the active design) — colors, fonts, animation specifics,
629
- layout variants. Apply it precisely — it overrides any default aesthetic preferences.
630
-
631
- If only one `---` section follows, it is the visual style (no domain is active).
632
-
633
- ---
634
-
635
- ## File Access Rules
636
-
637
- ### How tools interact with files
638
-
639
- The workspace `.ignore` file prevents binary formats from appearing in `grep`,
640
- `glob`, and `list` results (these tools use ripgrep, which honours `.ignore`).
641
- The `read` tool works by **direct file path** and is **not** affected by
642
- `.ignore` — if you have a path, you can always `read` it.
643
-
644
- ### Documents
645
-
646
- `.pdf` `.xlsx` `.xls` `.docx` `.doc` `.pptx` `.ppt` `.csv`
647
-
648
- If the `extract` tool is available, use it to extract document content as clean
649
- markdown text. **NEVER** use the `read` tool on PDF, Excel, Word, or PPT files
650
- — their raw binary content will flood the context window.
651
-
652
- If the `extract` tool is NOT available, use `read` only for text-based formats
653
- (`.csv`, plain text). For binary document formats, inform the user and ask them
654
- to provide the content in text form.
655
-
656
- ### Images
657
-
658
- `.png` `.jpg` `.jpeg` `.gif` `.webp` `.bmp` `.tiff` `.tif` `.avif`
659
-
660
- Use the `read` tool to view images directly (OpenCode returns them as visual
661
- attachments). In HTML, always reference the original file path for full-quality
662
- rendering:
663
-
664
- ```html
665
- <img src="photos/screenshot.png" alt="...">
666
- ```
667
-
668
- ### Binary files — never access
669
-
670
- These are excluded from all tools:
671
-
672
- `.mp4` `.mov` `.avi` `.mkv` `.webm` `.m4v` `.wmv`
673
- `.mp3` `.wav` `.ogg` `.flac` `.aac` `.m4a`
674
- `.zip` `.tar` `.gz` `.bz2` `.7z` `.rar` `.tgz`
675
- `.woff` `.woff2` `.ttf` `.otf` `.eot`
676
- `.db` `.sqlite` `.sqlite3` `.bin` `.exe` `.dll` `.so` `.dylib`
500
+ generating slides.
package/tools/designs.ts CHANGED
@@ -7,8 +7,10 @@ import {
7
7
  removeDesign,
8
8
  parseDesignSections,
9
9
  generateComponentIndex,
10
+ generateLayoutIndex,
10
11
  getDesignSection,
11
12
  getDesignComponent,
13
+ getDesignLayout,
12
14
  } from "../lib/design/designs"
13
15
  import { buildPrompt } from "../lib/prompt-builder"
14
16
  import { existsSync, readFileSync } from "fs"
@@ -23,7 +25,7 @@ export default tool({
23
25
  "Use action 'activate' to switch to a different design (requires name). " +
24
26
  "Use action 'install' to add a new design from a URL, local path, or github:user/repo shorthand (requires source). " +
25
27
  "Use action 'remove' to uninstall a design (requires name). " +
26
- "Use action 'read' to fetch on-demand design content: pass component (comma-separated names) to get full CSS/HTML for specific components, or section ('charts' | 'guide' | 'global' | 'layouts' | 'components') to get an entire section. Pass neither to get the Component Index table. " +
28
+ "Use action 'read' to fetch on-demand design content: pass layout (comma-separated names) to get full HTML/CSS for specific layouts, pass component (comma-separated names) to get full CSS/HTML for specific components, or section ('chart-rules' | 'foundation' | 'layouts' | 'components') to get an entire section. Pass neither to get the Component Index table. " +
27
29
  "After activating a new design, the system prompt is automatically rebuilt.",
28
30
  args: {
29
31
  action: tool.schema
@@ -39,6 +41,12 @@ export default tool({
39
41
  .describe(
40
42
  "Install source — URL, local path, github:user/repo. Required for install."
41
43
  ),
44
+ layout: tool.schema
45
+ .string()
46
+ .optional()
47
+ .describe(
48
+ "For action 'read': comma-separated layout name(s) to fetch (e.g. 'cover', 'two-col,card-grid')"
49
+ ),
42
50
  component: tool.schema
43
51
  .string()
44
52
  .optional()
@@ -49,7 +57,7 @@ export default tool({
49
57
  .string()
50
58
  .optional()
51
59
  .describe(
52
- "For action 'read': section name to fetch — 'charts', 'guide', 'global', 'layouts', or 'components'"
60
+ "For action 'read': section name to fetch — 'chart-rules', 'foundation', 'rules', 'layouts', or 'components'"
53
61
  ),
54
62
  },
55
63
  async execute(args) {
@@ -96,13 +104,18 @@ export default tool({
96
104
  }
97
105
  const raw = readFileSync(mdPath, "utf-8")
98
106
  const { body } = parseFrontmatter(raw)
99
- const { components, hasMarkers } = parseDesignSections(body)
107
+ const { layouts, components, hasMarkers } = parseDesignSections(body)
100
108
 
101
109
  if (!hasMarkers) {
102
110
  // No markers — return full body
103
111
  return body
104
112
  }
105
113
 
114
+ // Specific layout(s) requested
115
+ if (args.layout) {
116
+ return getDesignLayout(args.layout, designName)
117
+ }
118
+
106
119
  // Specific component(s) requested
107
120
  if (args.component) {
108
121
  return getDesignComponent(args.component, designName)
@@ -113,8 +126,11 @@ export default tool({
113
126
  return getDesignSection(args.section, designName)
114
127
  }
115
128
 
116
- // Default: return Component Index
117
- return generateComponentIndex(components)
129
+ // Default: return Layout Index + Component Index
130
+ const li = generateLayoutIndex(layouts)
131
+ const ci = generateComponentIndex(components)
132
+ const parts = [li, ci].filter(Boolean)
133
+ return parts.join("\n\n---\n\n") || "(no layouts or components found)"
118
134
  }
119
135
  default:
120
136
  return JSON.stringify({ error: `Unknown action: ${args.action}` })