Publishing and external comms — Slack, Gmail, blog, website
What you need: A populated project-state/ substrate with surfaces configured in manifest.yaml.
project-state generates artifacts — status reports, meeting notes, blog posts, milestone summaries. Those artifacts need to reach people. Surfaces are the external systems where artifacts get delivered. Five are supported: Slack, Gmail, Google Calendar, blog (scsiwyg), and project website.
The governing principle across all five: the system does the work of generating the artifact. A human does the work of deciding to send it.
The five surfaces
Each surface is configured in manifest.yaml:
surfaces:
slack:
enabled: false
gmail:
enabled: false
always_draft: true
google_calendar:
enabled: false
blog:
enabled: true
site_slug: "project-state"
site_url: "https://www.scsiwyg.com/project-state"
publication_review_required: false
website:
enabled: true
framework: "nextjs"
hosting: "vercel"
production_url: "https://project-state-docs.vercel.app"
require_review_for_public: false
Surfaces with enabled: false are ignored by the notifier and the orchestrator. Enable them when your project is ready for that channel.
Gmail is always draft
This is a design constraint, not a configuration option. The always_draft: true field exists in the schema, but there is no always_draft: false path in the code. Every email artifact project-state produces lands in your Gmail drafts folder. You review, edit if needed, and press send yourself.
The reason is blast radius. A misconfigured reporting matrix entry or a hallucinated status report is harmless as a draft. Sent to a steering committee, it's a problem. The cost of reviewing a draft is 30 seconds. The cost of retracting a sent email is a conversation nobody wants to have.
When project-state creates a Gmail draft:
Created Gmail draft:
To: jane@acme.com, steering-committee@acme.com
Subject: Weekly Status — 2026-W22
Body: [generated from project-status-reporter]
→ Review in Gmail before sending.
Slack auto-posts
Slack is the exception to the review-before-send rule. Messages post directly to the configured channel. The reasoning: Slack is ephemeral by nature. A status update in a channel is low-stakes — it can be corrected with a follow-up message. The channel is configured in the manifest, so the audience is known and bounded.
surfaces:
slack:
enabled: true
channel: "#project-updates"
When a skill routes an artifact to Slack:
Posted to #project-updates:
Weekly Status — 2026-W22
Phase: 04-release | Health: green
[milestone summary table]
If you want review-before-post on Slack, disable the surface and use Gmail drafts instead.
Blog with audience tiers
The blog surface publishes to scsiwyg. Three visibility levels control who sees what:
| Visibility | Audience | Use case |
|---|---|---|
public | Anyone with the URL | Release notes, documentation, announcements |
journal | Team members only | Weekly status, retrospectives, internal updates |
| Draft (unpublished) | Author only | Work-in-progress, review pending |
The publication_review_required flag in the manifest controls whether skills can publish directly or must create drafts:
blog:
publication_review_required: true # skills create drafts only
publication_review_required: false # skills can publish directly
When review is required, the flow is:
- Skill generates the post content
- Skill creates a draft on scsiwyg
- You review the draft at
scsiwyg.com/project-state/[slug] - You publish when satisfied
When review is not required, the skill publishes immediately. This is useful for internal journal posts (weekly reports) where the overhead of review isn't justified.
Project website
The website surface deploys a Next.js application that renders the substrate as a live reference site. Documents promoted to documents/published/ appear as pages. Milestones, risks, and decisions are accessible through the dashboard views.
website:
enabled: true
framework: "nextjs"
hosting: "vercel"
production_url: "https://project-state-docs.vercel.app"
auto_deploy_on_publish: true
require_review_for_public: false
default_visibility: "public"
The auto_deploy_on_publish flag means that when project-website-publisher generates new pages, they deploy automatically. With require_review_for_public: true, generated pages land as drafts in the website's content directory, and you deploy manually.
The website reads from the same substrate as the kanban dashboard. The difference is audience: the kanban is for the team (localhost), the website is for stakeholders (public URL).
Calendar holds
Google Calendar integration proposes meeting holds — it does not create confirmed events. When the orchestrator identifies an upcoming steering committee meeting or a deadline-driven review:
Proposed calendar hold:
Title: SC Meeting Prep — Q2 Claim Review
When: 2026-07-15 10:00-11:00
Calendar: project-acme
→ Confirm in Google Calendar to finalize.
The hold appears as a tentative event. You confirm, reschedule, or delete it.
The notifier
project-notifier is the central routing skill. It reads the reporting matrix and the manifest's surface configuration to determine where each artifact goes. When a generator skill (like project-status-reporter) produces output, the notifier:
- Reads the matrix entry to find the target surface
- Checks if that surface is enabled in the manifest
- Routes the artifact to the appropriate surface API
- Logs the delivery to
activity.ndjson
The notifier does not generate content. It takes a finished artifact and puts it where the matrix says it should go. If the target surface is disabled, the notifier logs a skip and moves on — no error, no retry.
The pattern across all surfaces
The review model varies by surface, but the architecture is consistent:
- A reporting matrix entry defines what artifact, for which stakeholder, on which surface
- A generator skill produces the artifact content
- The notifier routes it to the surface
- The surface's review model determines whether it goes live immediately or waits for human approval
Gmail always waits. Slack never waits. Blog and website are configurable. Calendar proposes but doesn't confirm.
Next step
Surfaces deliver artifacts to the outside world. But the project also moves through lifecycle phases, and transitions between phases have gates that enforce readiness. Phase transitions and gates shows how the five phase presets work and what happens when a gate blocks your transition.