# SM Autoposter User Manual This manual explains how to use the current SM Autoposter operator console. It should be updated whenever a new workflow is added. ## What The App Does SM Autoposter is a multi-client social media operations console. It helps you: - create client profiles - research a client's website into Sources - sync reviewed client voice and guardrails into the client wiki - upload local text documents as product or service sources - import GEO Smith recommendations as social content sources - map social accounts to a publishing engine - create campaign plans for objectives, topics, and CTAs - link drafts to campaign plans for cleaner reporting and future agent context - register, approve, reject, and attach generated media assets - collect source material into approved source memory - generate or write post drafts - review draft quality before approval - schedule approved drafts - record post metrics - save lessons so future drafts improve The current version is manual-approval first. Agents can help prepare work, but humans approve before scheduling. ## Opening The App Run the local server, then open: ```bash cmd /c npm start ``` Default URL: ```text http://localhost:8080/ ``` The browser manual is available at: ```text http://localhost:8080/manual ``` After deployment, replace the local manual URL with the hosted manual URL here and in any team onboarding docs. Security note: do not put the app on the public web until the gates in `docs/security-audit.md` are complete. A private test deployment can use `SM_AUTOPOSTER_REQUIRE_AUTH=true` and `SM_AUTOPOSTER_ACCESS_TOKEN=<long-random-token>` as a temporary guard. If that guard is enabled, the browser will prompt for the access token the first time it calls a protected API route. Auth note: the app now supports Clerk as the production auth foundation. When `SM_AUTOPOSTER_AUTH_PROVIDER=clerk` is set, the browser shows Clerk sign-in controls, the signed-in operator, the active organization, Refresh session, Sign out, user controls, and organization switching. API requests are authorized with Clerk session JWTs, and the tenant is taken from the user's active Clerk organization. The API accepts both long-form Clerk org claims and compact Clerk v2 active-organization claims. Clerk beta check note: run `cmd /c npm run clerk:beta-check` only when intentionally testing against a Clerk development instance. Normal production verification should use `cmd /c npm run clerk:check`. Production Clerk note: `cmd /c npm run clerk:check` verifies the Clerk instance is production-grade. It now passes against `https://autoposter.deployagentic.ai` with a production Clerk instance, verified `deployagentic.ai` Clerk domain, Organizations enabled, one production organization, and one production user. Predeploy note: before any hosted deployment attempt, run `cmd /c npm run security:predeploy`, then `cmd /c npm run deploy:preflight`. The security command runs static guardrails, the full test suite, and the whitespace/diff safety check used by the security audit. The deploy preflight checks whether production MongoDB, Clerk, cron, publishing, OpenAI drafting, media storage, timeout, and rate-limit settings are ready without printing secret values. Rate-limit note: normal API buckets default to `SM_AUTOPOSTER_RATE_LIMIT_MAX=120` per organization, method, and route window. Expensive source fetch, feed ingestion, scheduling, and draft-generation buckets use `SM_AUTOPOSTER_SENSITIVE_RATE_LIMIT_MAX=20` by default. Hosted MongoDB deployments share rate buckets through the store so separate function instances do not each get their own independent allowance. Hosted smoke note: after a production deployment, run `cmd /c npm run hosted:smoke`. It verifies hosted health, the manual route, Clerk auth config, unauthenticated client-data rejection, missing-secret rejection on all hosted cron routes, and authorized publisher queue sync without printing the cron secret. After setting `SM_AUTOPOSTER_HOSTED_AUTH_TOKEN` to a Clerk session token, run `cmd /c npm run hosted:preflight-smoke` to verify the live hosted deployment preflight endpoint using the app's actual Vercel runtime configuration. This is the safe path when sensitive Vercel env values cannot be pulled back into local files. Then run `cmd /c npm run hosted:persistence-smoke` to verify hosted MongoDB persistence, protected client reads, and nested audit-event reads without printing the token. Run `cmd /c npm run hosted:access-smoke` with the same short-lived token to verify the protected Client Access instruction route without printing the token or generated client-facing message. Run `cmd /c npm run hosted:document-smoke` to verify protected document source import, source readback, durable source-memory Markdown export, and `document_source_imported` audit coverage without printing the token. The document smoke targets the internal `client-document-smoke` client by default so it does not add smoke sources to real clients. Run `cmd /c npm run hosted:service-document-smoke` to verify the protected document-service connector list, Google Drive/Docs provenance import, durable source-memory Markdown export, source readback, and `document_service_source_imported` audit coverage. It also targets `client-document-smoke` by default. Run `cmd /c npm run hosted:draft-smoke` to import a safe source, generate a source-backed draft, verify the draft stays unapproved, and confirm `draft_generation_succeeded` audit coverage without scheduling or publishing. Hosted import failures print only sanitized error summaries. On Vercel, document-source Markdown writes default to `/tmp/sm-autoposter-wiki` unless `SM_AUTOPOSTER_WIKI_ROOT` is configured; local Obsidian runs still default to `wiki/`. Run `cmd /c npm run hosted:media-smoke` to upload a hosted test media file, verify the upload has provider-ready object-storage metadata, read it back, approve it, attach it to a draft, and verify the media audit trail without printing the token. Run `cmd /c npm run hosted:media-publish-smoke` only when you intentionally want to schedule one future internal MeWe post to prove the uploaded media handoff through the publishing provider. Use a fresh short-lived token for the command only; do not store it in `.env.local`. Provider verification note: after real MongoDB, OpenAI, and publishing values are in `.env.local` or Vercel, run `cmd /c npm run providers:verify`. It pings MongoDB, checks OpenAI model access, and verifies publishing API connectivity. Set `SM_AUTOPOSTER_VERIFY_PLATFORM=mewe` when testing the MeWe channel specifically. Run `cmd /c npm run smoke:mewe` to verify the connected MeWe account is visible without writing app records, or `cmd /c npm run smoke:mewe -- --write` to seed the internal test client/account/draft, record the `social_account_mapped` smoke audit event, and run the non-publishing safety gate. Run `cmd /c npm run smoke:mewe -- --schedule` only when you intentionally want to approve and schedule one future MeWe test post through the real publishing boundary. It Results status only and does not print the MongoDB URI, OpenAI API key, or publishing API key. Media note: generated media is stored as a separate media asset before it becomes draft media. Use the Media Assets panel in Content to upload a local image/video file, generate an image from the prompt when OpenAI media generation is configured, or paste an external asset URL as a fallback. In production, uploaded or generated media bytes go to Vercel Blob/object storage and the asset path becomes a provider-fetchable `https://` URL that can be handed to publishing workers. The media card shows a Provider-ready badge when the asset has a provider-fetchable URL, a preview/open link for safe media routes, and whether the asset is ready to attach or already attached to its draft. Local DB-inline storage remains only a controlled fallback for development. New assets start as `pending_review`; an operator must approve the asset before it can be attached to a draft. This keeps video/image generation behind the same human-approval boundary as copy and scheduling. The hosted media smoke targets the internal `client-sm-autoposter-test` / `draft-mewe-smoke-test` smoke records by default and creates those safe test records if the signed-in organization does not have them yet. Set `SM_AUTOPOSTER_HOSTED_MEDIA_CLIENT_ID` and `SM_AUTOPOSTER_HOSTED_MEDIA_DRAFT_ID` only when you want a different internal smoke target. Current provider status: MongoDB, OpenAI, and publishing provider verification passed locally on 2026-05-18 using `.env.local` values. The dedicated Vercel project is `ewishkis-projects/sm-autoposter`, with canonical production domain `https://autoposter.deployagentic.ai`, and production environment variables configured for MongoDB, Clerk production keys, Clerk authorized parties, OpenAI drafting, cron, and publishing provider access. Current hosted status: production deployment is live at `https://autoposter.deployagentic.ai`. Hosted smoke checks passed on 2026-05-21 for `/api/health`, `/manual`, Clerk production auth config, unauthenticated client-data rejection, missing-secret rejection on all hosted cron routes, and authorized publisher queue sync. Authenticated hosted persistence, Client Access, document, source-backed draft, and media smokes also passed on 2026-05-21 against production deployment `dpl_7igsMPgq4BRrqu9XkFPvXXyKytrJ`: MongoDB/Clerk status returned 200, protected client reads returned two clients, access instructions returned Facebook Page guidance, document import wrote governed source memory, draft generation created an unapproved source-backed draft with audit coverage, and media upload used provider-ready Vercel Blob storage with readback, approval, attachment, and audit coverage. The controlled MeWe beta schedule is local `scheduled-mewe-smoke-test`, provider post `cmp73nw3h026xqh0yclp46obd`, and the app-side publisher status synced to `PUBLISHED` after the provider confirmed publication on 2026-05-18. Reliability note: the app now fails closed on stuck requests. Browser API calls time out after 20 seconds and duplicate identical calls are suppressed while the first one is still running. Server API requests default to 30 seconds, source fetches default to 15 seconds, and publishing provider calls default to 15 seconds. If a request times out, retry once after checking the source URL, publishing provider status, or network connection. Source fetch safety note: URL, sitemap, RSS, and YouTube transcript fetches reject local hosts, private IP ranges, and redirected final URLs that land on private network targets before reading the response body. Sitemap imports only crawl same-host page URLs from the submitted sitemap and use the page limit shown in the form. Use normal public source URLs and keep internal documents in manual uploads instead. Database note: local development defaults to SQLite at `data/sm-autoposter.sqlite`. Production-style testing can use your MongoDB account by setting `SM_AUTOPOSTER_STORE=mongodb`, `MONGODB_URI=<connection-string>`, and `MONGODB_DB=sm-autoposter`. Keep the MongoDB URI in `.env.local` or hosted environment variables, never in docs or committed files. Atlas network note: if Atlas warns that `0.0.0.0/0` or `::/0` was added, follow `docs/mongodb-network-hardening.md` before public deployment. Keep SM Autoposter in its own Vercel project. Run `cmd /c npm run mongodb:check` to confirm the runtime DB user remains app-scoped; it fails if the MongoDB user has broad roles such as `readWriteAnyDatabase`. Atlas infrastructure note: run `cmd /c npm run atlas:review` after Atlas CLI login to check project network access, backups, point-in-time restore, private endpoints, and cluster tier without printing secrets. The current M0 private-beta cluster has broad `0.0.0.0/0` access and no backups. Do not remove broad access until a stable hosted egress or private connectivity path is available, because default hosted serverless egress can change. Environment note: `docs/environment-variables.md` is the safe setup checklist. Use it to create your local `.env.local`, and use the same key list when adding Vercel environment variables. Never paste real API keys, MongoDB URIs, Clerk secrets, OpenAI keys, or any `.env*` file into git. Drafting note: source-backed draft generation defaults to the deterministic fallback. To use OpenAI, set `SM_AUTOPOSTER_DRAFT_PROVIDER=openai`, `OPENAI_API_KEY=<key>`, and optionally `OPENAI_DRAFT_MODEL=gpt-5.2`. Client intake profile building uses the same OpenAI provider when available, or set `SM_AUTOPOSTER_PROFILE_PROVIDER=openai` plus optional `OPENAI_PROFILE_MODEL` and `OPENAI_PROFILE_TIMEOUT_MS`. You can also set `SM_AUTOPOSTER_MODEL_TIER` to `economy`, `balanced`, or `quality`, then map those tiers with `OPENAI_DRAFT_MODEL_ECONOMY`, `OPENAI_DRAFT_MODEL_BALANCED`, and `OPENAI_DRAFT_MODEL_QUALITY`. `OPENAI_DRAFT_MODEL` is the strongest draft override when set. Set `SM_AUTOPOSTER_DISABLE_LLM_DRAFTS=true` to stop paid LLM draft and profile-builder calls immediately and use the fallback. The System Status panel under Settings shows whether drafting is using the fallback, OpenAI, or the LLM disable switch. OpenAI drafts still require human approval before scheduling. Media generation note: image generation is disabled unless `SM_AUTOPOSTER_MEDIA_GENERATION_PROVIDER=openai` and `OPENAI_API_KEY` are configured. The default image model is `gpt-image-1.5`, with optional `OPENAI_IMAGE_MODEL`, `OPENAI_IMAGE_SIZE`, `OPENAI_IMAGE_QUALITY`, and `OPENAI_IMAGE_TIMEOUT_MS` overrides. Set `SM_AUTOPOSTER_DISABLE_MEDIA_GENERATION=true` to immediately stop paid image generation calls. Generated media is saved as a pending media asset; it is not attached to a draft or scheduled until approved. Tenant note: clients are assigned to an organization ID. Local development defaults to `local-org`; Clerk auth uses the active Clerk organization ID; a private token-hosted test can set `SM_AUTOPOSTER_ORGANIZATION_ID=<tenant-id>`. The UI only shows clients for the current organization context. Role note: authenticated API writes are route-scoped. `owner` and `admin` can write all current routes. `editor` can create and operate content workflows, including scheduling. `reviewer` can approve/reject drafts, update source review status, preview safety, record recommendation reviews, and add metric/lesson evidence, but cannot schedule or change client/account configuration. `reporting` can add metric and lesson evidence, but cannot change client/account configuration. `read-only` can inspect authorized client data, Results, and audit trails, but cannot modify work. ## Main Dashboard Areas The left navigation is organized around the human workflow: - Overview: selected-client status, readiness, and the next unfinished action. - Clients: create clients and maintain profile, voice, guardrails, humanization profile, approval rules, and autonomy policy. - Sources: add approved client knowledge from URLs, documents, feeds, manual notes, and GEO Smith recommendations. - Content: create or generate drafts, choose a posting style for source-backed drafts, upload or attach media, review quality, and approve work. - Publishing: map connected channels, prepare access instructions, and sync account connection status. - Results: scheduled posts, metrics, lessons learned, performance insights, prompt/profile proposals, and agent recommendations. - Settings: system status, beta readiness, deployment checks, and smoke-test cleanup. Use the light/dark toggle in the top-right corner to switch themes. ## Signing In Local development can run without auth. Private testing can use the temporary bearer-token prompt. Production-style testing should use Clerk: ```text SM_AUTOPOSTER_AUTH_PROVIDER=clerk CLERK_PUBLISHABLE_KEY=<clerk-publishable-key> CLERK_SECRET_KEY=<clerk-secret-key> CLERK_REQUIRE_ORGANIZATION=true ``` When Clerk is enabled: 1. Open the app. 2. Sign in with the enabled method, such as email or Google. 3. Select or create the organization for the client workspace. 4. Confirm the System Status Auth card shows Clerk configured. If no organization is active, the app asks you to choose one before loading client data. This is intentional because client records are isolated by organization. The top-right session area shows the signed-in email or Clerk user label, active organization, and session status. Use Refresh session if a browser tab has been open for a while or an API request Results that the Clerk session expired. If refresh fails, the app hides client data behind a Session expired screen with options to refresh, sign in again, or sign out. The System Status panel lives under Settings. It shows publishing credential readiness, wiki path, database path, auth mode, drafting provider status, supported platform count, manual route, and Deploy Preflight. Deploy Preflight summarizes production readiness and names the first missing checks without showing secret values. The API also exposes `/api/settings/deployment-preflight` for the same sanitized report. The Beta Readiness panel lives under Settings and mirrors the CLI beta checklist from `/api/settings/beta-readiness`. It highlights blocked and manual beta gates first, then shows a small sample of ready gates. It also includes Current signed-in session, which uses your active Clerk session to confirm the protected Mongo-backed client read and nested audit-event read path. Use it after signing in to see whether provider checks, hosted smoke, Clerk checks, MongoDB hardening, session persistence, document import smoke, source-backed draft smoke, media approval smoke, and the MeWe beta flow are ready without opening the terminal. It never shows secret values. The Test Data Cleanup panel also lives under Settings. It uses `/api/settings/beta-cleanup` to find only known internal smoke clients in the current Clerk organization, including `client-sm-autoposter-test`, `client-draft-smoke`, `client-document-smoke`, and `client-hosted-media-smoke`. The Delete smoke data button requires owner/admin access and sends the fixed confirmation phrase `DELETE SMOKE DATA`; it does not delete normal client IDs or smoke clients that belong to another organization. The Overview screen includes the Next Step Path. It turns the selected client's real workflow state into a launch checklist: profile and guardrails, source memory, campaign plan, social account mapping, draft creation, human approval, scheduled post, and optional media readiness. Each card opens the screen that fixes that step. This is an operator guide only; it does not bypass approval, schedule posts, or publish anything. The Client Readiness checklist shows the next setup gaps for the selected client. It checks profile basics, mapped social accounts, source memory, campaign plans, draft activity, and scheduled posts. Use it as the first place to look when onboarding a new client or when a client workflow feels incomplete. The Clients screen starts with only the business name, website, and optional source documents. Build client profile researches/imports those inputs and fills the editable profile. Review it, then click Update profile to save. The Humanization profile fields control how drafts should sound: reading-grade target, client-native jargon, words to avoid, sensory/personal detail anchors, CTA frequency, and soft CTA examples. Add more resources merges new URL/document evidence into the current form without deleting old profile lines. Use Blog index source when you have a blog listing page such as `/blog`; the app discovers same-site post links and imports each actual article as source memory for the selected client. The Sources screen also supports document-service imports. Use Import document-service source when the useful client knowledge lives in Google Docs, Drive, OneDrive, SharePoint, Notion, Dropbox, Box, or a CMS export. Paste the reviewed text, keep the source URL or external document ID, and leave the source in Needs review unless you have verified the claims. This preserves provenance now and leaves room for authenticated connectors later without changing the approval workflow. After deployment, `cmd /c npm run hosted:service-document-smoke` verifies the signed-in production path with a short-lived Clerk token. For local Obsidian vaults, use Local Obsidian vault sync on the Sources screen instead of uploading the whole folder through the browser. The hosted app cannot read a Windows path directly, so the screen builds a PowerShell command that you run locally. The sync command reads the vault, skips `.obsidian`, hashes supported files, sends only changed `.txt`, `.md`, `.markdown`, `.csv`, and `.json` files through the bulk source API, and writes a `.sm-autoposter-sync.json` manifest in the vault. This indexing path does not call the LLM; LLM cost happens later only when a draft is generated from selected source memory. The Content screen has a Posting style selector for source-backed drafts. Auto lets the agent choose. Alpha is the clean/direct note, beta is the looser field-note style, and gamma allows a soft CTA when appropriate. Draft generation passes the selected style, the saved humanization profile, approved source memory, performance theme learning, and a matching style example into the draft agent. Generated drafts still start unapproved. The Style Examples panel shows curated and operator-managed humanization examples that can influence generation. Add a client-specific example when you have approved copy that captures the client's tone better than the defaults. Operator-managed examples can be edited in place from the same card; curated defaults are read-only. Use Export style examples to download active operator-managed examples as JSON, then import that file into a similar client when the same writing style should be available there. Use Allow to prefer a specific example for the selected client, Avoid to keep an example out of future selection, and Neutral to remove that override. Retire an operator-managed example when it stops fitting the client. Each posting-output artifact records the exact example, selection reason, guidance, sample excerpt, and compact performance report when metrics exist. Examples are advisory only; they do not approve, schedule, publish, or overwrite the client profile. The Content screen includes a lightweight Content Copilot box. It answers workflow questions from the selected client's current state, such as what is blocking scheduling, what needs approval, or how to create the next post. It is read-only guidance and does not create, approve, schedule, or publish anything. The Results screen includes Style Example Learning. It compares the exact example used by scheduled posts, not only the alpha/beta/gamma format family. Use it to decide which examples should be allowed, avoided, or kept neutral for future drafts. Download performance summary creates a Markdown client-review export with a plain-English summary, use-more/use-less/keep-testing buckets, measured evidence, and data notes. It is read-only; it does not apply profile changes or prompt-setting changes. For production verification, `npm run hosted:style-review-smoke` checks the signed-in Results workflow after a client has style-example metrics. It confirms the app can read the performance summary, find the client in bulk recommendation review, create a proposal, accept it, and show the exact apply preview. By default, it dismisses the smoke-created proposal after preview so repeated tests do not leave accepted proposals behind. Use `-- --keep-proposal` only when you want to inspect that proposal manually, and use `-- --apply` only when you intentionally want to write the previewed changes. ## Client Setup Start every workflow by creating a client. 1. Go to Clients. 2. Enter the business name and Website URL. 3. Optionally upload source documents. 4. Click Build client profile. 5. Review the generated Voice & Guardrails fields. 6. Edit anything that needs human judgment, then click Update profile. 7. Use Add more resources when you find more documents, folders, URLs, or a blog listing URL later. 8. Review the merged profile fields, then click Update profile again. 9. Click Export current profile to wiki after the reviewed profile is ready to become durable team memory. Recommended Voice & Guardrails fields: - Audience: one audience segment per line, such as contractors or homeowners. - Offers: products, services, downloads, audits, or CTAs the client wants to promote. - Forbidden claims: claims the system should flag for review, such as guaranteed savings. - Voice examples: short examples of how the client should sound. - Approval rules: internal rules for review before scheduling. - Website URL: the client's main site. This powers website research and future website-first answer workflows. These fields are used by generated drafts and quality checks. Website research and Add more resources do not automatically overwrite the saved client profile. They fill the editable profile form for review, and the profile changes are saved only after you click Update profile. Add more resources accepts a URL, uploaded text/Markdown/CSV/JSON documents, a folder of supported documents, dropped folders/files, a blog listing URL, or a combination. The folder picker imports one selected parent folder recursively; choose a shared parent folder when you want multiple subfolders, or drag multiple folders into the drop zone in Chrome or Edge. This browser folder path is only intended for small one-off document sets. For a real Obsidian vault, use Sources -> Local Obsidian vault sync so unchanged files are skipped on future runs. The importer only accepts `.txt`, `.md`, `.markdown`, `.csv`, and `.json` files and reports skipped unsupported files. Normal resource URLs are merged into the profile form. Blog listing URLs are treated as indexes: the app imports the same-site article links it finds as separate blog post source records. Imported blog posts do not automatically rewrite the profile or create posts; review them on Sources and mark useful ones Trusted, leave uncertain ones Needs review, or Block sources that should never be used. The resource merge path rebuilds profile suggestions in additive mode and merges new audience, offer, claim, voice, and approval-rule lines into the editable form without removing existing lines. The business summary may be refined, but list-style profile memory is preserved unless an operator manually edits it. Autonomy Policy is below Voice & Guardrails. Use it to define what future agents may recommend or draft, what still requires explicit approval, and what is blocked for that client. The current system always keeps human approval required and execution disabled, even if `schedule` appears in allowed actions. Updating the policy writes an `autonomy_policy_updated` audit event. Profile sync writes the reviewed client profile to: ```text wiki/wiki/clients/<client-name>/profile.md ``` Use this page in Obsidian to review the client's business, audience, offers, forbidden claims, voice examples, and approval rules. The database remains the operational truth; click Export current profile to wiki after meaningful profile edits so source memory stays aligned. This replaces `profile.md` with the current saved app profile; it does not overwrite source records, blog sources, or other client wiki pages. The client list shows the expected Profile wiki path so operators can quickly find the matching Markdown page after sync. ## Social Account Setup Social accounts connect a client to the publishing engine. 1. Go to Publishing. 2. Select the client. 3. Under Client Access, pick the platform and optionally enter the client's contact name and email. 4. Click Prepare instructions. 5. Review the platform-specific access model and client steps. Facebook Page, LinkedIn Page, Google Business, MeWe, and other channels use the safest delegated-access path the app can describe without exposing backend infrastructure. 6. Send the generated message to the client. It is safe to share because it asks for delegated account access and explicitly says not to send passwords. 7. After the client grants access, click Load integrations. 8. Pick the returned integration and click Use. 9. Review the selected client, platform, and provider integration ID. 10. Click Map account. If publishing credentials are configured, click Load integrations to fetch connected accounts from the publishing engine. Click Use on an integration to prefill the account form. After mapping accounts, click Sync connections to verify that each saved provider integration ID still exists in the publishing engine. Accounts marked Missing should be remapped or reconnected before scheduling. Use Deactivate account when a channel is disconnected, revoked, or should stop receiving scheduled posts; use Reactivate account only after the mapping is intentionally valid again. The API can also apply provider account events from `/api/publisher/account-events`: token refresh failures and provider-side disconnects mark the mapped account inactive and Missing, while reconnect events mark it active and Connected. The app can still be used for clients, drafts, sources, metrics, and Results without publishing credentials. Scheduling requires the publishing engine credentials. Publishing provider credentials are configured locally and in Vercel production as `PUBLISHER_BASE_URL=<provider-api-origin>` and `PUBLISHER_API_KEY=<secret>`. Supported platforms currently include X, LinkedIn, LinkedIn Page, Reddit, Instagram, Facebook Page, MeWe, Threads, YouTube, Google Business, TikTok, Pinterest, Dribbble, Discord, Slack, Kick, Twitch, Mastodon, Bluesky, Lemmy, Farcaster, Telegram, Nostr, VK, Medium, Dev.to, Hashnode, WordPress, and Listmonk. Each account also shows a safety stage: - Launch: first 14 days after the account is mapped. - Warmup: day 14 through day 59. - Established: day 60 and later. The safety stage controls conservative posting caps and minimum spacing. This is intentionally stricter than most marketing advice because the app is meant to protect client accounts before optimizing volume. If an account is Inactive or its connection status is Missing, the scheduling safety check blocks the post before it reaches the publishing boundary. ## Campaign Plans Campaign plans define the strategy a group of drafts should follow. 1. Go to Content. 2. Under Campaign Plans, select the client. 3. Add the campaign name. 4. Add the objective. 5. Add one topic per line. 6. Add the CTA. 7. Click Add campaign. Use campaign plans for content sprints such as product education, objection handling, seasonal offers, or GEO Smith gap coverage. Drafts can now be linked to a campaign, which keeps the post tied to its objective and gives future agents cleaner strategy context. Campaign plans can be updated after creation: 1. Edit the campaign objective, topics, CTA, or status in the Campaign Plans list. 2. Click Save campaign. Use Active for campaigns that should appear in the draft campaign selector. Use Paused for campaigns you want to keep but temporarily stop using for new drafts. Use Completed when the campaign is finished but should remain available for reporting and lessons. Every campaign create or update also writes a campaign strategy page into the client wiki: ```text wiki/wiki/clients/<client-name>/campaigns/<campaign-id>.md ``` Use these pages in Obsidian when reviewing campaign objective, topics, CTA, and status with the team. Future agents should use these pages as durable strategy memory before drafting or recommending campaign changes. The Campaign Plans list shows the current wiki path for each campaign so operators can find the matching Markdown page quickly. ## Source Ingestion Sources are the raw material for draft generation. You can add sources nine ways: - Fetch URL source: paste an article or page URL. - Blog index source: paste the blog listing page, such as `https://example.com/blog`. The app discovers same-site article links from that index and saves each actual post as its own `blog_post` source memory item. The index page is not treated as the article; each discovered article keeps its original URL so future social posts can link to it or rewrite from it. - Fetch YouTube transcript: paste a YouTube URL and import the transcript as a source. - Fetch sitemap pages: paste a public sitemap URL and import a bounded set of same-site pages. - Ingest RSS feed: paste a feed URL and import recent items. - Saved source feed: store a reusable RSS feed, sitemap, or YouTube channel feed for the selected client, then click Fetch latest for one feed or Run due feeds for all due saved feeds. - Manual source: paste source title, URL, captured text, and synthesis yourself. - Upload document source: choose a local text document and add it to the client's governed source memory. - Import GEO Smith recommendation: paste an AEO/GEO search gap and social recommendation from GEO Smith. Saved source feeds: 1. Go to Sources. 2. Under Saved source feed, select the client. 3. Choose RSS, Sitemap, or YouTube channel. 4. Add a feed name, feed or sitemap URL, topic tags, and trust score. 5. Click Save feed. 6. In the saved feeds list, click Fetch latest when you want to ingest recent items, same-site sitemap pages, or YouTube channel entries into Sources. Use saved feeds for recurring industry publications, client-approved sitemaps, client YouTube channels, news sources, and trusted topical feeds. The feed record keeps the default trust score and topic tags so imported items arrive with consistent source metadata. Sitemap feeds keep the same-host crawl boundary used by the one-off sitemap import. YouTube channel feeds use the public `https://www.youtube.com/feeds/videos.xml?channel_id=...` feed shape and import video entries as reviewable source memory. Blog index sources are for high-value owned articles that should become social post material. Paste the blog listing URL in Sources, import discovered posts, then mark the individual article sources Trusted after review. The app stores readable article text and keeps each article URL attached so generated drafts can point back to the original blog post when that is useful. The saved feeds list shows when each feed was last fetched, whether the feed is fresh, stale, or never fetched, and how many source records were imported. A feed becomes stale after 7 days without a fetch. Use that status to refresh recurring sources before generating new drafts. YouTube transcripts: 1. Go to Sources. 2. Under YouTube video URL, select the client. 3. Paste the YouTube video URL. 4. Add topic tags when useful. 5. Click Fetch YouTube transcript. Use this for client videos, trusted creator videos, interviews, product demos, and explainers that should become source-backed social material. The transcript becomes a normal source record with provenance and can be reviewed, trusted, blocked, or used for draft generation like other sources. Saved feed jobs: 1. Go to Sources. 2. Select the client. 3. Under Saved feed jobs, click Run due feeds. 4. Review the job summary for fetched feeds, skipped feeds, and created source records. Run due feeds imports never-fetched or older saved feeds for the selected client and skips feeds fetched recently. This is the operator route for manual feed refreshes. Each fetched source feed writes a `source_feed_run` audit event with the feed, source type, status, created record count, freshness reason, and latest fetch timestamp. Hosted automation uses a separate cron-safe route: ```text GET /api/jobs/source-feeds/run-due Authorization: Bearer <CRON_SECRET> ``` That hosted route runs due feeds without accepting an arbitrary client ID from the caller. It fails closed if the cron secret is missing or wrong. Daily review snapshot automation uses the same cron-secret pattern: ```text GET /api/jobs/review-snapshots/sync Authorization: Bearer <CRON_SECRET> ``` This writes each client's current review snapshot into the Markdown wiki so the team has a fresh operator brief for daily review. It does not publish, schedule, draft, or accept a client ID from the caller. Publisher queue status automation uses the same cron-secret pattern: ```text GET /api/jobs/publisher-posts/sync Authorization: Bearer <CRON_SECRET> ``` This reconciles local scheduled posts against the publishing provider queue, persists the latest status on scheduled posts, and writes audit events. It does not publish, schedule, draft, delete posts, or accept a client ID from the caller. Vercel setup note: the repo includes `vercel.json` with API/manual rewrites and three cron schedules. Source feeds run at `0 6 * * *`, review snapshots sync at `0 12 * * *`, and publisher queue status sync runs hourly at `0 * * * *`. A local hourly Codex automation sends grouped, sanitized incidents through the connected Linear plugin. `CRON_SECRET` is configured in Vercel production. Run `cmd /c npm run deploy:preflight` after environment changes; it should report zero errors before deployment. Source governance: - Trusted: source can be used for drafts when the claims still match the client guardrails. - Needs review: source is stored, but operators should inspect it before approving posts based on it. - Blocked: source remains stored for provenance, but the app blocks draft generation from it. Use Source notes to explain why a source is trusted, needs review, or blocked. This helps future agents avoid weak sources without deleting the historical record. The source list includes status counts and filters for All sources, Trusted, Needs review, and Blocked. Each source row also shows a freshness badge so stale material is visible before draft generation. Use these filters to review risky sources before generating drafts, or to confirm which blocked sources are being retained only for provenance. After reviewing a source, change its Status in the source list, update the Notes field, and click Save source status. Use this to promote reviewed sources to Trusted or to mark weak sources as Blocked without deleting their history. Document upload: 1. Go to Sources. 2. Under Upload document source, select the client. 3. Choose a local `.txt`, `.md`, `.csv`, or `.json` file. 4. Add a short synthesis if you already know what the app should remember. 5. Click Upload document source. Use document upload for product sheets, service descriptions, FAQs, internal notes, and offer details that are not published on the client website yet. The operator console sends these through the protected document import route, not URL fetch, so private notes are stored as governed source memory with document provenance and audit history. Sitemap page crawl: 1. Go to Sources. 2. Under Fetch sitemap pages, select the client. 3. Paste a public sitemap URL such as `https://example.com/sitemap.xml`. 4. Add topic tags such as `owned-site`, `services`, or `FAQs`. 5. Set a small page limit. The default is 5 and the API caps the request. 6. Click Fetch sitemap pages. The app fetches the sitemap, keeps same-host URLs, fetches each page, extracts readable text, writes each page into the wiki, and stores each source as review-needed source memory. Review each source status before generating drafts from it. GEO Smith recommendation import: 1. Go to Sources. 2. Under Import GEO Smith recommendation, select the client. 3. Add a title, the AI search gap, the search query, and the recommendation. 4. Add the suggested topic, starter copy, evidence URLs, and priority when available. 5. Click Import recommendation. Use this when GEO Smith finds that a client is missing from AI-search answers or has weak AEO/GEO coverage. The import becomes governed source memory, so you can generate platform-specific drafts from it while keeping the original gap, evidence, and recommendation for review. The API also exposes a read-only GEO Smith export at `/api/clients/<client-id>/geo-smith-export`. It returns imported GEO Smith recommendation sources, drafts created from those sources, scheduled posts, metric snapshots, and lessons. This is for future app-to-app sync and attribution only. It does not allow GEO Smith to schedule or publish anything. Operators can preview that same export in the UI: 1. Go to Results. 2. Select the client you want to review. 3. Under GEO Smith Export, click Preview export. 4. Review the counts for recommendation sources, related drafts, scheduled posts, metric snapshots, and lessons. Use this preview before sharing feedback with GEO Smith or checking whether imported recommendations are producing measurable social results. When a source is ingested, the app writes immutable raw source capture files and synthesized Markdown notes into the wiki folder. The database stores the source record, wiki paths, and generated Markdown content. The source list shows both the synthesized Wiki path and Raw capture path when those files exist, so operators can open the matching notes in Obsidian during review. ## Knowledge Manifest The app can also expose a client-scoped knowledge manifest for future indexing into Pinecone or another knowledge layer: ```text GET /api/clients/<client-id>/knowledge-manifest ``` The manifest lists each client Markdown note with its relative vault path, document type, title, content hash, byte size, indexable flag, and client namespace. It does not expose local absolute file paths. Use this endpoint as the bridge between Obsidian and future agent memory. Obsidian stays the place where humans review durable synthesis. MongoDB stays the operational truth. Pinecone, when added, should index changed manifest files so agents can retrieve better source-cited context without replacing either one. For hosted source-memory export that does not depend on temporary Vercel wiki files, use: ```text GET /api/clients/<client-id>/source-memory-export ``` This returns raw source captures and synthesized source notes from durable database records with content hashes, byte sizes, and source metadata. Operators can download the same durable bundle from the app: 1. Go to Sources. 2. Select the client. 3. Click Download source memory. 4. Keep the downloaded Markdown with the client handoff, agent context, or external review packet. The download is read-only. It does not change source status, approve drafts, or write new wiki files. ## Draft Creation There are two draft paths today. Manual draft: 1. Go to Content. 2. Select the client. 3. Select a campaign when the draft belongs to a planned content sprint. Leave it as No campaign for one-off posts. 4. Under Posting targets, select one or more mapped social accounts. Use Select all targets if the draft should go to every mapped account for that client, or Clear targets to start over. 5. Add a topic and copy. 6. Click Add draft. Source-based draft: 1. Ingest a source. 2. Select a campaign in Content when the generated draft should support that campaign. 3. Select one or more Posting targets in Content. 4. Find the source in the Sources list. 5. Click Generate draft. Generated drafts use client audience, offers, voice examples, selected campaign objective and CTA, source details, SEO/AEO/GEO metadata, and forbidden-claim checks. Draft generation also receives recent content memory from existing drafts and scheduled posts. This helps the generator choose a fresh campaign topic or source angle instead of repeating what was already drafted or scheduled. If a generated draft still overlaps a recent topic, the draft quality report adds a warning so the operator can revise the angle before approval. Each selected target account gets its own platform-specific variant. The app should not send identical copy to every platform. Short-form networks get tighter hooks, professional networks get decision-oriented framing, visual platforms get caption-style copy, and video platforms get script-style hooks. ## Reviewing Drafts Every draft card shows: - the draft topic and selected platforms - the post copy - platform-specific variants that can be edited before approval - the written hypothesis - quality report status, issues, warnings, and optimization checks - optimization counts for GEO, AEO, SEO, and voice - attached source titles, source type, and wiki path when the source is already in the Sources Use this section before approving a draft. If a draft has quality issues, revise it before approval. The API blocks approval when the quality report fails. Warnings do not block approval, but they should be reviewed. For example, a manual draft with no source can pass if the copy is clean, but it will warn you to verify claims manually. Posting output artifacts add a second review layer for human-readable final copy. Their validation flags can now call out standard AI-pattern phrases, client fluff blacklist matches, internal notes such as `review note:` or `field note:`, glossary-style definition blocks, hard CTA or engagement-bait wording that conflicts with the saved CTA policy, and missing client-specific detail. Artifacts with failed validation must be edited or regenerated before approval. Each artifact card includes an editable Post copy box. Use Save edited copy when the operator wants to fix the human-readable artifact without changing the source draft. The app re-runs validation on the artifact and returns it to pending approval. If the artifact has validation flags, Regenerate with fixes creates a new pending revision from the same draft and keeps the original artifact for audit. Every source-backed draft generation attempt is stored as a draft generation run. The API route is: ```text GET /api/clients/<client-id>/draft-generation-runs ``` Use it for audit review, troubleshooting failed provider calls, and future cost reporting. It stores provider, model, status, duration, token usage when available, and a shortened error message when generation fails. Each source-backed draft-generation success or failure also writes a client audit event tied to the draft generation run. Drafts generated from sources marked Needs review also carry a quality warning naming the source. Treat that as a prompt to open the source note, confirm the claims, and either approve the draft, revise it, or change the source status. Drafts generated from sources captured more than 90 days ago also carry a freshness warning. The draft can still be approved, but verify that product details, prices, rules, statistics, news, and platform-sensitive claims are still current before scheduling. ## Revising Drafts Draft cards include editable Topic and Copy fields. 1. Edit the topic or copy directly in the draft card. 2. Edit any platform-specific Variant copy or Variant notes that need a different hook, CTA, or platform angle. 3. Click Save revision. 4. Review the draft again. 5. Approve it when the revision is ready. Saving a revision returns the draft to draft status, clears prior approval/rejection state, and marks the quality report as needing review. This prevents edited copy from staying approved accidentally. ## Approving And Scheduling Drafts cannot be scheduled until approved. 1. In Content, click Approve. 2. Choose a Schedule time for the platform you want to schedule. 3. Click Check safety to preview whether that account can safely receive the post at that time. 4. Review the safety report. If it says blocked, adjust the schedule time or revise the copy. 5. Click the platform-specific Schedule button. Before the app sends a schedule request to the publishing engine, it runs an account safety gate. The gate blocks risky schedules when: - the account has already reached its current rolling 24-hour post cap - the new post is too close to another scheduled post on the same account - the copy is substantially duplicate of another post scheduled for the client in the last 30 days - the schedule time is invalid or in the past Blocked schedules do not reach the publishing engine. Adjust the schedule time or revise the copy before trying again. Scheduled posts appear in Results under Scheduled Posts. Click Sync publisher status when you want to refresh the selected client's publishing queue state immediately instead of waiting for the hourly hosted job. This checks whether each local scheduled post still matches a provider queue record and stores the result locally for review. It does not publish, schedule, delete, or change post copy. Scheduled post rows and metric selectors show the campaign name and draft topic when the scheduled draft is linked to a campaign. This keeps reporting readable without looking up draft IDs. Scheduled post rows also show the latest Publisher status. A normal queued post should show `Publisher: matched QUEUE` with the scheduled provider time. `missing`, `unavailable`, or `error` means the operator should inspect the publishing provider before assuming the post is safely queued. Scheduled post rows also show captured, missing, and due metric windows. Use that checklist to keep the 1h, 24h, 72h, 7d, and 30d snapshots current without treating future windows as immediate work. Results also includes Metric Reminders. This list shows metric windows due now plus the next upcoming uncaptured window for each scheduled post. Click Fill metric form on a due row to preselect the scheduled post and result window before entering the numbers. Upcoming rows are planning reminders so you know when the next `1h`, `24h`, `72h`, `7d`, or `30d` capture is coming. Results also includes Account Safety Actions. This list summarizes launch and warmup accounts, community-channel caution, and accounts that have already reached the current rolling 24-hour posting cap. Use it before adding more scheduled posts for a client. Results also includes Source Memory Actions. This list summarizes saved feeds that need fetching, stale feeds, sources that need review, stale source material, and blocked sources retained for provenance. Use it before generating or approving source-backed drafts. Results also includes Campaign Strategy Actions. This list highlights active campaigns that need drafts, campaigns with drafts but no scheduled posts, campaigns with scheduled work but no lessons, and paused or completed campaigns that still have unresolved draft work. Results also includes Draft Review Actions. This list shows drafts that need revision, drafts waiting for approval, and approved drafts that still need scheduling. Use it as the daily operator checklist before opening individual draft cards. ## Approval Audit Results includes an Approval Audit section. It shows recent approve and reject events for the selected client, including: - action taken - operator - draft topic - target platforms - timestamp - rejection reason when provided Use this when checking who approved a draft, why a draft was rejected, or whether a revised draft has a fresh approval before scheduling. The API also exposes a broader client audit event list at `/api/clients/<client-id>/audit-events`. This currently records social access instruction prep, social account mapping, connection syncs, deactivations, reactivations, provider disconnects, token refresh failures, source ingestion, external recommendation imports, source-status changes, source feed runs, draft-generation success/failure, scheduled-post creation, manual metric snapshots, metric CSV imports, lesson creation, recommendation review decisions, publisher status syncs, and client wiki syncs with organization ID, actor, action, target, request IP, user-agent, metadata, and timestamp. It is intended for security review and future admin reporting. ## Metrics Metrics are recorded manually in the current version. 1. Go to Results. 2. Under Metric Snapshot, select the scheduled post. 3. Select the result window: 1h, 24h, 72h, 7d, or 30d. 4. Enter the metrics you have. 5. Leave unsupported or unavailable metrics blank. 6. Click Save metrics. Blank metrics are stored as null, not zero. The app computes a qualified engagement score using: - comments - replies - shares - reposts - saves - bookmarks - clicks - follows Likes, reach, and impressions are kept as context but are not the main optimization target. CSV metric import: 1. Go to Results. 2. Under Metric CSV Import, select the client. 3. Paste CSV text with a header row. 4. Include `postId`, `window`, and `platform`, plus any available metric columns. 5. Click Import CSV metrics. Supported metric columns are `impressions`, `reach`, `likes`, `comments`, `replies`, `shares`, `reposts`, `saves`, `bookmarks`, `clicks`, `follows`, `videoViews`, and `watchTimeSeconds`. Blank values are stored as `null`. Use this for platform exports until direct metric API imports are added. ## Performance Insights The Results section includes Performance Insights above the metric forms. This is the first operator-facing summary of what the system has learned. Results also includes a Client Review Snapshot. It is the same structured summary used by the wiki sync and future agent read path. It shows readiness status, top qualified score, platform snapshot count, and the current number of open actions. The API also exposes a client agent context bundle at `/api/clients/<client-id>/agent-context`. This is for future agent work and includes the profile, accounts, campaigns, drafts, scheduled posts, sources, feeds, lessons, performance report, review snapshot, and the current rule that publishing still requires human approval. Results also includes Theme Learning. This is the performance-learning brain for profile themes. It looks at draft topics, audiences, hook types, expected results, metric snapshots, saved lessons, and protected profile guardrails. Each theme is marked as: - Strengthen: performance evidence supports using the theme more often when sources fit. - Demote: weak metrics or negative lessons say to use the theme less often or retest it with a different hook. - Flag: protected guardrails, forbidden claims, or risky memory that should stay visible for review. - Observe: keep the theme available until more evidence exists. Theme Learning never deletes client profile content automatically. It only changes how operators and future agents should prioritize or review themes. Edit the profile manually if a human decides something should be removed. Results also includes Style Learning. It compares posting-output styles `alpha`, `beta`, and `gamma` from scheduled post metrics and shows which style is recommended, strengthened, demoted, or still being observed. The draft agent receives this style evidence, and posting-output artifact creation can use the recommended style when enough measured evidence exists. Operators can still override the style in Content. Results also includes Prompt & Profile Proposals. Click Create proposal from results after metrics or lessons exist to turn the current performance report into an editable advisory proposal. Review all client recommendations scans authorized clients with style-example metrics and lists clients with actionable strengthen or avoid evidence; use Create proposal on a row only when you want to generate a normal reviewable proposal for that client. The app writes a durable proposal record and, on local writable filesystems, a Markdown proposal under `docs/Posting Output/proposals/`. The proposal card shows the recommended style, recommended style example, exact examples to allow or avoid, strengthened themes, weak themes, style metric snapshots, style-example metric snapshots, top posts, and affected profile or prompt fields. Click Open preference controls on a style-example recommendation to jump to that exact example in Content, where you can Allow, Avoid, or return it to Neutral. Use the filter buttons to scan all, pending, accepted, applied, or dismissed proposal history. Edit the summary or proposed-change JSON if needed, then Save edits, Accept, or Dismiss. The Prompt & Profile Proposals section starts with Style Review Readiness. It tells whether the selected client has enough measured style-example evidence, whether pending or accepted proposals already need review, and the safest next action. It also shows the hosted style-review smoke command for the selected client. The command verifies the protected production review path and dismisses its own proposal unless you explicitly keep or apply it. Internal smoke clients also show a `--seed-evidence` command that can create one fresh review artifact when needed and add one smoke metric snapshot when scheduled smoke posts already exist. This seed path is blocked for real clients; real clients need real post metrics. Accepted proposals still do not immediately change the client. To apply one: 1. Click Preview apply changes. 2. Review the exact fields, before values, additions, and after values. 3. If the preview is right, click Apply accepted proposal. Applying a proposal writes only the reviewed client profile and prompt-setting changes, then marks the proposal Applied. If the proposal recommends exact style examples, the preview shows the allowed or avoided example IDs before they are written into client prompt settings. It does not schedule, comment, publish, or delete historical profile knowledge. To manually adjust applied prompt guidance later: 1. Go to Clients. 2. Open Client Profile & Voice. 3. Edit Recommended posting style or Prompt notes. 4. Click Update profile. Click Sync agent context to write that full bundle into: ```text wiki/wiki/clients/<client-name>/agent-context.md ``` Use this page when reviewing what a future agent would know about the client. It includes a readable summary and a machine-readable JSON block for handoff/export. Results also includes Agent Recommendations. These are deterministic next-action suggestions from the current client context, such as reviewing a source, capturing metrics, saving a lesson, creating a campaign draft, or scheduling an approved draft. They are advisory only. They do not post, comment, schedule, or change source status without a human operator. Results also includes Helpful Answer Draft. Paste a real question or comment, optionally add the source URL, and click Draft helpful answer. The app uses non-blocked client source memory to prepare a practical reply for operator review. It records `helpful_answer_drafted` in the audit log, but it does not publish, comment, schedule, or contact any platform. Results also includes Cross-Account Opportunities. This compares the selected client's active social accounts with other authorized clients' scheduled posts and shows possible review items when audiences, offers, or topics overlap. It is advisory only. It does not comment, share, amplify, schedule, or contact a platform. Get explicit approval from both client contexts before acting on any opportunity. Use Accept or Dismiss on a recommendation to record the operator decision in the Recommendation Review Log. This is an audit trail only. Accepting a recommendation does not execute it, schedule a post, change source status, or contact any platform. When a recommendation has already been reviewed, the list shows the latest decision, reviewer, and time so operators and future agents can see what happened without opening the audit log first. Dismissed recommendations move out of the active recommendation list. They remain visible in the Recommendation Review Log and in the reviewed recommendation history that can be synced to the wiki. Click Sync recommendations to write the current recommendation brief into: ```text wiki/wiki/clients/<client-name>/agent-recommendations.md ``` Use this note in Obsidian for planning and team review. It is not an execution queue. Results also includes an Operator Brief. It summarizes the current action load across setup, publishing, source memory, and measurement so a client review can start with the highest-priority blocker instead of scanning every list. Results also includes Content Mix. It shows scheduled coverage by mapped social account and draft/schedule coverage by campaign, which helps spot platform imbalance or campaigns that are not moving into the schedule. Results also includes Autonomy Readiness. It classifies the selected client as manual setup required, manual review required, draft assistance only, measurement attention needed, or candidate for assisted scheduling. This is advisory only; publishing remains human-approved. It shows: - top qualified engagement score - average qualified engagement score - best platform so far - campaign performance summaries with scheduled post count, metric count, average qualified score, and top score - ranked posts by topic, platform, hook type, window, and score - theme learning for what to strengthen, demote, flag, or keep observing - next actions such as missing metric windows or lessons to save Source Quality ranks source records by how they perform downstream. It looks at source-backed drafts, approvals, scheduled posts, metric snapshots, and saved lessons, then suggests whether to Promote, Monitor, Measure, Review, or leave a source Unused. These are advisory trust recommendations only. They do not automatically change source status or trust score. Use campaign performance to compare content sprints, not just individual posts. Use the top-post list to understand which hook and platform drove the result. The report is only as good as the metric snapshots and lessons entered, so keep the 24h and 7d windows current when possible. Click Sync report to wiki after meaningful metric or lesson updates. This writes the current performance summary to: ```text wiki/wiki/clients/<client-name>/performance-report.md ``` Use this report in Obsidian when reviewing progress with a client or preparing future campaign recommendations. Click Sync review snapshot when you want a broader meeting-ready client note. This writes the operator brief, autonomy readiness, content mix, performance summary, and open actions to: ```text wiki/wiki/clients/<client-name>/client-review-snapshot.md ``` Use the review snapshot before client check-ins or internal planning sessions. The performance report is narrower and metric-focused; the review snapshot is better for deciding what the operator or future agent should do next. ## Lessons Learned Lessons tell future drafting agents what worked and what to try next. 1. Go to Results. 2. Under Lesson Learned, select the scheduled post. 3. Select the result window. 4. Add the qualified score if known. 5. Write the lesson. 6. Click Save lesson. Good lessons are short and concrete. Example: ```text Mistake-led hooks got useful contractor replies. Try another mistake hook, but use a more direct CTA. ``` Saved lessons are stored in the database and appended to the client's wiki memory at: ```text wiki/wiki/clients/<client-name>/lessons.md ``` ## Current Limits - Publishing credentials are optional for setup but required for scheduling. - Metrics are manual entry for now. - Draft generation uses the deterministic fallback unless the OpenAI draft provider is configured. - The app is still pre-production. Clerk auth, tenant route guards, route-level role groups, audit coverage, hosted smoke, authenticated persistence smoke harness, database-backed rate-limit foundations, and the renderer-by-renderer XSS review manifest are in place. Public deployment still needs final Clerk organization/domain review and Atlas network hardening as described in `docs/security-audit.md`. - Helpful answer drafting is live as an approval-gated operator workflow only. Automated question discovery, comments, and replies are not live yet. Future comment workflows should draft useful replies for human approval and avoid unsolicited mass replies. ## Operating Rules - Keep human approval on until autonomous mode is intentionally designed and tested. - Do not treat reach alone as success. - Prefer source-backed, client-specific posts. - Update client voice and forbidden claims before generating drafts for a new client. - Record lessons after metrics so the source-to-results loop has useful evidence. - Treat account safety as a hard gate, not a suggestion. Do not bypass it to chase short-term volume.