Skip to content

Persist marketing-cycle state in .marketing/ (operator-curated) #89

Description

@stempeck

Investigation Notes

Before this change the repo had no durable marketing capability. Cycle state — the runbook, the announced-features ledger, the cycle records — existed only as git-ignored files on one workstation, and the marketing-cycle formula existed only in that workstation's local store. Factories run in disposable containers: anything uncommitted dies with the container, so the ledger (the cross-run memory that tells a cycle what has already been announced) could not survive between runs, and no other clone or container could run a marketing cycle at all. An earlier attempt to land this content reached main without review and was force-rewound; this issue and PR #90 are the properly gated re-land.

PR #90 introduces the complete capability: committed cycle state under .marketing/, the generic (repo-agnostic) marketing-cycle formula in both its runtime and embed locations, and the generated first-class agent.

Affected Layers & Files

Cycle state (.marketing/ — committed, following the .designs/ pattern)

  • approach.md — the operator-signed runbook: operator identity, channels with homepage allowlist, voice profile, claim-verification map, Standing Assets declarations, explicit Privacy-Decision: COMMITTED, and the sign-off line
  • announced-ledger.md — cross-run record of what has been announced, where, and when; also carries the untold-features backlog
  • cycle-1-audit.md, cycle-1-log.md, cycle-1-story.md, cycle-1-report.md, cycle-1-publish-checklist.md — cycle-1 records (log and story are labeled RECONSTRUCTED: the checks ran live 2026-07-11/12; the files were assembled afterward in the formula's artifact format)
  • cycle-1-linkedin.md, cycle-1-medium.md — the two published drafts (content already public)
  • architecture-diagram.png, social-preview.png, social-preview.svg — declared standing assets

Formula (declarative workflow, 23 steps)

  • .agentfactory/store/formulas/marketing-cycle.formula.toml — runtime copy
  • internal/cmd/install_formulas/marketing-cycle.formula.toml — embed copy (ships in the af binary)

Structure: first-run bootstrap that generates the runbook by operator interview and holds for sign-off; four human gates (story approval, draft approval, Tier A merge, publish); five evidence-logged checklist gates that write VERDICT lines to the cycle log; an artifact-manifest gate in cleanup that fails any file tracing to no formula step and no Standing Assets declaration; operator communication via GitHub issues and PR comments (agent mail stays agent-to-agent); data-not-directive guards on untrusted input; homepage-URL validation against the runbook's allowlist.

Agent (first-class, generated by af formula agent-gen from formula v2)

  • internal/templates/roles/marketing-cycle.md.tmpl — embedded role template, so the agent identity survives context compression
  • .agentfactory/agents/marketing-cycle/CLAUDE.md — workspace persona
  • .agentfactory/agents/marketing-cycle/.claude/settings.json — hook configuration
  • .agentfactory/agents.json — registration

Additional Context

  • The formula is generic by design: everything repo- or operator-specific (voice, channels, target phrases, verification paths, allowlists) lives in the runbook, which a first run generates by interview. This repo's runbook is the first instance; a different repo bootstraps its own.
  • Privacy is an explicit operator decision recorded in the runbook, then enforced against git state — never inferred from ambient ignore rules. Gotcha for future readers: git check-ignore silently skips already-tracked files unless --no-index is used; the formula's enforcement accounts for this.
  • The plan-era drafts that will never ship (Show HN, Reddit, awesome-list submission plans) are deliberately absent per operator decision — "didn't happen and aren't going to happen." The manifest gate flags any such unaccounted file in future cycles.
  • The runbook instructs agents that only the operator merges PRs; the formula's delivery step opens the PR and holds.

Acceptance Criteria

  • After merge, a fresh clone or newly built container contains the runbook, ledger, and cycle-1 records; a subsequent cycle can determine what has already been announced with no state from the original workstation.
  • A factory built from this repo can discover and instantiate the marketing-cycle formula, and the generated agent's identity survives context compression.
  • A cycle run against a repo with no runbook stops at bootstrap and waits for operator sign-off rather than proceeding.
  • No content under the operator's name is ever published by the agent; every such artifact waits at a human gate, and post-merge history shows operator merges only.
  • Every file in .marketing/ is accounted for: it traces to a formula artifact or a Standing Assets declaration.
  • Template-regen CI passes with the committed role template (template and formula stay in sync).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions