add examples

This commit is contained in:
Connor Rhodes 2026-04-09 21:14:18 -05:00
parent b8b04d7ca2
commit 2c74317780
5 changed files with 298 additions and 6 deletions

View file

@ -1,7 +1,7 @@
--- ---
name: pov-doc name: pov-doc
description: This skill should be used when the user asks to "write a POV doc," "create a proof of value document," "POV criteria," "proof of concept criteria," "generate a POC document," or discusses creating a proof-of-value or proof-of-concept document for a Verkada customer evaluation. Generates a customer-facing POC/POV criteria document for Verkada physical security product evaluations. description: This skill should be used when the user asks to "write a POV doc," "create a proof of value document," "POV criteria," "proof of concept criteria," "generate a POC document," or discusses creating a proof-of-value or proof-of-concept document for a Verkada customer evaluation. Generates a customer-facing POC/POV criteria document for Verkada physical security product evaluations.
version: 1.0.0 version: 1.1.0
--- ---
# POV Doc # POV Doc
@ -23,13 +23,50 @@ Before generating the document, gather the following from the user's notes and c
Search `~/notes` for account notes, meeting notes, and inbox items related to the customer to populate these fields. Use ripgrep to find relevant content across all note files. Search `~/notes` for account notes, meeting notes, and inbox items related to the customer to populate these fields. Use ripgrep to find relevant content across all note files.
### Logo and Mission Statement
In addition to the fields above, gather these for the document header:
**Customer logo:** Search the web for the customer's official logo. Prefer high-resolution PNG files (at least 1000px wide). Good sources include the customer's website, Wikipedia/Wikimedia Commons, and official brand asset portals. Download the logo to a temporary location (e.g., `/tmp/`). If no high-res version is available, download what you can find and upscale it 4x using Pillow.
**Customer mission statement:** Search the web for the customer's official mission statement. Prefer the most recent version from their website or official publications (district improvement plans, annual reports, etc.). If the customer has both a mission and vision statement, use the mission statement.
Leave both as placeholders in the markdown (`<!-- Image goes here: ... -->` and `*"..."*`). The rendering step below will inject them into the final document.
## Document Generation and Rendering
### Step 1: Generate Markdown
Follow the Document Structure section below to write the markdown document.
### Step 2: Render to .odt
After generating the markdown, render it to a formatted .odt file using the bundled `scripts/render_poc.py` script:
```bash
python3 skills/pov-doc/scripts/render_poc.py \
--input "path/to/[Customer Name] POC Criteria.md" \
--customer-logo /tmp/customer-logo.png \
--mission "Customer mission statement here" \
--output "path/to/[Customer Name] POC Criteria.odt"
```
The script does the following:
1. Replaces logo HTML comments with the actual customer logo and Verkada logo images
2. Updates the mission statement if `--mission` is provided
3. Converts the markdown to .odt using pandoc with the clean reference template (`examples/POC Reference Template.odt`)
The reference template carries over professional formatting (fonts, heading sizes, table styles, page margins) from the City of El Paso example without any customer-specific content.
Dependencies: `pandoc` (on PATH), `Pillow` (for logo resizing).
## Document Structure ## Document Structure
The output document must follow this structure. Each section is required unless the user explicitly says it does not apply. The output document must follow this structure. Each section is required unless the user explicitly says it does not apply.
### Header ### Header
- Document title: `# **Verkada Proof of Concept Criteria**` - Document title: `# **Verkada Proof of Concept Criteria**`
- Customer logo placeholder: `<!-- Image goes here: customer logo -->` - Customer logo placeholder: `<!-- Image goes here: [Customer Name] logo -->`
- Verkada logo placeholder: `<!-- Image goes here: Verkada logo -->` - Verkada logo placeholder: `<!-- Image goes here: Verkada logo -->`
- Customer mission statement (if known), formatted as a blockquote: `*"MISSION STATEMENT HERE"*` - Customer mission statement (if known), formatted as a blockquote: `*"MISSION STATEMENT HERE"*`
- Table of contents with anchor links to each numbered section - Table of contents with anchor links to each numbered section
@ -96,12 +133,15 @@ Numbered list of concrete next actions. Include any steps that have already been
## Examples ## Examples
Two example documents are provided in the `examples/` folder: Example documents are provided in the `examples/` folder:
- `examples/City of El Paso POC Criteria.md` - A completed POV document for a municipal access control evaluation - `examples/City of El Paso POC Criteria.md` - A completed POV document for a municipal access control evaluation
- `examples/Proof of Concept Criteria - TEMPLATE.md` - A template-style POV document for a retail environment - `examples/Proof of Concept Criteria - TEMPLATE.md` - A template-style POV document for a retail environment
- `examples/POC Reference Template.odt` - Clean ODT reference template for pandoc rendering (styles only, no customer content)
Review these examples to match tone, structure, and formatting conventions. The El Paso example shows how to write a finalized document with specific details filled in. The template example shows the structure with placeholder content for a broader product evaluation. Review the markdown examples to match tone, structure, and formatting conventions. The El Paso example shows how to write a finalized document with specific details filled in. The template example shows the structure with placeholder content for a broader product evaluation.
## Output Location ## Output
Write the generated document to `~/notes/Inbox/` with the filename format `[Customer Name] POC Criteria.md`. Write the generated markdown document to `~/notes/Inbox/` with the filename format `[Customer Name] POC Criteria.md`.
After rendering, the .odt file should be placed alongside the markdown or in the same location the user specifies.

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

View file

@ -0,0 +1,252 @@
#!/usr/bin/env python3
"""
Render a Verkada POC Criteria markdown document as a formatted .odt file.
This script takes a POC Criteria markdown file (generated by the pov-doc skill),
replaces logo placeholders and mission statement with actual content, and converts
the result to a professionally formatted .odt using pandoc with a reference document.
Usage:
python render_poc.py --input <markdown_file> --customer-logo <logo.png> \
[--verkada-logo <verkada.png>] [--mission <"mission statement">] \
[--reference-doc <reference.odt>] [--output <output.odt>]
If --verkada-logo is not provided, the Verkada logo placeholder is removed.
If --mission is not provided, the existing mission statement in the markdown is kept.
If --reference-doc is not provided, defaults to the included City of El Paso reference.
If --output is not provided, defaults to the input filename with .odt extension.
Dependencies:
- pandoc (must be installed and on PATH)
- Pillow (for logo resizing)
"""
import argparse
import os
import re
import subprocess
import sys
import tempfile
from pathlib import Path
def find_skill_dir() -> Path:
"""Locate the pov-doc skill directory relative to this script."""
return Path(__file__).resolve().parent.parent
def find_reference_doc() -> Path:
"""Find the default reference ODT template in the skill's examples directory."""
skill_dir = find_skill_dir()
ref = skill_dir / "examples" / "POC Reference Template.odt"
if ref.exists():
return ref
# Fallback: look for the El Paso doc and warn
alt = skill_dir / "examples" / "City of El Paso POC Criteria.odt"
if alt.exists():
print("Warning: using City of El Paso reference (may carry over logos). "
"Run create_reference_template() to generate a clean template.",
file=sys.stderr)
return alt
return None
def find_verkada_logo() -> Path:
"""Find the bundled Verkada logo in the skill's assets directory."""
skill_dir = find_skill_dir()
logo = skill_dir / "assets" / "verkada-logo.png"
if logo.exists():
return logo
return None
def resize_logo_if_needed(input_path: str, max_width_inches: float = 2.75, dpi: int = 150) -> str:
"""
Resize a logo image if it exceeds the target width for print.
Returns the path to the (possibly new) resized image.
"""
try:
from PIL import Image
img = Image.open(input_path)
width_px, height_px = img.size
max_width_px = int(max_width_inches * dpi)
if width_px > max_width_px:
ratio = max_width_px / width_px
new_size = (max_width_px, int(height_px * ratio))
img_resized = img.resize(new_size, Image.LANCZOS)
# Write resized version to a temp file
fd, out_path = tempfile.mkstemp(suffix=".png")
os.close(fd)
img_resized.save(out_path, "PNG")
return out_path
return input_path
except ImportError:
print("Warning: Pillow not installed, skipping logo resize", file=sys.stderr)
return input_path
def process_markdown(
md_content: str,
customer_logo_path: str,
verkada_logo_path: str | None,
mission_statement: str | None,
) -> str:
"""
Process the markdown content:
1. Replace logo HTML comments with markdown image syntax
2. Optionally update the mission statement
3. Remove the Table of Contents section (pandoc can generate one)
"""
# Replace customer logo placeholder (match any logo comment that is NOT Verkada)
md_content = re.sub(
r'<!--\s*Image goes here:(?!.*?Verkada).*?logo.*?-->\s*\n?',
f'![Customer Logo]({customer_logo_path})\n\n',
md_content,
flags=re.IGNORECASE,
)
# Replace Verkada logo placeholder
if verkada_logo_path:
md_content = re.sub(
r'<!--\s*Image goes here:.*?Verkada.*?logo.*?-->\s*\n?',
f'![Verkada Logo]({verkada_logo_path})\n',
md_content,
flags=re.IGNORECASE,
)
else:
# Remove the Verkada logo placeholder entirely
md_content = re.sub(
r'<!--\s*Image goes here:.*?Verkada.*?logo.*?-->\s*\n?',
'',
md_content,
flags=re.IGNORECASE,
)
# Update mission statement if provided
if mission_statement:
# Match the existing italicized mission statement
md_content = re.sub(
r'\*"[^"]*"\*\s*\n',
f'*"{mission_statement}"*\n\n',
md_content,
)
return md_content
def convert_with_pandoc(md_path: str, output_path: str, reference_doc: str) -> bool:
"""Convert markdown to .odt using pandoc with a reference document."""
cmd = [
"pandoc",
md_path,
"-o", output_path,
"--from", "markdown",
"--to", "odt",
"--reference-doc", reference_doc,
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
print(f"pandoc error: {result.stderr}", file=sys.stderr)
return False
return True
except FileNotFoundError:
print("Error: pandoc not found. Install it with your package manager.", file=sys.stderr)
return False
except subprocess.TimeoutExpired:
print("Error: pandoc timed out", file=sys.stderr)
return False
def main():
parser = argparse.ArgumentParser(
description="Render a Verkada POC Criteria markdown document as a formatted .odt file."
)
parser.add_argument("--input", "-i", required=True, help="Path to the POC Criteria markdown file")
parser.add_argument("--customer-logo", required=True, help="Path to the customer logo image")
parser.add_argument("--verkada-logo", help="Path to the Verkada logo image (optional)")
parser.add_argument("--mission", help="Customer mission statement (replaces existing)")
parser.add_argument("--reference-doc", help="Path to reference .odt for formatting")
parser.add_argument("--output", "-o", help="Output .odt path (default: same as input with .odt)")
args = parser.parse_args()
# Validate input file
input_path = Path(args.input)
if not input_path.exists():
print(f"Error: input file not found: {input_path}", file=sys.stderr)
sys.exit(1)
# Validate customer logo
if not os.path.isfile(args.customer_logo):
print(f"Error: customer logo not found: {args.customer_logo}", file=sys.stderr)
sys.exit(1)
# Find reference doc
reference_doc = args.reference_doc or find_reference_doc()
if not reference_doc or not Path(reference_doc).exists():
print("Error: reference document not found. Provide --reference-doc or place the "
"City of El Paso POC Criteria.odt in the skill's examples directory.",
file=sys.stderr)
sys.exit(1)
# Find Verkada logo
verkada_logo = args.verkada_logo or find_verkada_logo()
if verkada_logo and not Path(verkada_logo).exists():
verkada_logo = None
# Determine output path
if args.output:
output_path = args.output
else:
output_path = str(input_path.with_suffix(".odt"))
# Resize logos for print
customer_logo_resized = resize_logo_if_needed(args.customer_logo)
verkada_logo_resized = resize_logo_if_needed(verkada_logo) if verkada_logo else None
# Read and process markdown
md_content = input_path.read_text(encoding="utf-8")
processed = process_markdown(
md_content,
customer_logo_resized,
verkada_logo_resized,
args.mission,
)
# Write processed markdown to temp file (so image paths work)
fd, temp_md = tempfile.mkstemp(suffix=".md")
os.close(fd)
try:
with open(temp_md, "w", encoding="utf-8") as f:
f.write(processed)
# Convert with pandoc
print(f"Converting {input_path.name} to {output_path}...")
print(f" Reference doc: {reference_doc}")
if verkada_logo:
print(f" Verkada logo: {verkada_logo}")
success = convert_with_pandoc(temp_md, output_path, reference_doc)
if success:
out_size = os.path.getsize(output_path)
print(f"Done: {output_path} ({out_size:,} bytes)")
else:
sys.exit(1)
finally:
# Clean up temp files
os.unlink(temp_md)
if customer_logo_resized != args.customer_logo:
os.unlink(customer_logo_resized)
if verkada_logo_resized and verkada_logo_resized != verkada_logo:
os.unlink(verkada_logo_resized)
if __name__ == "__main__":
main()