opdev / opdev/agentic-status-report

M5: Synthesizer — skill invocation, audit chain, Slack delivery

Open
#8 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kind/feature
Dominant language
Python
Stars
0
Forks
2
Avg merge
7d 51m
Merged PRs (30d)
8

Description

Summary

Implement M5: end-to-end management report synthesis from confirmed ledger entries — skill invocation, audit chain persistence, and Slack channel delivery.

Design reference: docs/DESIGN.md §5.4 (Synthesizer), §7.3–7.4 (contracts), §8 (Skills integration)

Current state (partial implementation)

Component Status
skills/weekly-status-synthesizer/SKILL.md Exists — rules ported from weekly_status-main/.claude/commands/format-status.md
src/status/skills/synthesizer.py Stub — build_synthesis_input() + run_synthesizer() with dry-run fallback
src/status/cli.py status report Exists — --dry-run defaults True; writes markdown to stdout or -o file
report_run / report_entry tables Schema exists in models.py + Alembic — not written to yet
Slack report delivery Not implemented
Skill publish status skills publish --skill synthesizer works if SYNTHESIZER_SKILL_ID unset (creates new)
Known bugs to fix in M5

In src/status/skills/synthesizer.py:

  • display_name=entry.person_id — should use Person.display_name from DB join
  • flags=[] hardcoded — should include unacknowledged flag rows for the week
  • No persistence to report_run / report_entry after skill returns

Tasks

1. Publish synthesizer skill
status skills publish --skill synthesizer
# Set SYNTHESIZER_SKILL_ID and pin SYNTHESIZER_SKILL_VERSION in .env / OpenShift Secret

Validate against fixtures built from confirmed ledger rows (create fixtures/synthesis-input-*.json from real confirmed data — scrub PII, gitignore if needed).

2. Complete build_synthesis_input()
  • Join Person for display_name
  • Load unacknowledged flags: Flag where week_ending matches and acknowledged = false
  • Include all participation rows for the week (confirmed, expired, sent, send_failed, on_leave)
  • Only include status_entry where is_current AND confirmed_at IS NOT NULL

Repo helpers exist in src/status/db/repo.py:

  • get_confirmed_entries_for_week
  • get_participation_for_week
3. Persist audit chain

After successful skill invocation, write:

report_run:

  • week_ending, prompt_version, model, generated_at
  • output_uri — optional path or object store URI if saving markdown file
  • delivered_at — set when posted to Slack

report_entry:

  • One row per cited entry: (run_id, entry_id, section) where section comes from synthesizer metadata if available

New module suggested: src/status/db/report.py

def persist_report_run(session, week_ending, output: SynthesisOutput, *, model, prompt_version) -> ReportRun:
    ...
4. Wire status report CLI
  • Change default --dry-run to False when SYNTHESIZER_SKILL_ID is set (keep --dry-run flag for testing)
  • Add --deliver flag to post markdown to REPORT_CHANNEL_ID via Slack Web API
  • Add --persist (default true) to write report_run rows
5. Slack delivery

Post synthesized markdown to private channel (REPORT_CHANNEL_ID):

  • Use slack_sdk.WebClient.chat_postMessage with mrkdwn text
  • Long reports may need splitting (Slack 40k char limit) — split on section headers if needed
  • Set report_run.delivered_at on success

Optional: attach as snippet or upload file if formatting breaks in chat.

6. Synthesis validation

SynthesisOutput schema in src/status/skills/schemas.py — ensure Pydantic validates:

  • markdown non-empty
  • week_ending matches input
  • Metadata fields: sections_used, entries_cited, non_responders, asks

On validation failure: do not persist partial report; surface error to CLI.

7. Tests
  • tests/test_synthesizer.py — build input from fixture DB session (SQLite or mocked)
  • Test dry-run path unchanged
  • Test report_run + report_entry rows created on persist
  • Golden test: synthesis input JSON shape, not markdown prose

Synthesis rules (skill must enforce)

From design doc / SKILL.md:

  • Sections: Partner Enablement, Certification / CI, Mindshare
  • Format: * **Name** - description with links on noun phrases
  • No raw Jira IDs in visible text
  • Alphabetical within sections
  • Non-responders explicit
  • Every ask from ledger appears in report
  • Organize by epic/project, not by person

Acceptance criteria

  • status report --week 2026-08-14 invokes skill when configured (not dry-run)
  • report_run and report_entry populated with audit chain
  • --deliver posts to REPORT_CHANNEL_ID
  • Confirmed entries only; expired participation reflected in output metadata
  • Tests pass: pytest tests/test_synthesizer.py

Branch / PR

  • Branch: feat/m5-synthesizer
  • Base: main
  • PR title: feat(synthesizer): management report generation and delivery (M5)

Depends on

  • M0–M3 on main (ledger + confirm flow)
  • At least one week of confirmed entries in Postgres for integration testing
  • M4 not strictly required but improves data quality before first real report

Out of scope (M6 / Phase 2)

  • Monday 09:00 auto-expire unconfirmed (participation.status = 'expired') — M6
  • CronJob lock-and-report
  • DOCX export / email (weekly_status-main commands)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with docs/DESIGN.md §5.4 and §7.3–7.4, then inspect src/status/skills/synthesizer.py, src/status/db/repo.py, models.py, and src/status/cli.py. Use tests/test_synthesizer.py and its fixture DB as the entry point; verify input filtering, validation, persistence, and Slack delivery paths. Done means pytest passes and the listed status report acceptance checks are met.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, python
Domain
backend, cli, databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.