All notable changes to this project are documented here. Format based on Keep a Changelog; versioning follows Semantic Versioning.
Autonomous SaaS marketing loop across social networks and dev communities (epic #46, issues #47-#60):
- Channel registry (
lib/channels/registry.ts, issue #49): typed registry of 8 social platforms and 41 developer/community portals across 10 languages (id, audience, link policy, tone, publish method, compliance notes, frequency limits). - Integration broker (
lib/integrations/broker.ts, issue #52): resolves publish/schedule/fetch_metrics/draft_ad/comment_monitor/evidence_capture to the safest adapter (api/mcp/browser/computer-use/manual) per channel, with dry-run simulation and structured failure logging. - Community compliance gate (
lib/compliance/community.ts, issue #56): anti-spam/etiquette audit with apass | fail | needs_reviewthree-state result — checks that cannot be evaluated (unreadable channel rules, corrupted post history) hold for human review instead of silently passing. - Accrual-based analytics scoring (
lib/analytics/score.ts, issue #54): ranks amplification candidates by the delta between successive polls (normalized per day), not a single cached snapshot, so slow-compounding threads aren't starved by yesterday's spike; flags implausible vanity-metric spikes as spam risk. - Strategy playbooks (
.specs/strategy/PLAYBOOKS.md, issue #50): per-channel launch playbook for the 10 priority international dev/community channels. - Content templates (
.specs/pieces/templates/*.md,lib/content/templates.ts, issue #57): five evidence-aware templates (dev article, social derivative, video script, Reddit/forum answer, launch thread) that mark missing evidence explicitly and render English-first before any localized adaptation. - Browser/computer-use lane (
lib/automation/browser-lane.ts, issue #51): governed evidence capture with redaction and failure-mode classification (login_required, captcha, two_factor, platform_rejection, policy_block); DRY_RUN-gated, live actions require explicit human approval. - Paid-growth budget guardrails (
lib/promotion/budget-guardrail.ts, issue #55): max daily spend, max CPA/CPL, max experiment duration, and stop-loss enforcement wired into the existing ads-draft flow, plus an append-only promotion-attempt audit log with hypothesis. - Campaign CLI (
lib/cli/campaign.ts,lib/campaigns/campaign.ts, issue #53):marketing-engine campaign --brief <CAMPAIGN.md>plans a channel/language/format-tagged piece queue and enforces organic-before-paid by default;campaign review <id>summarizes winners/losers/spend. - Yool tuple-space board (
lib/yool/board.ts,.specs/architecture/YOOL-BOARD.md, issue #59): event-sourced tuple board across 13 tuple classes and 11 worker lanes; mandatory agent-manifest guardrails (cpu/disk/timeout quotas);WorkerGovernorbounds concurrency per lane. - Community reply loop (
lib/community/reply-loop.ts, issue #60): classifies incoming comments, assigns risk level, drafts evidence-honest replies for human review; never posts autonomously. - Root super-skill (
.skills/simplicio-loop-marketing/SKILL.md, issue #48): orchestrates the full discover→...→learn loop by capability. - Runtime-first ADR (
.specs/architecture/ADR-002-runtime-first.md, issue #47): confirms zero required dependency onsimplicio-sprint/simplicio-prompt. - E2E mock launch loop (
e2e/saas-launch-loop.spec.ts, issue #58): proves the full loop end-to-end against mocks, DRY_RUN throughout, never a live provider/platform call.
- Hardened release-readiness and handoff guidance: added
docs/release-readiness.mdwith a minimum readiness checklist, claims/evidence rules, and a handoff template; expandeddocs/architecture-map.md,docs/domain-map.md,docs/local-setup.md, anddocs/troubleshooting.mdwith clearer setup and troubleshooting detail; minorREADME.mdupdate.
- watcher-gate (N-Nest style): independent verification layer in the generate loop that re-checks caption pillar hashtags, script topic coverage, caption length constraints, placeholder leakage, and overpromise language before allowing draft→scheduled transition. Every output receives a
claims_tag:MEASURED,CANON, orUNVERIFIED. - claims-gate: enforce claims discipline at promote time — UNVERIFIED pieces blocked from ad creation. Watcher reports persisted under
data/gate/<piece-id>.json. .skills/watcher-gate/SKILL.md: skill manifest documenting gate rules, integration points, and DoD.- Piece frontmatter:
claims_tagandwatcher_report_pathoptional fields. Template defaults toclaims_tag: UNVERIFIED. - Manifest payload now includes
watcher_report_path. maybeMarkMeasuredsetsclaims_tag: MEASUREDwhen performance data confirms value.- Promote loop checks claims gate before creating ad drafts; blocked pieces logged to
data/learnings.md.
<!-- rtk-cli:start -->block inAGENTS.mdand.github/copilot-instructions.md(CLAUDE.md is a symlink to AGENTS.md) documenting optional RTK CLI usage for token-smart shell exploration (https://github.com/rtk-ai/rtk)..skills/rtk-cli/SKILL.mdskill manifest with plain→rtk mapping, trigger examples, and DoD.<!-- yool-tuple-hamt:start -->capability-addressing block citing yool/tuple/HAMT spec v0.2 with mandatory guardrails (cpu_quota_pct=60,disk_quota_mb=100,timeout_s=300) per Victor Genaro's review.
qa-tech-specsnow reads channel constraints from.specs/product/CHANNELS.md, probes assets withffprobe/identify, falls back to filename metadata when possible, and skips safely with install guidance when local probe tools are unavailable.- The generate loop now writes
qa-tech-specs.jsonper piece, blocks pieces that fail hard platform-spec checks before scheduling, and records the QA report path in the manifest for successful runs. - Wavespeed image and video providers now support real model selection, batch-oriented variant expansion with concurrency capped at 5, and mocked local coverage for image downloads plus WAN video polling.
- Compliance loading now honors
ACTIVE_CLIENT, reads additive client override rules from.specs/clients/<client>/COMPLIANCE.override.md, and writes warn lines to a weekly digest plus repeat-block alerts todata/learnings.md. - Blocking compliance reports now move local pieces to
review, persist the report indata/compliance-blocked/, and keep the pipeline metadata pointed at the canonicaldata/compliance/<piece>.jsonaudit trail. generatenow routes compliance through the shared loader instead of the old inline regex helper, and the repo ships a template.specs/clients/_template/COMPLIANCE.override.mdplus focused coverage for override loading, escalation, and review transitions.
marketing-engine syncnow pulls Notion calendar rows into the host workspace.marketing-engine/pieces/, rendering new piece files from.specs/pieces/piece-template.mdand recording the linkednotion_page_idplus the last synced remote fingerprint.- Notion sync conflicts now preserve the local piece file and append the remote snapshot as a comment block instead of overwriting the frontmatter or losing local edits.
generatenow back-syncs linked pieces to Notion when they advance toscheduled, andpromotemarks linked published pieces asmeasuredin both the local piece file and the Notion calendar..ralph/sync-calendar.shnow calls the realmarketing-engine synccommand, and the repo adds focused Notion sync coverage for creation, conflict handling, and status back-sync paths.
DeepSeekProvidernow picksdeepseek-chatforcaptionandtranslation, while reasoning-heavy tasks route throughdeepseek-reasoner.- DeepSeek pricing now resolves the correct model family in
lib/providers/cost.ts, with optional per-1k token env overrides for chat and reasoner tiers. - Added provider coverage that asserts the DeepSeek request shape, retry behavior, usage accounting, and model-specific cost calculation.
- Synchronized the package version metadata across
package.jsonandpackage-lock.json.
OllamaProvidernow normalizesOLLAMA_HOST, preserves the configuredOLLAMA_MODEL, and throws a descriptive unreachable-host error that points operators to start Ollama or change the host before the fallback chain moves on.- Added local adapter coverage that asserts the Ollama
/api/chatrequest payload and retry behavior when the local server is offline. - Synchronized the published package metadata version between
package.jsonandpackage-lock.json. - Added the missing scheduler helper parameter annotations in
lib/schedule/{linux,mac}.tsso the repo-wide typecheck can complete again.
marketing-engine schedulenow routes install, status, and uninstall through platform-aware launchd and cron backends, including macOS uninstall/status support and a Windows manual Task Scheduler warning instead of silent writes.- Scheduler preview mode now prints the exact launchd plist bodies or cron
lines that would be installed, and the Linux cadence now correctly renders
22:00and09:00as0 22 * * */0 9 * * *. - Added scheduler round-trip E2E coverage against temporary cron and launchd directories, plus updated setup guidance for the new CLI commands.
- Provider pricing and usage estimation now live in
lib/providers/cost.ts, keeping the editable pricing table andchar/4fallback heuristic in one shared module. - Real LLM adapters now emit a concrete retry attempt count, and
data/llm-usage.jsonlpersiststokens,cost_usd, and the finalattemptnumber from the provider call instead of logging only a router-level success marker. - Missing SDK usage payloads now warn once per provider/model pair while still producing cost estimates from the shared fallback token heuristic.
lib/pieces/frontmatter.tsnow enforceslocaleas a required frontmatter field, matching the documented piece template contract.lib/pieces/id.tsnow computes ISO weeks from UTC date parts, preventing timezone-dependent week rollover bugs inPIECE-YYYYWww-NNNids.lib/pieces/store.tsnow exportslist,read, andwritealiases in addition to the existing*Piece*helpers so the public API matches the issue contract more directly.
marketing-engine new-piece,status, andlogsnow operate against the host project's.marketing-engine/workspace instead of assuming runtime files live at the host root.new-piecenow renders from.specs/pieces/piece-template.md, prints the created file path directly, and scans existing weekly piece files so repeated CLI invocations do not reuse the samePIECE-YYYYWww-NNNid.statusandlogsnow return infra exit code2when the workspace has not been initialized yet, while still succeeding cleanly when the data directory exists but the usage log file is empty.
marketing-engine promotenow reads and writes its runtime artefacts from the host project's.marketing-engine/{data,pieces,outputs}workspace by default, matching the scaffolded project layout.- Winner drafts now honor
provider_override.adsfrom the source piece frontmatter, and the CLI summary output matches the documentedpromoted: N | losers: M | skipped: Kformat.
marketing-engine generatenow resolves the host project's.marketing-engine/{pieces,outputs,data}workspace by default instead of assuming runtime files live at the host root.lib/cli/generate.tsnow honors theMAX_ITERenvironment variable in addition to the existing--max-iterflag, and the E2E coverage exercises both the host-workspace defaults and the capped iteration flow.
e2e/provider-factories.spec.tsexercises the non-DRY_RUNfactory path so the suite proves the repo returns real provider adapters instead of production mocks.
- E2E coverage now mirrors the Sprint 0 acceptance language more closely:
e2e/cli-init.spec.tsande2e/cli-scan.spec.tssplit the host-project scaffold and scan coverage,e2e/generate-loop.spec.tsasserts structured usage-log tasks, ande2e/matrix.spec.tsproves that editing.specs/architecture/PROVIDERS.mdchanges routing without code edits. CONTRIBUTING.mdnow documents how to updateCHANGELOG.md, and the PR template links directly to the changelog checklist target.
lib/providers/matrix.tsparses.specs/architecture/PROVIDERS.mdas the single source of routing truth (ADR-001). Embedded defaults are used when the file is missing or malformed, with a stderr warning.lib/providers/policy.ts— shared retry/backoff/timeout helper (withRetry), per-provider pricing table andestimateCost/estimateTokenshelpers.lib/router.tsexposesrunWithFallback— wraps any provider call with the primary/fallback chain documented inPROVIDERS.mdand writes one structured line per attempt todata/llm-usage.jsonl(ok,fallback_used,attempt,latency_ms).lib/data/runs.tsandlib/data/manifest.tswrite the artefacts the AGENTS Definition of Done requires:data/runs.jsonlper piece run andoutputs/<client>/<date>/<piece-id>/manifest.jsonper piece.lib/pieces/{id,frontmatter,store}.ts— piece engine. ISO-8601 week-numbered IDs (PIECE-YYYYWww-NNN), zero-dependency YAML frontmatter parser, state machine (draft → scheduled → published → measured, side statereview).lib/cli/generate.ts— real generation loop that readspieces/, routes every task through the matrix + fallback chain, runs inline compliance, writes outputs/script/captions/compliance.json/manifest.json, transitions status, and appends todata/runs.jsonl.lib/cli/promote.ts— real promotion loop that classifiesdata/analytics.jsonl(top/bottom 20% by save rate, ≥100 impressions), writesads-draft.jsonfor winners, appendsdata/learnings.mdfor losers.lib/calendar/notion.ts— Notion calendar reader (pullCalendar,syncToLocal,pushStatus). DRY_RUN-safe.lib/publish/adaptlypost.ts— real AdaptlyPost wiring with retry/backoff; DRY_RUN still writesadaptlypost-draft.jsonlocally.lib/publish/meta-ads.ts— Meta Ads draft builder +data/promotions.jsonlwriter. Real Meta API call is a stub (calls into the meta-ads MCP layer when available).lib/analytics/{meta,tiktok,youtube}.ts— DRY_RUN keeps deterministic synthetic data; non-DRY paths call Graph / TikTok Business / YouTube Data APIs.lib/compliance/{generic,loader}.ts— executable cross-vertical audit, writesdata/compliance/<piece>.json, escalates blocks todata/compliance-blocked/, exposesdetectStreaksfor the alerts module.lib/skills/{humanizer,brand-voice}.ts— executable critic skills (regex pass- LLM secondary stub, voice-axis distance scoring).
lib/qa/tech-specs.ts— ffprobe/identify wrapper with filename fallback; per-platform validation againstCHANNELS.mdspecs.lib/observability/{cost,ab-report,failures}.ts— cost summary + HTML report, A/B per (task, provider) ROI table, failure-rate detector + webhook poster.lib/schedule/cron.ts— cron / launchd install / uninstall / status helpers with marker block isolation.- CLI gains:
new-piece,status,logs,cost,ab-report,alerts,sync,schedule. Each delegates to a TypeScript module via the bundledtsxruntime. - E2E coverage (Playwright) across all of the above: matrix parsing, fallback chain, policy retry/timeout/cost, pieces engine, init/scan/generate loop, promote loop, compliance, qa-tech-specs, observability, CLI surface.
lib/router.tsno longer hardcodes routing tables; everything resolves vialib/providers/matrix.ts.lib/providers/{llm,image,video}.tsnow contain real adapter classes that call concrete APIs. Mock variants live underlib/providers/__mocks__/and the factory switches based onDRY_RUN.bin/marketing-engine.mjsgenerate/promoteare no longer placeholders.
- All new external behavior is gated by
DRY_RUN=true(the default) — CI never reaches real API endpoints. - The mock providers preserve the original deterministic output, so previously authored e2e specs continue to pass.
- CLI scaffold (
bin/marketing-engine.mjs):init,scan,checkcommands. - Provider type interfaces (
lib/providers/{types,llm,image,video}.ts) and mock implementations. - Publish + analytics scaffolds (
lib/publish/adaptlypost.ts,lib/analytics/{meta,tiktok,youtube}.ts). - Specs tree under
.specs/: architecture (DESIGN, PROVIDERS, ROUTING-MATRIX, ADR-001), product (BRAND, CHANNELS, COMPLIANCE, PERSONAS, PILLARS), piece + campaign templates, client_template/overrides. - 11 SKILL.md documents under
.skills/(provider-neutral skills). - E2E suite (Playwright): CLI, compliance, caption-format, tech-specs, provider-router, AdaptlyPost-publish.
- CI workflow + DoD workflow.
- Remotion video explainer (PT-BR + EN) under
video/. - Bilingual README + SETUP + CONTRIBUTING + AGENTS.md (charter) + Apache-2.0 LICENSE.