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 supportstopic_id,workstream_id,task_id,event_type, andsincefilters, 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
Domainsas a top-level page indashboard/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 to1h. - Optional exact-window inputs:
sinceanduntil; when supplied, they should override or constrainrangepredictably. - Accept simple duration values such as
15m,1h,6h, and1d; 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.mdor20260522T110000Z--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_slugto the domain id, associated topic ids, active repos, workstreams, and tasks. - Collect
ProgressEventrows 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 importsmarkitect_tool.template.render_templatewhen available. - Keep a subprocess fallback to
markitect template renderfor 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, andattention_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-scopeto generate a report.GET /domains/{slug}/recently-on-scopeto 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/markdownwhere 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.jssoDomainscan expose a child page without hiding the existing/domainsoverview. - 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_atdescending. - Render or preview Markdown safely in the dashboard, or link to the raw
text/markdownendpoint 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.mdor 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
.gitignoreentry while keeping the template tracked. - Verify with
python3 -m pytestand dashboard build/test commands already used by this repo. - After the workplan file is synced, run
make fix-consistency REPO=state-hubfrom~/state-hub.
Done when tests pass, docs explain the operator workflow, and generated reports have a clear retention and Git-tracking policy.