+ )
+ }
+
// Option-based step
if (onboardingStep.options.length > 0) {
return (
diff --git a/app/ui_layer/browser/frontend/src/types/index.ts b/app/ui_layer/browser/frontend/src/types/index.ts
index a6d55b27..d312df36 100644
--- a/app/ui_layer/browser/frontend/src/types/index.ts
+++ b/app/ui_layer/browser/frontend/src/types/index.ts
@@ -533,6 +533,15 @@ export interface OnboardingStepOption {
requires_setup?: boolean // Whether this option needs API key or additional setup
}
+export interface OnboardingFormField {
+ name: string
+ label: string
+ field_type: 'text' | 'select' | 'multi_checkbox'
+ options: OnboardingStepOption[]
+ default: string | string[]
+ placeholder: string
+}
+
export interface OnboardingStep {
name: string
title: string
@@ -543,6 +552,7 @@ export interface OnboardingStep {
options: OnboardingStepOption[]
default: string | string[] | null
provider?: string | null // only present on the api_key step
+ form_fields?: OnboardingFormField[] | null // present on form steps (e.g., user_profile)
}
// ─────────────────────────────────────────────────────────────────────
diff --git a/app/ui_layer/onboarding/controller.py b/app/ui_layer/onboarding/controller.py
index e433b9cc..4a68cf7f 100644
--- a/app/ui_layer/onboarding/controller.py
+++ b/app/ui_layer/onboarding/controller.py
@@ -9,6 +9,7 @@
ProviderStep,
ApiKeyStep,
AgentNameStep,
+ UserProfileStep,
MCPStep,
SkillsStep,
HardOnboardingStep,
@@ -67,6 +68,7 @@ class OnboardingFlowController:
ProviderStep,
ApiKeyStep,
AgentNameStep,
+ UserProfileStep,
MCPStep,
SkillsStep,
]
@@ -287,11 +289,18 @@ def _complete(self) -> None:
for skill_name in selected_skills:
enable_skill(skill_name)
- # Initialize language from OS locale (first launch only)
- self._initialize_user_language()
+ # Write user profile data to USER.md (replaces _initialize_user_language)
+ user_profile = self._state.collected_data.get("user_profile", {})
+ if user_profile:
+ from app.onboarding.profile_writer import write_profile_to_user_md
+ write_profile_to_user_md(user_profile)
+ else:
+ # Fallback: initialize language from OS locale if profile step was skipped
+ self._initialize_user_language()
# Mark hard onboarding complete
- onboarding_manager.mark_hard_complete(agent_name=agent_name)
+ user_name = user_profile.get("user_name") if user_profile else None
+ onboarding_manager.mark_hard_complete(user_name=user_name, agent_name=agent_name)
# Trigger soft onboarding now that hard onboarding is done
# This is needed because the soft onboarding check in agent.run() happens
@@ -362,10 +371,10 @@ def get_step_info(self) -> Dict[str, Any]:
Get comprehensive information about the current step.
Returns:
- Dictionary with step metadata, options, and progress
+ Dictionary with step metadata, options, progress, and form_fields
"""
step = self.get_current_step()
- return {
+ info = {
"name": step.name,
"title": step.title,
"description": step.description,
@@ -376,3 +385,23 @@ def get_step_info(self) -> Dict[str, Any]:
"total_steps": len(self.STEP_CLASSES),
"progress": self.get_progress_text(),
}
+
+ # Include form fields if the step has them (e.g., UserProfileStep)
+ form_fields = getattr(step, 'get_form_fields', lambda: [])()
+ if form_fields:
+ info["form_fields"] = [
+ {
+ "name": f.name,
+ "label": f.label,
+ "field_type": f.field_type,
+ "options": [
+ {"value": o.value, "label": o.label, "description": o.description, "default": o.default}
+ for o in f.options
+ ],
+ "default": f.default,
+ "placeholder": f.placeholder,
+ }
+ for f in form_fields
+ ]
+
+ return info
diff --git a/requirements.txt b/requirements.txt
index bd6fdd9f..6cc79a4e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -45,3 +45,4 @@ watchdog
telethon
croniter>=2.0.0 # Cron expression parsing for scheduler
playwright # WhatsApp Web browser automation
+babel>=2.14.0 # Language list for onboarding
diff --git a/skills/file-format/SKILL.md b/skills/file-format/SKILL.md
new file mode 100644
index 00000000..e15de7a1
--- /dev/null
+++ b/skills/file-format/SKILL.md
@@ -0,0 +1,129 @@
+---
+name: file-format
+description: "Use this skill BEFORE generating any file output — PDF, PPTX, DOCX, XLSX, HTML, or Markdown. Triggers include: any request to create, produce, or generate a document, presentation, spreadsheet, report, memo, proposal, invoice, resume, or any formatted file. Also use when the user asks to update formatting preferences, style standards, or brand guidelines. This skill provides a 3-layer formatting lookup: global standards, file-type rules, and document-purpose rules. Always invoke this skill before the file-type-specific skill (docx, pptx, xlsx, pdf)."
+---
+
+# File Format Standards
+
+## Overview
+
+This skill provides consistent formatting and design standards across all file outputs. It ensures consistent branding, typography, layout, and structure across every file type and document purpose the agent generates.
+
+Standards live in `resources/FORMAT.md`, organized into three layers that the agent reads on demand.
+
+---
+
+## How to Read FORMAT.md
+
+`resources/FORMAT.md` is divided into sections using `## section-name` headings. Each section is separated by a `---` horizontal rule divider.
+
+**To extract the formatting rules you need:**
+
+1. Use grep to search `resources/FORMAT.md` for the section keyword (e.g., `"## pptx"`, `"## finance-report"`)
+2. Read from the matched `## heading` down to the next `---` divider — that is the complete section
+3. Each section is self-contained: everything between `## heading` and the next `---` belongs to that section
+
+**Section types in FORMAT.md:**
+
+- `## global` — universal standards (always at the top)
+- `## ` — file-format-specific rules (e.g., `## pptx`, `## docx`, `## xlsx`, `## pdf`, `## md`, `## html`)
+- `## ` — document-purpose-specific rules (e.g., `## finance-report`, `## seo-audit`, `## meeting-minutes`)
+
+Users can add their own file-type or purpose sections at any time. Do not assume the list is fixed — always search for a match.
+
+---
+
+## 3-Layer Lookup Process
+
+**Before generating any file, perform these lookups IN ORDER:**
+
+### Layer 1: Global Standards (ALWAYS read)
+
+Search for `## global` in `resources/FORMAT.md`. Read the entire section.
+
+This section defines universal rules: brand color palette, typography scale, writing conventions, and general layout. These apply to every file you generate.
+
+### Layer 2: File-Type Standards (ALWAYS read)
+
+Search `resources/FORMAT.md` for the `## ` section matching your output format. The section name matches the file extension or format name.
+
+Examples:
+- Generating a `.pptx` file → search for `## pptx`
+- Generating a `.docx` file → search for `## docx`
+- Generating a `.pdf` file → search for `## pdf`
+
+If the exact file type is not found, fall back to Layer 1 global standards only.
+
+These sections override or extend global standards with format-specific rules (slide setup, page margins, cell formatting, etc.). Each file-type section typically contains: setup, color application, typography overrides, structure rules, and common mistakes to avoid.
+
+### Layer 3: Document Purpose Standards (read WHEN APPLICABLE)
+
+Search `resources/FORMAT.md` for the `## ` section matching the document's purpose or category. Purpose sections are listed after the file-type sections under the heading `# Document Purpose Standards`.
+
+Examples:
+- Creating a quarterly earnings report → search for `## finance-report`
+- Creating an SEO audit → search for `## seo-audit`
+- Creating meeting notes → search for `## meeting-minutes`
+
+**How to find the right purpose section:** Identify the purpose or category of the document from the user's request, then search for it as a keyword in `resources/FORMAT.md`. If no matching purpose section exists, skip Layer 3.
+
+Purpose sections follow the same structure as file-type sections — they provide formatting overrides (color application, typography, layout, data formatting, structure rules, common mistakes), not content guidance. Apply them on top of Layers 1 and 2.
+
+If no purpose section matches the user's request, skip Layer 3.
+
+---
+
+## Conflict Resolution
+
+When rules from different layers conflict:
+
+- **Layer 3 (purpose) overrides Layer 2 (file-type) overrides Layer 1 (global)**
+- The more specific rule always wins
+- Example: Global says "left-align body text", but `## legal-doc` says "justified text is acceptable" — use justified for legal documents
+
+---
+
+## Multi-Purpose Documents
+
+Some requests span multiple purposes (e.g., "create a financial proposal"). When this happens:
+
+1. Read all applicable purpose sections
+2. Apply all non-conflicting rules from each
+3. For conflicts between purpose sections, prefer the section closer to the user's primary intent
+4. When in doubt, ask the user which purpose takes priority
+
+---
+
+## Purpose Detection
+
+When the user's request does not explicitly name a purpose category, infer it from context:
+
+- "quarterly earnings" or "P&L" or "budget" or "forecast" -> `## finance-report`
+- "SEO" or "keyword ranking" or "backlink" or "site audit" -> `## seo-audit`
+- "meeting notes" or "action items from the call" or "minutes" -> `## meeting-minutes`
+- "pitch" or "proposal" or "RFP" -> `## proposal`
+- "executive summary" or "brief" or "one-pager" -> `## executive-summary`
+- "newsletter" or "internal update" or "company news" -> `## newsletter`
+- "resume" or "CV" or "cover letter" -> `## resume`
+- "contract" or "NDA" or "terms" or "agreement" -> `## legal-doc`
+
+These are examples — not an exhaustive list. Users may add custom purpose sections. Always search FORMAT.md for a match based on the document's purpose keywords.
+
+If the purpose is ambiguous, proceed with only Layers 1 and 2, or ask the user.
+
+---
+
+## Updating Standards
+
+Users can request changes to formatting preferences. When they do:
+
+1. Read the current `resources/FORMAT.md`
+2. Identify the correct section to update (global, file-type, or purpose)
+3. Make the edit within that section, following the existing structure pattern
+4. Confirm the change with the user
+
+To add a new file-type or purpose section:
+1. Add it after the existing sections of the same type (file-type sections go before the `# Document Purpose Standards` heading, purpose sections go after)
+2. Use `## section-name` as the heading
+3. Follow the same subsection structure as existing sections (color application, typography, layout, structure rules, common mistakes to avoid)
+4. End the section with a `---` divider
diff --git a/skills/file-format/resources/FORMAT.md b/skills/file-format/resources/FORMAT.md
new file mode 100644
index 00000000..6ec6c690
--- /dev/null
+++ b/skills/file-format/resources/FORMAT.md
@@ -0,0 +1,706 @@
+# Formatting Standards
+
+Agent reads this before generating any file. Edit to customize.
+`## global` = universal. `## ` = type-specific overrides. `## ` = document-purpose overrides.
+
+---
+
+## global
+
+### Colors
+- Base: `#141517` (deep grey — primary background/text on light)
+- Surface: `#1E1F22` (card/panel bg in dark contexts)
+- Muted: `#6B6E76` (secondary text, captions, borders)
+- Border: `#2E2F33` (dividers, table lines, rules)
+- White: `#FFFFFF` (bg on light, text on dark)
+- Light grey: `#F4F4F5` (alt row shading, subtle bg)
+- Highlight: `#FF4F18` (accent — sparingly: key stats, active states, CTAs, emphasis)
+- Highlight hover: `#E64615` (darker variant for pressed/hover states)
+
+**Usage rules:**
+- Highlight is for emphasis only — never large fills, never body text color.
+- Max 1–2 highlight elements per page/slide/section.
+- Body text is always base or white depending on bg.
+
+### Typography
+- Font family: Roboto (all weights). Fallback: Arial, Helvetica, sans-serif.
+- Weights: 300 (Light), 400 (Regular), 500 (Medium), 700 (Bold).
+
+| Role | Size | Weight | Color | Spacing |
+|---|---|---|---|---|
+| Display / hero | 32–40pt | 700 | base or white | line-height 1.1, letter-spacing -0.5px |
+| H1 | 22–26pt | 700 | base or white | line-height 1.2, margin-bottom 16px |
+| H2 | 16–18pt | 700 | base or white | line-height 1.25, margin-bottom 12px |
+| H3 | 13–14pt | 500 | base or muted | line-height 1.3, margin-bottom 8px |
+| Body | 11pt | 400 | base | line-height 1.5, paragraph spacing 10px |
+| Small / caption | 9–10pt | 300 or 400 | muted | line-height 1.4 |
+| Code / mono | 10pt | 400 | base | font: Roboto Mono, line-height 1.45 |
+
+### Writing & Content
+- Sentence case for all headings. Never ALL CAPS except single-word labels (e.g., "NOTE").
+- Em dashes (—) not hyphens. Curly quotes not straight.
+- Left-align body. Never justify (causes uneven word spacing).
+- One idea per paragraph. Max 4 sentences per paragraph.
+- Prefer active voice. No filler ("It is important to note that…" → cut).
+- Numbers: spell out one–nine, digits for 10+. Always digits for units (3 kg, 5 min).
+
+### General Layout
+- Whitespace is a design element — do not fill every gap.
+- Visual hierarchy: size → weight → color. Not decoration.
+- Max content width: 7" (print), 720px (screen).
+- Consistent internal padding: 12–20px or 0.2–0.3" in print contexts.
+
+---
+
+## pptx
+
+### Slide setup
+- 16:9 widescreen (13.333" × 7.5"). No 4:3.
+- Safe margins: 0.5" all sides. Keep all content inside.
+- Grid: mentally divide slides into 12 columns for alignment.
+
+### Color application
+- Title/section slides: base `#141517` full-bleed bg, white text, highlight accent stripe or element.
+- Content slides: white bg, base text. Highlight for one focal element only.
+- Charts/graphs: use base, muted, light grey as series colors. Highlight for the one key series.
+
+### Typography (slide-specific)
+| Role | Size | Weight |
+|---|---|---|
+| Slide title | 32–36pt | 700 |
+| Subtitle / section | 18–22pt | 300 or 400 |
+| Bullet text | 16–18pt | 400 |
+| Data callout / stat | 44–56pt | 700, highlight color |
+| Source / footnote | 9–10pt | 300, muted |
+
+### Content rules
+- DO NOT excessively use list of 3–5 bullet points per slide, which is a common LLM mistake.
+- Max 6 words per bullet headline. Supporting text below if needed (12–14pt, muted).
+- One key message per slide. If you can't state it in one sentence, split.
+- Ideally, every slide should have a visual: chart, diagram, icon, image, or shape block. No text-only slides.
+- Trying using varying layout or blocks across the deck/slice: full-bleed image, two-column, stat callout, comparison grid, timeline.
+
+### Common mistakes to avoid (unless specify otherwise)
+- **Over use of bullet points:** Using 3-5 bullets for every pages.
+- **Uniform layout:** every slide is title + bullets. Fix: alternate layouts every 2–3 slides.
+- **Oversized tables:** tables with 5+ columns or 8+ rows are unreadable. Fix: simplify, show top 5, or use a chart.
+- **Missing visual hierarchy:** all text same size/weight. Fix: title ≠ body ≠ caption.
+- **Image bleeds off slide or wrong aspect ratio:** always set image dimensions explicitly within safe area. Never stretch.
+- **Orphan slides:** a single-bullet slide or a slide that only says "Thank you." Combine or enrich.
+- **Inconsistent alignment:** elements randomly placed. Fix: snap to grid, align to slide's left margin.
+- **Overusing highlight color:** more than 2 highlight elements per slide dilutes emphasis.
+
+---
+
+## docx
+
+### Page setup
+- US Letter 8.5" × 11". Margins: 1" top/bottom, 1" left/right.
+- Header: 0.5" from top edge. Footer: 0.5" from bottom edge.
+- Page numbers: bottom-center, Roboto 9pt, muted color.
+
+### Typography (doc-specific)
+| Role | Size | Weight | Color | Extra |
+|---|---|---|---|---|
+| Title (doc) | 26pt | 700 | base | 24px below, optional highlight underline |
+| H1 | 18pt | 700 | base | 18px above, 10px below, border-bottom 1px muted |
+| H2 | 14pt | 700 | base | 14px above, 8px below |
+| H3 | 11pt | 700 | base | 12px above, 6px below |
+| Body | 11pt | 400 | base | line-height 1.5, 10px paragraph spacing |
+| Blockquote | 11pt | 400 italic | muted | left border 3px highlight, 12px left padding |
+| Table header | 10pt | 700 | white on base bg | |
+| Table cell | 10pt | 400 | base | alt row: light grey bg |
+
+### Structure rules
+- **Max heading depth: 3 levels.** Never use H4+. If you need it, restructure.
+- **Sections:** Do not over-segment. A 2-page doc should not have 10 headings. A section should have more paragraphs rather than just 2-3 sentences. Otherwise, merge sections.
+- **Paragraph length:** Must not have less than 2–5 sentences.
+- **Lists:** Do not over-use list.
+- **Tables:** use only for genuinely tabular data (rows × columns). Do not use tables for layout or for simple lists.
+- **Table sizing:** max 5 columns. More than 5 → rotate to vertical layout or split. Column widths must be set explicitly — never auto-width with overflow.
+- **Horizontal rules:** use sparingly to separate major sections. Max 2–3 per document.
+
+### Common mistakes to avoid (unless specify otherwise)
+- **Over-sectioning:** every paragraph gets its own heading. Fix: merge related short sections.
+- **List abuse:** entire document is nested bullet lists. Fix: write in prose. Lists are for parallel items only.
+- **Table for everything:** using a 2-column table instead of a definition list or bold+colon. Fix: use inline formatting.
+- **Extra page breaks:** a section breaks mid-page awkwardly.
+- **Inconsistent spacing:** different gaps between headings and body. Fix: define and reuse paragraph styles.
+- **Images not anchored:** images float to wrong page or overlap text. Fix: set inline positioning, explicit width (max 6.5" for full-width), and keep-with-next.
+- **Image too large:** image exceeds printable area. Fix: max width = page width minus margins. Always set explicit dimensions.
+- **Phantom empty paragraphs:** blank lines used for spacing. Fix: use paragraph spacing, not empty returns.
+- **Font fallback failure:** Roboto not embedded → falls back to Times New Roman. Fix: embed fonts or use a guaranteed-available fallback.
+
+---
+
+## xlsx
+
+### Sheet setup
+- Default column width: 14 characters. Adjust per content.
+- Freeze top row (header) and first column (labels) by default.
+- Zoom: 100%. Never deliver at odd zoom levels.
+- Print area: set explicitly if document may be printed.
+- Sheet names: short, no spaces (use underscores), max 20 chars.
+
+### Cell formatting
+| Element | Font | Size | Color | Background |
+|---|---|---|---|---|
+| Header row | Roboto Bold | 11pt | white | base `#141517` |
+| Data cell | Roboto Regular | 10pt | `#141517` | white |
+| Alt row | Roboto Regular | 10pt | `#141517` | `#F4F4F5` |
+| Total/summary row | Roboto Bold | 10pt | `#141517` | `#E8E8EA` border-top 2px |
+| Highlight cell | Roboto Bold | 10pt | `#FF4F18` | — |
+
+### Number formatting
+- Currency: `$#,##0` (no decimals) or `$#,##0.00` (two decimals). Be consistent within a sheet.
+- Percentages: `0.0%` (one decimal).
+- Integers: `#,##0` with thousands separator.
+- Negatives: parentheses `(1,234)` not minus `-1,234`. Red text optional.
+- Dates: `YYYY-MM-DD`. Never `MM/DD/YY`.
+- Don't mix formatted and unformatted numbers in same column.
+
+### Financial model conventions
+- Blue `#0000FF`: hardcoded inputs/assumptions.
+- Black: calculated formulas.
+- Green `#008000`: cross-sheet or external references.
+- Yellow bg `#FFFF00`: key assumption cells.
+
+### Structure rules
+- **One topic per sheet.** Don't combine unrelated tables on one sheet.
+- **Header row is row 1.** No merged title rows above data. Use sheet name for title.
+- **No merged cells in data ranges.** Merged cells break sorting, filtering, and formulas.
+- **No blank rows/columns** within data ranges. Blank rows break auto-detection.
+- **Column order:** identifiers first (name, ID, date), then measures, then calculations, then notes.
+- **Wrap text** for cells with >30 chars. Set explicit row height.
+
+### Common mistakes to avoid (unless specify otherwise)
+- **Merged cells:** breaks all data operations. Fix: never merge in data areas. Only merge in clearly decorative headers outside data range.
+- **Formulas as values:** pasting values when formulas are needed. Fix: always verify formula references.
+- **Inconsistent number formats:** same column has `$1,000` and `1000.00`. Fix: apply format to entire column.
+- **Hidden data:** rows/columns hidden and forgotten. Fix: unhide all before delivery.
+- **No header row:** data starts at A1 with no labels. Fix: always include descriptive headers.
+- **Overly wide sheets:** 20+ columns requiring horizontal scroll. Fix: split into multiple sheets or pivot layout.
+- **Print overflow:** data prints across 5 pages wide. Fix: set print area, fit to 1 page wide.
+- **Circular references:** fix before delivery. If intentional, document in a Notes sheet.
+- **Hard-coded numbers in formulas:** `=A1*0.08` instead of referencing a tax rate cell. Fix: externalize assumptions.
+
+---
+
+## pdf
+
+### Page setup
+- US Letter 8.5" × 11". Margins: 1" all sides.
+- Header: base `#141517` bar (0.4" tall), white text left-aligned (document title, Roboto 9pt).
+- Footer: centered page number, Roboto 9pt, muted `#6B6E76`.
+- First page may omit header for a custom title block.
+
+### Typography
+- Same as docx standards. Body: Roboto 11pt, headings: Roboto Bold.
+- Use ReportLab XML markup for superscripts, subscripts if applicable.
+- Embed all fonts. Never rely on system fonts.
+
+### Design
+- Section dividers: 1px line in muted color, full content width.
+- Callout boxes: light grey `#F4F4F5` bg, left border 3px highlight `#FF4F18`, 10px padding.
+- Tables: same style as docx (base header bg, alt row shading).
+- Cover page (if applicable): base bg full page, white title 32pt center, highlight accent line.
+
+### Structure rules
+- **Max heading depth: 3 levels.** Never use H4+. If you need it, restructure.
+- **Sections:** Do not over-segment. A 2-page doc should not have 10 headings. A section should have more paragraphs rather than just 2-3 sentences. Otherwise, merge sections.
+- **Paragraph length:** Must not have less than 2–5 sentences.
+- **Lists:** Do not over-use list.
+- **Tables:** use only for genuinely tabular data (rows × columns). Do not use tables for layout or for simple lists.
+- **Table sizing:** max 5 columns. More than 5 → rotate to vertical layout or split. Column widths must be set explicitly — never auto-width with overflow.
+- **Horizontal rules:** use sparingly to separate major sections. Max 2–3 per document.
+
+### Common mistakes to avoid (unless specify otherwise)
+- **Images not rendering:** wrong path, unsupported format, or not embedded. Fix: use absolute paths, embed images, verify format (PNG/JPG).
+- **Image exceeds margins:** overflows into margin or off-page. Fix: set max width = page width − 2× margin. Always calculate available space.
+- **Text overlaps elements:** manually positioned text collides with tables or images. Fix: use flowable layout, not absolute coordinates (unless precise placement is required).
+- **Broken table across pages:** table starts near page bottom, header row orphaned. Fix: use repeatRows for header, allow table to split cleanly.
+- **Wrong page size:** defaulting to A4 when US Letter expected. Fix: set explicitly.
+- **Missing fonts:** tofu characters (□). Fix: embed TTF files, register before use.
+- **Massive file size:** uncompressed images. Fix: resize images to display size before embedding. Max 150 DPI for screen, 300 DPI for print.
+- **Raw markup in output:** PDF shows literal `## Heading` or `**bold**` instead of rendered formatting. Fix: ensure all markdown/markup is fully converted to native PDF elements (styled paragraphs, bold spans, etc.) before rendering. Never pass raw markdown text directly into PDF content.
+- **Over-sectioning:** every paragraph gets its own heading. Fix: merge related short sections.
+- **List abuse:** entire document is nested bullet lists. Fix: write in prose. Lists are for parallel items only.
+- **Table for everything:** using a 2-column table instead of a definition list or bold+colon. Fix: use inline formatting.
+- **Extra page breaks:** a section breaks mid-page awkwardly.
+- **Inconsistent spacing:** different gaps between headings and body. Fix: define and reuse paragraph styles.
+- **Images not anchored:** images float to wrong page or overlap text. Fix: set inline positioning, explicit width (max 6.5" for full-width), and keep-with-next.
+- **Image too large:** image exceeds printable area. Fix: max width = page width minus margins. Always set explicit dimensions.
+- **Phantom empty paragraphs:** blank lines used for spacing. Fix: use paragraph spacing, not empty returns.
+- **Font fallback failure:** Roboto not embedded → falls back to Times New Roman. Fix: embed fonts or use a guaranteed-available fallback.
+
+---
+
+## md
+
+### Formatting
+- ATX headings only (`#`, `##`, `###`). Max depth: 3 levels.
+- One blank line before and after headings, code blocks, and block quotes.
+- No trailing whitespace. No multiple consecutive blank lines.
+- Fenced code blocks with language identifier: ` ```python `. Never indented code blocks.
+- Links: inline `[text](url)` for fewer than 3 links. Reference-style `[text][id]` for 3+.
+- Images: `` — always include alt text.
+- Bold: `**text**`. Italic: `_text_`. Never use `__` or `*` for these.
+
+### Structure rules
+- **Front matter:** if used, YAML only (`---` delimiters).
+- **Heading hierarchy:** never skip levels (no H1 → H3).
+- **Lists:** max 7 items. Nested lists max 2 levels. Use `-` for unordered (not `*`).
+- **Tables:** max 5 columns. Always include header separator `|---|`. Align consistently.
+- **Line length:** wrap at 100 characters for readability in raw form (unless the target is rendered-only).
+- **Paragraphs:** 2–5 sentences. Single-sentence paragraphs only for emphasis.
+
+### Content conventions
+- **README files:** order sections as: title, description (1–2 lines), installation, usage, configuration, API/reference, contributing, license.
+- **Documentation:** lead with what it does, then how to use it, then edge cases/details.
+- **No HTML** in Markdown unless absolutely necessary (complex tables, embedded media).
+
+### Common mistakes to avoid (unless specify otherwise)
+- **Over-nesting lists:** 4+ indent levels. Fix: flatten or restructure into subsections.
+- **Heading as formatting:** using `###` just to make text bold. Fix: use `**bold**`.
+- **No blank lines around blocks:** heading immediately followed by text or code fence. Fix: always add blank lines.
+- **Giant tables:** 10+ column tables in Markdown are unreadable raw. Fix: simplify or link to CSV.
+- **Inconsistent list markers:** mixing `-`, `*`, `+`. Fix: use `-` everywhere.
+- **Raw URLs:** bare `https://...` without link syntax. Fix: wrap in `<>` or `[label](url)`.
+- **Over-use of emphasis:** every other word is **bold** or _italic_. Fix: emphasis means rare.
+
+---
+
+## html
+
+### Setup
+- DOCTYPE: ``. Lang attribute set.
+- Viewport meta: ``.
+- Charset: UTF-8.
+- Use semantic tags: ``, ``, ``, ``, `