Skip to content

refactor(daily-prompt): versioned daily report prompt templates (prerequisite for #423 enrichment) #450

@eanzhao

Description

@eanzhao

Architectural follow-up surfaced in docs/audit-scorecard/2026-04-27-daily-pipeline-architecture-review.md §C3. Prerequisite for #423.

Symptom

The daily report prompt template lives in code as a static StringBuilder (AgentBuilderTemplates.cs:48-64). At agent creation time the rendered prompt string is frozen into SkillRunnerState.SkillContent. Implications:

  • Updating the prompt requires a deploy.
  • After deploy, existing agents still use the old prompt (frozen in their state).
  • There is no way to roll out a new prompt to existing agents without /delete-agent + recreate.
  • There is no concept of "prompt version" anywhere — /agent-status cannot tell you which prompt your daily is running on.

Why now

issue #423 plans to substantially enrich the daily report (more sections, repo-aware queries, structured envelope). That work is gated on this: shipping a new prompt today silently leaves all existing daily-report agents on the old prompt indefinitely. The richer prompt also won't fit "fix the string in code, redeploy" cleanly.

Architectural violations

  • CLAUDE.md "渐进演进: 开发期可用本地/内存实现,但生产语义必须能无缝迁移到分布式与持久化". The prompt is a fact (versioned, queryable, owned), not a code constant.
  • CLAUDE.md "事实源唯一". The same prompt content is currently in code AND mirrored into N agent states.

Proposed direction

Introduce a DailyReportTemplateCatalog — actor-owned or document-store-backed:

  • Each template version has template_id, version, title, system_prompt, execution_prompt_template, created_at, description.
  • Subscription actor (post-#refactor-split-skill-runner) stores template_id + template_version instead of the rendered skill_content string.
  • Run actor (post-split) resolves template_id + template_version → fetches current rendered prompt at run start.
  • Two run modes:
    • Pinned: subscription explicitly pinned to a version; new versions don't affect it.
    • Floating: subscription tracks "latest" version of a template id; new template version applies on next run.
  • Defaults are floating; user can pin via a future /daily template_version=N flag.

Acceptance

  • No skill_content string in subscription actor state.
  • /agent-status shows current template id + version.
  • Updating the catalog with a new version applies to floating subscriptions on next run, leaves pinned subscriptions alone.
  • Migration: existing SkillRunnerState.SkillContent strings are mapped to a synthetic template_version=0 so old agents keep behaving identically until an explicit upgrade.
  • Test: ship a new template version → existing floating subscription's next run uses it; pinned subscription stays on old.

Dependencies

  • Best after / alongside #refactor-split-skill-runner — that's where the subscription actor lives.

Related

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions