Next steps

Updated Jul 14, 2026
  • Address CI stability
  • Begin database migration planning

Generated at 2024-07-14 12:00 UTC by gpt-5.1-thinking | Window: 2024-07-07 to 2024-07-14 | Report ID: abc-123 ```

Sections with no content (empty highlights, risks, or next steps) are omitted entirely. The renderer reads from the structured machine_summary field on the Gold layer report, so the Markdown content always matches the database.

Report sink configuration

Variable Default Description
GHILLIE_REPORT_SINK_PATH (unset) Filesystem directory for Markdown report output. When unset, no files are written.

Rendering and sink usage

To render a report as Markdown without writing to disk:

from ghillie.reporting import render_report_markdown

md = render_report_markdown(report, owner="acme", name="widget")

To use the filesystem sink directly:

from pathlib import Path

from ghillie.reporting import (
    FilesystemReportSink,
    ReportMetadata,
    render_report_markdown,
)

sink = FilesystemReportSink(Path("/var/lib/ghillie/reports"))
metadata = ReportMetadata(
    owner="acme",
    name="widget",
    report_id="abc-123",
    window_end="2024-07-14",
)
markdown = render_report_markdown(report, owner="acme", name="widget")
await sink.write_report(markdown, metadata=metadata)

The ReportSink protocol supports future storage backends (for example, S3 or a dedicated Git repository) without changes to the reporting service.

Integration with the reporting service (scheduled)

When a FilesystemReportSink is provided, the ReportingService automatically renders and writes Markdown after each report is persisted to the Gold layer. The Dramatiq actors (generate_report_job, generate_reports_for_estate_job) create the sink automatically when GHILLIE_REPORT_SINK_PATH is set.

from pathlib import Path

from ghillie.reporting import (
    FilesystemReportSink,
    ReportingConfig,
    ReportingService,
    ReportingServiceDependencies,
)

config = ReportingConfig.from_env()
sink = FilesystemReportSink(Path("/var/lib/ghillie/reports"))

dependencies = ReportingServiceDependencies(
    session_factory=session_factory,
    evidence_service=evidence_service,
    status_model=status_model,
)
service = ReportingService(dependencies, config=config, report_sink=sink)

# Reports are now rendered and stored as Markdown automatically
report = await service.run_for_repository(repository_id)