Digital Publisher Implementation PlanElena Daehnhardt |
Image credit: Illustration created with Midjourney, prompt by the author.
Image prompt“An illustration representing cloud computing” |
Digital Publisher Implementation Plan
Date: 2026-03-27
Repository (local dev): /Users/elena/git/edaehn.github.io
1) Objective
Implement the AI publishing agency in a low-risk sequence with:
- Tuesday and Friday scheduled automation via GitHub Actions.
- OpenAI SDK/API-based content operations using
OPENAI_API_KEY. - Git branch + draft PR review gates for all mutating work.
- Telegram notifications in MVP, Telegram inbound polling in Phase 2.
- GitHub Pages kept strictly as publishing layer only.
- File-based operational memory (CSV/JSON/Markdown), no database.
2) MVP vs Phase 2 Cut Line
MVP (first deploy)
.github/workflows/agency-run.yml- Tuesday flow (
agents/tuesday_improve_drafts.py) - Friday flow (
agents/friday_ai_signals.py) - Validator (
agents/validator.py) - Git branch + draft PR flow (
agents/git_ops.py) - Telegram notifications only (
agents/telegram_notify.py) - Logs/reports/state in
automation/ - Policy loading from
AGENTS.md+automation/policies/
Phase 2 (after MVP stability)
- Telegram poller (
agents/telegram_poller.py+telegram-poller.yml) - GitHub Issues task queue for
/ask - Issue worker (
issue-worker.yml) - On-demand router (
agents/on_demand_router.py) - Richer target resolution and advanced fact-check/ranking flows
3) AGENTS.md Governance
AGENTS.mdis the editorial source of truth.automation/policies/*.mdare derived runtime files.- Validators enforce objective rules that originate in
AGENTS.md. - If
AGENTS.mdconflicts with a derived policy,AGENTS.mdwins. - Editorial rule changes must be made in
AGENTS.mdfirst, then propagated.
4) Path Assumptions
- Local path (
/Users/elena/git/edaehn.github.io) is informational only. - CI/runtime path resolution must use
GITHUB_WORKSPACEwhen present. - No production script may depend on user-specific absolute paths.
5) Phase Order (Risk-Reduced)
Phase 0: Foundation/bootstrap
- Create core directories:
agents,automation,scripts. - Add
agency-run.yml, scheduler state, and dependency manifest. - Copy/adapt starter scripts from
_starter_agency_files.
Deliverable: dry-run pipeline executes without branch/PR side effects.
Phase 1: Shared runtime + policy loading
- Implement
agents/common.pyutilities. - Add
automation/policies/and policy loading fromAGENTS.md. - Delay
automation/prompts/until needed.
Deliverable: all agents share consistent parsing/logging/policy loading.
Phase 2: Validator hardening (before content generation)
- Front matter checks.
- Tag validity checks against
tag/*.md. - Weekly source freshness checks.
- Python code block compilation checks.
- Safe-scope and out-of-scope change checks.
Deliverable: guardrails in place before automated edits scale.
Phase 3: Tuesday flow
- Find unpublished non-Weekly candidates.
- Improve 1-2 posts.
- Write report/logs and run validation.
Deliverable: Tuesday editorial automation with validator enforcement.
Phase 4: Friday flow
- Build Weekly draft from fresh source set.
- Enforce Friday stop conditions.
- Write source tracking + validation report.
Deliverable: one Weekly draft in ready_for_review state.
Phase 5: Git ops / PR lifecycle
- Create/update task branch.
- Commit scoped changes.
- Push and create/update draft PR.
Deliverable: reviewable PR output for every mutating run.
Phase 6: Telegram notifications
- Send status summaries and failure notices.
- Never block editorial success due to notification failure.
Deliverable: phone-visible run summaries.
Phase 7: Telegram polling + issue queue
- Implement Telegram
getUpdatespoller. - Convert commands into labeled issues.
- Maintain monotonic
last_update_idstate.
Deliverable: inbound Telegram request intake without extra service.
Phase 8: On-demand router + issue worker
- Trigger on issue events.
- Resolve target deterministically.
- Execute scoped task branch flow + validation + PR updates.
Deliverable: safe /ask execution via GitHub Issues.
Phase 9: Rollout and hardening
- Activate schedules and concurrency controls.
- Run duplicate/rerun tests.
- Finalize runbooks and failure recovery paths.
Deliverable: stable operational agency.
6) Idempotency Rules
- A Telegram
update_idmay be converted to at most one issue. - A given issue may have at most one active task branch unless explicitly rerun.
- Worker checks existing PRs before creating new PRs.
- Tuesday/Friday reruns must not duplicate same-day outputs.
- Friday must check if today’s Weekly draft already exists before creating another.
7) Concurrency and Write Safety
- Use
concurrencygroups for Tuesday/Friday runs. - Use one poller concurrency group to prevent dual polling.
- Use per-issue concurrency groups for issue workers.
- Scheduled workflows must not overlap with themselves.
- Mutating jobs re-read state and working tree before commit.
8) Target Resolution Specification
When a task references a post, resolve in this order:
- exact filename match
- exact slug match
- exact title match
- case-insensitive title substring
- latest matching unpublished draft
- if ambiguity remains: set
needs_human_input
9) Safe Write Scope
- Tuesday may modify only selected
_postsdrafts and relatedautomationlogs/reports/state. - Friday may modify only one Weekly draft, source tracking files, and related
automationfiles. - On-demand tasks may modify only task-related files.
- No workflow may mass-edit unrelated historical posts.
- Out-of-scope file mutations must fail validation.
10) MVP Image Policy
- MVP Friday runs may use safe/default image metadata for draft PRs.
- Full Flux image generation is Phase 2 unless CI reliability is proven.
- Validator distinguishes draft warnings from publish-blocking image errors.
11) Publishability Levels
Use these normalized outcomes:
draft_createdvalidation_failedready_for_reviewneeds_human_inputpublishable
Tuesday/Friday automation should normally end at ready_for_review.
12) Friday Stop Conditions
Friday workflow must stop and mark needs_human_input if:
- fewer than 4 valid fresh sources remain
- source set is mostly paywalled
- major claims cannot be supported by open sources
- source freshness dates cannot be confirmed
- title selection succeeds but source support is weak
13) Issue Body Contract
Every automation-created issue must include:
- request source
- original Telegram command
- normalized task type
- target selector
- Telegram update ID (if applicable)
- creation timestamp
- current status
14) Failure Recovery
- If worker fails after branch creation and before PR creation: keep branch and post failure report.
- If PR creation fails: report branch in issue comment + Telegram summary.
- If validation fails: commit reports and keep PR draft.
- If Telegram notification fails: do not fail editorial execution.
- If CSV/state write fails: mark blocked and stop further mutation.
15) Model Routing and Budget Controls
- Use lowest-cost acceptable model for classification/ranking/metadata.
- Use stronger model only for difficult rewrites/fact-check/polish.
- Log tokens and estimated cost per run (
agent_runs.csv). - Support
LOW_COST_MODE=true.
16) Dry-Run Contract
In dry-run mode, workflows may:
- scan repository files
- generate reports
- write temporary runner-local artifacts
In dry-run mode, workflows must not:
- push branches
- open PRs
- open issues
- mutate scheduler/poller state
- send Telegram notifications unless explicitly test-enabled
17) Acceptance Criteria
- Tuesday updates at most 1-2 unpublished non-Weekly drafts per run.
- Friday creates at most one Weekly draft per date.
- Validator blocks missing front matter, invalid tags, stale sources, and broken Python blocks.
- All mutating runs create task branches and draft PRs; no direct
mainwrites. - Telegram notifications include task status and branch/PR references.
- Logs/reports/state are written for every run.
- Poller never reprocesses old updates (
last_update_idmonotonic). - Each valid
/askyields exactly one labeled issue. - GitHub Pages remains publish-only and unchanged as automation runtime.
- Reruns do not create duplicate issues, branches, or Weekly drafts unless explicitly requested.
18) Planned New Directories and Files
All paths are absolute and grouped by deployment stage.
MVP directories
/Users/elena/git/edaehn.github.io/agents/Users/elena/git/edaehn.github.io/automation/Users/elena/git/edaehn.github.io/automation/logs/Users/elena/git/edaehn.github.io/automation/reports/Users/elena/git/edaehn.github.io/automation/state/Users/elena/git/edaehn.github.io/automation/policies/Users/elena/git/edaehn.github.io/scripts
MVP files
/Users/elena/git/edaehn.github.io/.github/workflows/agency-run.yml/Users/elena/git/edaehn.github.io/requirements.txt/Users/elena/git/edaehn.github.io/agents/__init__.py/Users/elena/git/edaehn.github.io/agents/common.py/Users/elena/git/edaehn.github.io/agents/intake.py/Users/elena/git/edaehn.github.io/agents/tuesday_improve_drafts.py/Users/elena/git/edaehn.github.io/agents/friday_ai_signals.py/Users/elena/git/edaehn.github.io/agents/validator.py/Users/elena/git/edaehn.github.io/agents/git_ops.py/Users/elena/git/edaehn.github.io/agents/telegram_notify.py/Users/elena/git/edaehn.github.io/scripts/update_logs.py/Users/elena/git/edaehn.github.io/automation/state/scheduler.json/Users/elena/git/edaehn.github.io/automation/logs/tasks.csv/Users/elena/git/edaehn.github.io/automation/logs/agent_runs.csv/Users/elena/git/edaehn.github.io/automation/logs/approvals.csv/Users/elena/git/edaehn.github.io/automation/logs/sources.csv/Users/elena/git/edaehn.github.io/automation/reports/README.md/Users/elena/git/edaehn.github.io/automation/policies/global_policy.md/Users/elena/git/edaehn.github.io/automation/policies/technical_post_policy.md/Users/elena/git/edaehn.github.io/automation/policies/weekly_signals_policy.md/Users/elena/git/edaehn.github.io/automation/policies/series_policy.md/Users/elena/git/edaehn.github.io/automation/policies/media_policy.md/Users/elena/git/edaehn.github.io/automation/policies/validation_policy.md
Phase 2 files
/Users/elena/git/edaehn.github.io/.github/workflows/telegram-poller.yml/Users/elena/git/edaehn.github.io/.github/workflows/issue-worker.yml/Users/elena/git/edaehn.github.io/agents/telegram_poller.py/Users/elena/git/edaehn.github.io/agents/on_demand_router.py/Users/elena/git/edaehn.github.io/automation/state/telegram_poller.json