Skip to content

Reports & Presentations

vita's report system turns research, analysis, meetings, and operational evidence into durable artifacts: Markdown documents, designed HTML reports, HTML slide decks, and PDFs. Files on disk are the source of truth for report content. SQLite adds lifecycle classification, keyword and semantic retrieval, interaction history, and grouping; a verified publisher can expose selected artifacts through tokenized, optionally PIN-gated URLs at vita-reports.ham.xyz.

The central design principle is:

Report content is durable because it is a file in data/reports/; most discovery state in reports.db can be rebuilt from those files. Exact interaction rowsβ€”especially per-token attributionβ€”cannot be reconstructed after DB loss, so deleting the database is not operationally lossless.

Not every evidence product is a report. In particular, document-flow produces a live documentation canvas, and /oneshot may choose a canvas or another proof surface. Those artifacts are adjacent to the report system but do not automatically enter reports.db.

System flow

research / meetings / production data / human brief
                         |
                         v
       Markdown, HTML, slides, or PDF in data/reports/
                         |
          +--------------+----------------+
          |                               |
          v                               v
 Sentinel + API self-heal           verified publisher
          |                         reports.publish
          v                               |
 reports.db                              v
 metadata + FTS5 + vectors         vita-reports.ham.xyz
 lifecycle + interactions          token + optional PIN
          |
          v
 /reports UI + /api/reports + reports.search CLI

There are deliberately two completion boundaries:

  1. Authored means the durable file exists and can be indexed locally.
  2. Published means reports.publish has fetched the share back through the public domain and verified the expected report or PIN gate. Minting a token alone is not a successful handoff.

The data model

A report is identified by a base slug, such as 2026-07-15-some-analysis. Files sharing that base are treated as formats of the same logical report:

File Role
{slug}.md Markdown body with YAML frontmatter; normally the canonical format
{slug}.html Designed single-file HTML version, or an HTML-only report
{slug}-slides.html HTML slide-deck version
{slug}.pdf PDF version, supported by public sharing
{slug}-assets/ Per-report images and other assets

The conventional filename is YYYY-MM-DD-short-description.md. The date prefix is a fallback sort key and contributes to series detection.

PDF is currently a sharing format rather than a first-class indexed family: the report index exposes has_html and has_slides, but no equivalent has_pdf field. A PDF-only artifact therefore has weaker discovery in /reports unless it also has Markdown or HTML metadata.

Frontmatter

Markdown reports carry YAML frontmatter. HTML reports carry equivalent metadata in a leading <!-- ... --> comment.

---
title: "Report Title"
date: "2026-07-15"
project: project-slug
tags: [research, strategy, analysis]
description: "Optional one-line summary."
parent: 2026-07-14-overview
---

Report content in Markdown...

The canonical indexer in scripts/reports/index_db.py parses Markdown frontmatter with yaml.safe_load. HTML comment metadata uses a simpler line-oriented key: value parser. Some API mutation paths also edit individual frontmatter lines, so simple scalar fields and inline tag lists are the most interoperable authoring style. A parent ending in .md is normalized to the bare slug.

Three ways reports relate

These mechanisms solve different problems:

Grouping Source of truth Cardinality Set by
Parent/child frontmatter parent one parent per report PATCH /{slug}/parent or file edit
Series reports.db machine-clustered members detect_series() during reclassification
Collections data/reports/collections.json ordered many-to-many lists collections API or /reports UI

Parent/child represents one logical document split into parts. Series is heuristic clustering by project, titles, and dates. Collections are manually curated playlists and can cross project boundaries.

Where state lives

Path or table Contents
data/reports/{slug}.* durable report files; source of truth for content
data/reports/{slug}-assets/ per-report assets
data/reports/reports.db SQLite metadata, FTS, vectors, lifecycle, changelog, series, and interactions
reports / reports_fts indexed metadata and FTS5 text
report_vectors / reports_vec embedding hashes and sqlite-vec vector index
changelog edit history used by lifecycle classification and the UI
interactions timestamped activity rows, including source and optional share token
series / series_members detected report families
data/reports/.report-state.json legacy pin/star/view/revision state retained for compatibility
data/reports/.shares.json share-token registry: token to slug, format, PIN, and kind
data/reports/collections.json durable curated collections
data/reports/.history/{slug}/ backups made by the LLM editor

The legacy state file and database coexist. Current write paths update both where compatibility requires it. Search, lifecycle ranking, changelog, semantic vectors, and token-attributed interactions live in the database; file scanning remains the content fallback when the DB is unavailable. Metadata, FTS, vectors, and lifecycle can be regenerated. Historical interaction rows and their token attribution cannot.

Generating reports

Report generation is intentionally not one universal pipeline. Choose based on the desired artifact and quality bar.

Path Best for Trade-off
generate_html_report_v2 substantial, polished HTML reports multi-stage, slower, roughly $3–7 per report
generate_html_report drafts and high-volume HTML faster and cheaper, one-shot visual judgment
generate_presentation / frontend-slides viewport-fitted HTML decks slide constraints rather than document layout
specialized skills WBR, engineering, offsite, or other domain-specific evidence opinionated sourcing, review, and publishing contracts

All core generators write into data/reports/. Publication is a separate step; use verified publishing when another person needs the public URL.

Designed HTML: v2 multi-stage pipeline

scripts/reports/generate_html_v2.py is the default for substantial designed reports. It turns a brief into a single-file HTML report plus a {slug}-assets/ directory:

  1. Design spec β€” Claude Opus 4.7 produces a structured visual and narrative specification.
  2. Image assets β€” gpt-image-2 renders the specification's image manifest in parallel.
  3. Implement β€” Opus produces complete HTML using the brief, spec, asset paths, and optional design exemplars.
  4. Render β€” Playwright captures 1440, 900, and 390-pixel-wide screenshots.
  5. Critique β€” a multimodal pass compares the renders with the design spec.
  6. Refine β€” Opus applies the critique to the HTML.

Stages 4–6 repeat when refine_iters >= 2. The module supports stage caching/resume and records token/cost usage in its result.

from scripts.reports.generate_html_v2 import generate_html_report_v2

result = generate_html_report_v2(
    title="Report Title",
    content="all research and source material",
    project="project-slug",
    tags=["research", "strategy"],
)
.venv/bin/python scripts/reports/generate_html_v2.py "Title" path/to/brief.md \
  --project project-slug --tags research,strategy

Useful controls include --style-hints, --slug, --no-images, --no-refine, and --refine-iters.

Designed HTML: legacy single-shot

scripts/reports/generate_html.py sends the brief through one Gemini 3.1 Pro OpenRouter call. It is the fast, inexpensive option for drafts and repeated production. It also backs POST /api/reports/{slug}/generate-html.

from scripts.reports.generate_html import generate_html_report

result = generate_html_report(
    title="Report Title",
    content="source material",
    style_hints="optional design direction",
    project="project-slug",
    tags=["draft"],
)

The practical distinction is quality control: v2 separates art direction, implementation, real rendering, critique, and refinement; legacy asks one model call to make all those decisions at once. Neither path proves factual correctness. Grounding, claim review, and publish verification remain the caller's responsibility.

Model strings and cost constants are pinned in the generator modules and will drift over time. See model guidance rather than treating this page as the model registry.

Slide presentations and frontend-slides

scripts/reports/generate_presentation.py produces self-contained HTML decks with slides fixed to 100vh/100dvh, no per-slide scrolling, keyboard/touch/wheel navigation, transitions, navigation dots, a progress bar, responsive height breakpoints, and reduced-motion handling. Output uses the -slides.html suffix and carries a presentation tag.

from scripts.reports.generate_presentation import generate_presentation

result = generate_presentation(
    title="Deck Title",
    content="# Slide 1\nIntro\n# Slide 2\nEvidence",
    style_preset="Swiss Modern",
    project="project-slug",
)

The frontend-slides skill at .claude/skills/frontend-slides/SKILL.md adds a more interactive workflow for creating decks from scratch or converting PPT/PPTX files. It uses visual style discovery, can reuse the 12 presets in STYLE_PRESETS.md, and validates that every slide fits the viewport. Use the module when the outline and aesthetic are already known; use frontend-slides when visual exploration or conversion is part of the task.

Editing an existing Markdown report

scripts/reports/edit_report.py has two modes:

  • Simple (edit_simple) β€” synchronous edit returned directly.
  • Agent (edit_agent) β€” asynchronous agent edit returning a task ID to poll.

Both back up the previous file to data/reports/.history/{slug}/{timestamp}.md and append a changelog entry. The API exposes these through POST /{slug}/edit and GET /{slug}/edit/{task_id}.

Indexing and lifecycle

Autonomous indexing

scripts/sentinel/report_sentinel.py is a Sentinel ScriptResponder for filesystem changes under data/reports/:

watchdog event -> SentinelLoop -> report_sentinel
               -> hash files -> two-tick stability check
               -> index stable changes

The stability check avoids reading a report while it is still being written. A stable change updates metadata, diff/changelog information, FTS content, and lifecycle fields.

GET /api/reports is a second, rate-limited backstop. Every 30 seconds at most, it finds unindexed Markdown/HTML files and synchronizes derived changelog fields. It also reconciles has_html and has_slides for already-indexed rows, so adding a new format to an existing report no longer requires deleting and rebuilding its row.

When newly discovered files are indexed, the API launches a detached semantic backfill. Otherwise it throttles semantic refresh to roughly hourly. Content hashes prevent unchanged reports from being re-embedded.

Lifecycle classification

scripts/reports/lifecycle.py evaluates stages in this order; first match wins:

Stage Rule
active edited within 7 days, or at least 3 interactions in 7 days
living at least 3 changelog entries on at least 3 distinct days
reference at least 10 views and no edit in 30 days
recent created within 14 days
archive everything else

Manual lifecycle_override always wins. A final NULL sweep ensures a failed per-row classification cannot leave reports invisible: unclassified reports younger than 14 days become recent; older ones become archive.

Relevance scoring combines recency, interaction, edit frequency, and manual state, with title-sensitive half-lives. Meeting-prep and recurring-meeting artifacts decay quickly; runbooks and reference material decay much more slowly. Dashboard, library, search, and project views apply different ranking emphases.

Series detection

scripts/reports/series.py groups reports within a project by normalized title/date patterns and Jaccard similarity. A cluster needs at least three related reports. Reclassification rewrites series and series_members, and API responses expose series_key, series_name, series_position, and series_total.

Retrieval and discovery

The reports subsystem has its own retrieval path. It is distinct from Vita's broader long-term-memory search.

scripts/reports/search.py supports three modes:

Mode Behavior
keyword FTS5 prefix matching with BM25 weighting
semantic cosine-nearest-neighbor search over report embeddings
smart reciprocal-rank fusion of keyword and semantic results; default

Keyword ranking weights title most heavily, followed by tags, description, body content, and changelog. Search responses can include a highlighted snippet, score, and match_type so the UI can explain why a result appeared.

Structured operators can be combined with free text:

Operator Examples
project project:vita, proj:rwgps, p:cadence
tags tag:strategy, tags:research
lifecycle lifecycle:active, stage:reference
format format:html, type:slides
dates after:2026-07-01, since:2026-07-01, before:2026-08-01
state is:starred, is:pinned

A filter-only query returns matching rows ordered by date. The CLI talks directly to SQLite and therefore remains useful when the API or web app is down:

PYTHONPATH=scripts uv run python -m reports.search \
  'capabilities project:vita after:2026-07-01' --mode smart --limit 5

PYTHONPATH=scripts uv run python -m reports.search \
  'lifecycle:reference tag:runbook' --json

Results include slug, title, date, project, score, match type, snippet, and the absolute report path.

Semantic index

scripts/reports/semantic.py stores 1,536-dimensional text-embedding-3-small vectors in the same reports.db using sqlite-vec. Each embedding is derived from title, description, and stripped report body, capped at 7,000 characters with a smaller retry on token overflow.

The semantic index is a deliberate dual write: metadata lives in report_vectors; vectors live in reports_vec. Backfill batches up to 50 reports, falls back to individual requests if a batch fails, skips unchanged content by hash, and prunes vectors for deleted reports.

uv run python -m scripts.reports.semantic backfill
uv run python -m scripts.reports.semantic backfill --force
uv run python -m scripts.reports.semantic search 'why was this architecture chosen?'

If sqlite-vec or embedding access is unavailable, smart search degrades to keyword-only and emits a warning instead of making the whole report library unavailable.

API surface

The internal API runs on port 33800 (./run api). api/src/routers/reports.py is mounted at /api/reports; collections and public sharing are separate routers.

Static endpoints such as /search, /stats, and /reclassify must remain declared before the /{slug} catch-all.

/api/reports

Method Endpoint Purpose
GET `` List reports; filters include lifecycle, query, view, tag, and project; q uses smart search
GET /search?q=&mode=smart Ranked smart, keyword, or semantic retrieval
GET /stats Counts by lifecycle/project plus activity summaries
POST /reclassify Reclassify lifecycle and detect series; called by /sleep
GET /{slug} Content, metadata, revisions, and recent changelog
GET /{slug}/html Serve raw HTML and record an html_serve interaction
GET /{slug}/assets/{filename} Serve a path-traversal-guarded report asset
GET /{slug}/changelog Paginated changelog
PATCH /{slug}/state Set pinned/starred
PATCH /{slug}/project Update project frontmatter
PATCH /{slug}/parent Set or clear parent frontmatter
PATCH /{slug}/lifecycle Set or clear lifecycle override
POST /{slug}/interact Record a web_view interaction on the base slug
POST /{slug}/generate-html Asynchronously generate legacy HTML from Markdown
POST /{slug}/presentation Asynchronously generate slides from an existing report
POST /{slug}/edit Run a simple or agent-mode Markdown edit
GET /{slug}/edit/{task_id} Poll an agent edit
DELETE /{slug}/format/{fmt} Delete HTML or slides while retaining the Markdown primary

ReportMeta includes frontmatter plus derived fields: format flags, excerpt, cover image, lifecycle, relevance, view/edit counts, activity sparkline, timestamps, parent/children, collections, series, public-share status and PIN, and search fields (snippet, search_score, match_type). ReportContent additionally includes content, revisions, and changelog rows.

Collections API

/api/collections is backed by scripts/reports/collections.py and collections.json, not SQLite.

Method Endpoint Purpose
GET / POST /api/collections list or create collections
GET / PATCH / DELETE /api/collections/{id} inspect, update, reorder, or delete
POST / DELETE /api/collections/{id}/members/{slug} add or remove a member

Updating members is a full ordered replacement, which is also how collections are reordered.

Verified public publishing

The agent-facing publishing primitive is scripts/reports/publish.py. Report-producing workflows should use it instead of hand-written curl calls.

PYTHONPATH=scripts uv run python -m reports.publish 2026-07-15-report-slug \
  --format html --pin 1234

PYTHONPATH=scripts uv run python -m reports.publish \
  --verify-token EXISTING_TOKEN

Supported formats are primary, markdown, html, slides, and pdf. --pin "" explicitly clears an existing PIN; --notify queues a Telegram link only after verification. Publishing is idempotent for the same slug and format, so updating a live report does not mint a new token or break its URL.

The publisher verifies the public domain, not merely localhost:

  1. POST the share request to the local API.
  2. GET https://vita-reports.ham.xyz/s/{token}, retrying one transient network failure.
  3. For open shares, require a nontrivial body and a report-title marker.
  4. For PIN shares, require the gate markers and confirm that the report title did not leak. The verifier never submits or logs the PIN.

Failures are attributed to the failing leg: report/report-file, local API, tunnel/public API, or content verification. A public 404 is checked against the same token on the local API to distinguish a dangling share from stale public infrastructure. The command emits one JSON result containing slug, token, url, pin, verified, and per-leg checks.

--no-verify exists for exceptional debugging, but it does not satisfy the normal publish contract.

Through-the-domain smoke

scripts/reports/domain_smoke.py validates the whole share surface:

  • Offline: cross-reference every report token in .shares.json against files on disk and classify valid, orphaned, format-dangling, and malformed records.
  • Network: sample current open shares across formats and one PIN share through the public domain.
  • Freshness: compare the domain health endpoint's git SHA/code freshness with local HEAD so stale code cannot masquerade as a successful content test.
PYTHONPATH=scripts uv run python -m reports.domain_smoke
PYTHONPATH=scripts uv run python -m reports.domain_smoke --offline-only
PYTHONPATH=scripts uv run python -m reports.domain_smoke --token TOKEN
./run smoke-reports

--strict-dangling turns historical dangling entries into failures. --network-optional is used by fast verification so a down stack is a visible skip rather than a false content failure. Service monitoring uses --freshness-only --grace-minutes 30.

Public sharing details

api/src/routers/shared_reports.py serves individual reports and collections on vita-reports.ham.xyz. The registry is data/reports/.shares.json.

POST /api/reports/{slug}/share?format=primary&pin=1234
  -> { token, url: "https://vita-reports.ham.xyz/s/{token}" }

Sharing a parent also shares its children. A corrupt registry is an honest HTTP 503; an unknown token is a plain 404; a valid token whose file has disappeared returns a styled 404 tombstone. These distinctions matter operationally because they separate infrastructure failure, invalid links, and rename/deletion drift.

PIN gate

  • PINs are stored plaintext in .shares.json; this is a convenience gate, not high-assurance authentication.
  • Before unlock, GET /s/{token} returns only the gate and sends no report data.
  • POST /s/{token}/unlock compares the PIN server-side, keeping it out of URLs and access logs.
  • A successful unlock sets a 180-day, path-scoped, httpOnly, SameSite=Lax cookie; it is Secure under HTTPS.
  • The unlock key is never exposed to page JavaScript or placed in the URL.

Rendering

  • Markdown shares render as responsive standalone pages with a table of contents when there are at least two headings, print styles, dark/light support, and copy-Markdown control.
  • Links to another shared Markdown report are rewritten to that report's share URL.
  • HTML shares receive a <base href="/s/{token}/"> so relative assets resolve under the token.
  • Slides serve {slug}-slides.html directly; PDFs are served inline.
  • primary chooses HTML when present, then Markdown.

Interactions and token attribution

reports.db.interactions records report_slug, timestamp, source, and optional share token. Current sources include:

  • web_view from POST /api/reports/{slug}/interact
  • html_serve from the internal HTML route
  • public_share after public content is actually served
  • share_unlock after a correct PIN

The token answers β€œwhich link was opened?” when multiple links point to the same report. Interaction writes on the public path are best-effort and never block delivery. A gated report may record share_unlock followed by public_share when the browser reloads after unlocking; viewing the locked gate alone is not counted as a report open.

The raw attribution exists, but there is not yet a dedicated token-analytics API or UI. Querying or aggregating it currently requires direct database work.

Collections

POST   /api/collections/{collection_id}/share
DELETE /api/collections/{collection_id}/share
GET    /c/{token}

The public collection page preserves curated member order. Sharing ensures each member has a primary report token. Tokens created only for a collection are marked via_collection so unsharing can remove them unless another collection or an individual share still needs them.

Web UI (/reports)

web/src/routes/reports/ implements the report library and viewer on the web app (port 33801). The current surface includes:

  • dashboard, gallery, list, and mobile layouts
  • lifecycle, project, tag, type, and state filtering
  • server-backed hybrid search with snippets and match labels
  • covers, excerpts, format/lifecycle badges, and activity metadata
  • Markdown/HTML report viewing, document-title updates, and report actions
  • collection creation, membership, reordering, and sharing

The internal UI exposes share_pin for owner convenience. That makes /reports an administrative surface; it is not suitable for untrusted viewers.

Specialized evidence pipelines

These workflows are documented here because they produce reports or closely related evidence, but their domain logic belongs in their skill files.

document-flow: shipping-flow documentation

The exact surface name is document-flow, defined at .claude/skills/document-flow/SKILL.md. It documents an existing, shipping product flow rather than building or validating a proposed change.

Its output is a live documentation canvas published at /cv/{token}, not a file in data/reports/. A complete flow combines:

  • every user-visible state at desktop and mobile widths
  • real screenshots, not mockups
  • live Amplitude volume/funnel/property-split measures
  • a deep link from every metric card to the exact chart supporting it
  • event coverage and instrumentation gaps
  • methodology and denominator definitions

Totals, unique users, and funnel conversion answer different questions, so the metric contract is chosen explicitly before authoring. Instrumentation gaps remain visible rather than being papered over. Use document-flow when the artifact must remain a live map of a shipping experience; use a report when the output is primarily a durable narrative or analysis.

engineering-report: contribution weight analysis

The exact surface name is engineering-report, at .claude/skills/engineering-report/SKILL.md. It compares named engineers by reading every merged PR diff and assigning engineering weight based on difficulty, judgment, debugging, design, and riskβ€”not lines changed.

The workflow normalizes by available working days from a fresh Deel out-of-office export, calibration-audits scoring across engineers, creates Markdown plus a terse HTML report, and publishes the HTML through verified, PIN-gated reports.publish.

Its limits are material: it sees GitHub-visible work, depends on a fresh manual OOO export, can be affected by PR-splitting behavior, and becomes expensive/rate-limited at large PR volumes. Scores are decision support, not an objective measure of human value.

wbr: Weekly Business Review

The exact surface name is wbr, at .claude/skills/wbr/SKILL.md. It creates a best-attempt first-draft Weekly Business Review for the L10, then refines it collaboratively.

The workflow retrieves prior editions and templates with reports.search, gathers current PR, support, growth, canvas, offsite, and working-memory evidence, renders an HTML report with traceable links, and publishes it through reports.publish. Sensitive strategy or personally identifying detail requires a PIN. Edits update the same file and therefore retain the same share token.

offsite-report: operational recap plus data validation

The exact surface name is offsite-report, at .claude/skills/offsite-report/SKILL.md. It turns a long multi-speaker recording into two coordinated artifacts:

  1. an operational recap with decisions, rocks, owners, tensions, and unresolved issues; and
  2. a supplemental production-data report that tests claims against live business data.

The workflow uses diarized transcription, a human speaker-map checkpoint, map-reduce extraction, editorial synthesis, adversarial review, and a human content checkpoint. scripts/meetings/build_offsite_report.py and build_data_report.py render the approved data. Both outputs are verified through the domain and normally PIN-gated.

/oneshot: evidence-first high-stakes work

.claude/skills/oneshot/SKILL.md is an opt-in, high-stakes plan -> work -> verify -> present workflow. It is not another report generator. Its presentation stage chooses the evidence surface appropriate to the work: a Cadence artifact for RWGPS, or a Vita canvas/report-like artifact elsewhere. Real screenshots, primary-source evidence, and adversarial review are required. Only outputs actually written into data/reports/ enter this subsystem.

CGM metabolic PDF

scripts/reports/cgm_report.py generates a four-page PDF from local CGM data: executive dashboard, daily profiles, variability analysis, and patterns/insights. The composite metabolic score weights time in range (35%), coefficient of variation (25%), mean glucose (20%), time below the low threshold (10%), and MAGE (10%).

uv run python scripts/reports/cgm_report.py
uv run python scripts/reports/cgm_report.py --recipient "Dr. Example"
uv run python scripts/reports/cgm_report.py --start 2026-07-01 --end 2026-07-07

CGM data is health-sensitive. Generate locally and use PIN-gated PDF sharing when a public-domain handoff is necessary.

Candid limitations

  • Files and DB can diverge briefly. Sentinel, the 30-second list self-heal, format reconciliation, and semantic backfill reduce drift; they do not make a multi-store transaction.
  • Database deletion is content-safe, not history-safe. The file library and most indexes can be reconstructed, but detailed interaction/token rows cannot.
  • Semantic search is an optional external dependency. It requires embedding access and sqlite-vec; keyword search is the designed fallback.
  • Semantic bodies are truncated. Very long reports are represented by title, description, and the first bounded body segment, not every paragraph.
  • is:shared is incomplete. The parser/UI vocabulary recognizes it, but ranked-row filtering currently has no shared field to enforce. Use the API's shared metadata or inspect .shares.json until this is fixed.
  • PDF discovery is weak. Sharing supports PDF, while the core index and format filters focus on Markdown, HTML, and slides.
  • Interaction analytics are raw. Token attribution is stored but lacks an aggregate endpoint, bot filtering, unique-view semantics, or a first-class UI.
  • PINs are convenience gates. They are plaintext at rest and should not be treated as identity, authorization, revocation auditing, or high-security access control.
  • Share registry cleanup is not automatic. Domain smoke finds orphaned and format-dangling entries; historical drift may remain until explicitly repaired.
  • Generated polish is not factual verification. The v2 visual critique checks design against a spec, not claims against primary sources. Specialized workflows add their own evidence and human checkpoints.
  • document-flow canvases are a separate system. They are public/live evidence pages but are not indexed, searched, classified, or collected as reports.

Maintenance and file map

Path Role
scripts/reports/generate_html_v2.py multi-stage designed HTML generator
scripts/reports/generate_html.py legacy single-shot HTML generator
scripts/reports/generate_presentation.py HTML slide generator
scripts/reports/edit_report.py simple and agent-mode Markdown editor
scripts/reports/index_db.py SQLite schema, parsing, FTS, interactions, and indexing
scripts/reports/search.py structured keyword/semantic/smart retrieval and CLI
scripts/reports/semantic.py vector schema, embedding backfill, and KNN search
scripts/reports/lifecycle.py lifecycle and relevance classification
scripts/reports/series.py automatic series detection
scripts/reports/collections.py durable collections store
scripts/reports/publish.py idempotent, through-domain verified publisher
scripts/reports/domain_smoke.py registry, content, PIN-gate, and code-freshness smoke
scripts/reports/cgm_report.py CGM PDF builder
scripts/reports/render.py Markdown render helper
scripts/reports/similarity.py similarity helpers for series detection
scripts/reports/backfill_descriptions.py one-shot description backfill
scripts/reports/backfill_markdown.py one-shot Markdown-body backfill
scripts/sentinel/report_sentinel.py filesystem-event report indexer
scripts/meetings/build_offsite_report.py approved offsite operational report renderer
scripts/meetings/build_data_report.py offsite data-validation report renderer
scripts/integrations/openai_image.py gpt-image-2 wrapper used by HTML v2
api/src/routers/reports.py report API, search, and index self-heal
api/src/routers/report_collections.py collections API
api/src/routers/shared_reports.py report/collection share routes and interactions
web/src/routes/reports/ report library, search, viewer, and collections UI
.claude/skills/document-flow/SKILL.md shipping-flow documentation canvas workflow
.claude/skills/engineering-report/SKILL.md engineering contribution report workflow
.claude/skills/wbr/SKILL.md Weekly Business Review workflow
.claude/skills/offsite-report/SKILL.md offsite report workflow
.claude/skills/frontend-slides/SKILL.md interactive presentation workflow
.claude/skills/oneshot/SKILL.md high-stakes evidence workflow
data/reports/ report files, assets, DB, shares, collections, and history

Where to go next

  • Sentinel β€” filesystem events and autonomous indexing.
  • Model guidance β€” current model selection; generator constants drift.
  • Research and Deliberation β€” common report-content producers.
  • Search β€” Vita's broader long-term-memory search, distinct from report retrieval.