Files
state-hub/workplans/STATE-WP-0044-recently-on-scope-digest.md

9.9 KiB

id, type, title, domain, repo, status, owner, topic_slug, created, updated, state_hub_workstream_id
id type title domain repo status owner topic_slug created updated state_hub_workstream_id
STATE-WP-0044 workplan RecentlyOnScope Domain Digest custodian state-hub finished codex custodian 2026-05-22 2026-05-22 ffefe4b2-e162-44c7-8658-5d8d9e27ad9c

RecentlyOnScope Domain Digest

Summary

Add a file-backed RecentlyOnScope digest that answers: "What happened in this domain recently?" The digest is generated as Markdown from a deterministic Markdown template, with a time range parameter defaulting to one hour. Generated reports are collected in a State Hub report directory and are browsable from a new Domains navigation subentry.

This should reuse MarkiTect template-rendering capabilities instead of adding a new ad hoc templating language. The local tool surface currently provides markitect template render and the Python API markitect_tool.template.render_template.

Current Findings

  • Domains are first-class records with topics and repos. Domain-scoped work can be resolved through Domain -> Topic -> Workstream -> Task.
  • GET /progress/ already supports topic_id, workstream_id, task_id, event_type, and since filters, making progress events the first digest source.
  • Decisions, workstreams, and tasks have timestamp fields, but their existing list endpoints do not expose a domain/time-window digest view.
  • Agent messages are not currently domain-linked. They should only enter the first digest when they can be tied to a topic, workstream, task, or explicit domain reference.
  • The dashboard currently exposes Domains as a top-level page in dashboard/observablehq.config.js. A subentry will require turning it into a collapsible navigation group or adding a nested Domains section.
  • No State Hub report directory exists yet. The work should create a clear generated-artifact location, proposed as reports/recently-on-scope/ inside this repo or the configured runtime data directory.

Out of Scope

  • LLM summarization of the digest. This work is deterministic collection and Markdown rendering.
  • Scheduled/background generation. This work provides on-demand generation and browsing hooks only.
  • Replacing the existing progress, task, decision, or workstream APIs.
  • Backfilling historic reports before the feature exists.

T01 - Define Digest Contract and Report Layout

id: STATE-WP-0044-T01
status: done
priority: high
state_hub_task_id: "0b8d0211-1d66-4808-b078-2d7c23af886a"

Define the input, output, and file layout for a RecentlyOnScope digest before implementation.

Implementation notes:

  • Required input: domain_slug.
  • Optional input: range, defaulting to 1h.
  • Optional exact-window inputs: since and until; when supplied, they should override or constrain range predictably.
  • Accept simple duration values such as 15m, 1h, 6h, and 1d; reject ambiguous values with a 422 response or CLI error.
  • Normalize all comparisons and generated filenames to UTC.
  • Store the tracked template at templates/recently-on-scope/domain-digest.md.
  • Store generated reports under a configurable report root, defaulting to reports/recently-on-scope/<domain_slug>/.
  • Name reports with enough information to sort and de-duplicate, for example 20260522T120000Z--1h.md or 20260522T110000Z--20260522T120000Z.md.
  • Include frontmatter in each generated Markdown report with domain_slug, range, since, until, generated_at, template_version, and source counts.

Done when the report contract is documented and has tests for duration parsing, default range behavior, and output path generation.

T02 - Build Domain Activity Collector

id: STATE-WP-0044-T02
status: done
priority: high
state_hub_task_id: "4d18fc40-dd28-417f-a2bf-538165eaa1e7"

Create a domain-scoped collector that turns recent State Hub records into a stable data object for template rendering.

Implementation notes:

  • Add a focused service module, for example api/services/recently_on_scope.py.
  • Resolve domain_slug to the domain id, associated topic ids, active repos, workstreams, and tasks.
  • Collect ProgressEvent rows for the domain topic ids and workstream/task ids in the requested time window.
  • Collect decisions created, updated, or resolved in the time window for domain topics and workstreams.
  • Collect workstreams and tasks updated in the time window, including status changes where that can be inferred from current records or progress events.
  • Include open human-intervention items in a separate "still needs attention" section when they belong to the domain, even if they were created before the requested window.
  • Keep output deterministic: sort by timestamp descending within sections, and include stable ids/links where available.
  • Do not infer domain ownership for messages unless a message is explicitly linked to a domain, topic, workstream, task, or digest-generation request.

Done when the collector returns a deterministic plain-Python data structure covering progress, decisions, workstreams, tasks, repos, and attention items for one domain and time window.

T03 - Reuse MarkiTect for Markdown Rendering

id: STATE-WP-0044-T03
status: done
priority: high
state_hub_task_id: "b3c5a238-3559-442b-a5ac-6f9aae802bac"

Render the digest with MarkiTect rather than custom string substitution.

Implementation notes:

  • Add a thin adapter, for example api/services/markitect_templates.py, that imports markitect_tool.template.render_template when available.
  • Keep a subprocess fallback to markitect template render for environments where the CLI is installed but the Python package is not importable.
  • Fail clearly if neither MarkiTect path is available; do not silently switch to a new template syntax.
  • Validate the template before generation by checking required variables.
  • Define a template data contract with keys such as domain, window, generated_at, progress_events, decisions, workstreams, tasks, repos, and attention_items.
  • Keep the template Markdown readable on its own, with no dashboard-specific markup.
  • Persist the rendered Markdown atomically so partial reports are not listed by the dashboard.

Done when a report can be rendered from the template using MarkiTect in tests and written to the configured report directory.

T04 - Provide Generation and Listing Mechanisms

id: STATE-WP-0044-T04
status: done
priority: high
state_hub_task_id: "e54ddc1e-75a5-44e5-b452-d8db58cce901"

Expose a practical mechanism to generate, list, and read RecentlyOnScope reports.

Implementation notes:

  • Add an API route group under Domains, for example:
    • POST /domains/{slug}/recently-on-scope to generate a report.
    • GET /domains/{slug}/recently-on-scope to list generated reports.
    • GET /domains/{slug}/recently-on-scope/{report_id} to return Markdown.
  • Return report metadata from generation and list calls: id, domain, range, since, until, generated_at, path, and source counts.
  • Return Markdown with text/markdown where appropriate.
  • Add a CLI script or make target for operator use, for example python -m scripts.recently_on_scope --domain custodian --range 1h.
  • Make the report root configurable with an environment variable such as STATE_HUB_REPORT_DIR, while preserving the repo-local default.
  • Avoid requiring dashboard access for generation; the CLI/API should be usable by agents and operators.

Done when operators can generate a digest from the command line or API, list existing reports, and read the Markdown contents.

T05 - Add Domains Navigation and Dashboard View

id: STATE-WP-0044-T05
status: done
priority: medium
state_hub_task_id: "dedad1d0-4afd-490a-ab59-a2ad348de5d2"

Make the reports accessible from a subentry under Domains in the State Hub dashboard navigation.

Implementation notes:

  • Update dashboard/observablehq.config.js so Domains can expose a child page without hiding the existing /domains overview.
  • Add a page such as dashboard/src/domains/recently-on-scope.md.
  • Provide domain selection, a time-range control defaulting to 1h, and a generate action backed by the new API.
  • Show the generated report list grouped by domain and sorted by generated_at descending.
  • Render or preview Markdown safely in the dashboard, or link to the raw text/markdown endpoint when full rendering is out of scope for the first pass.
  • Keep the view operational and compact: no landing page, no marketing copy, and no generated-output text that overlaps on small screens.
  • Add reference docs at dashboard/src/docs/domains.md or a dedicated docs page explaining where reports are stored and what the range parameter means.

Done when the dashboard navigation has a Domains subentry for RecentlyOnScope, reports can be generated/browsed from it, and raw Markdown is accessible for each entry.

T06 - Verification, Docs, and Operational Notes

id: STATE-WP-0044-T06
status: done
priority: medium
state_hub_task_id: "cecfb226-435b-429e-89fc-0da743a229ce"

Cover the feature with focused tests and operator documentation.

Implementation notes:

  • Add unit tests for duration parsing, collector filtering, MarkiTect adapter behavior, report naming, and report listing.
  • Add router tests for generation, list, missing domain, invalid range, and missing MarkiTect failure modes.
  • Add dashboard data/API smoke tests where existing dashboard test patterns make this practical.
  • Document the report directory, retention expectations, and whether generated reports are committed or treated as runtime artifacts.
  • If generated reports should stay out of Git, add a targeted .gitignore entry while keeping the template tracked.
  • Verify with python3 -m pytest and dashboard build/test commands already used by this repo.
  • After the workplan file is synced, run make fix-consistency REPO=state-hub from ~/state-hub.

Done when tests pass, docs explain the operator workflow, and generated reports have a clear retention and Git-tracking policy.