From 5462feda4a4dd3cdbb7acbaa5d6561dd04701b35 Mon Sep 17 00:00:00 2001 From: biswaroop1547 Date: Sun, 14 Jun 2026 09:45:44 +0200 Subject: [PATCH] docs: release-notes house-style pass, flow doc, publish pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - publish-release-notes.yml: generate one customer entry from pasted release URLs (frontend/backend-aware, deduped, Opus 4.8 effort max), following AGENTS.md voice rules, then open a PR. The workflow never merges — main's ruleset requires an approving review, so your review and merge is the publish gate. - release-notes-published.yml: on merge to main, DM the published notes (Slack-formatted) so you can forward them to the prem-app channel. - release-notes.mdx: trim punchy em dashes per the house style. - AGENTS.md: document the publishing flow. Co-Authored-By: Claude Fable 5 --- .github/workflows/publish-release-notes.yml | 81 +++++-------------- .github/workflows/release-notes-published.yml | 56 +++++++++++++ AGENTS.md | 14 ++++ release-notes.mdx | 16 ++-- 4 files changed, 97 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/release-notes-published.yml diff --git a/.github/workflows/publish-release-notes.yml b/.github/workflows/publish-release-notes.yml index 61ecb89..b5877e7 100644 --- a/.github/workflows/publish-release-notes.yml +++ b/.github/workflows/publish-release-notes.yml @@ -2,27 +2,22 @@ name: Publish release notes # Turns engineering GitHub release notes into customer-facing release notes on # docs.fluso.ai. You paste one or more release URLs; Claude (the `release-notes` -# skill from premAI-io/fluso-development-skills) rewrites them into a single -# Mintlify entry, opens a PR, and DMs you on Slack. Approving the -# `docs-release` environment on the run merges the PR to main and Mintlify -# deploys. +# skill) rewrites them into ONE Mintlify entry and opens a PR. +# +# Review and merge that PR to publish. `main` requires an approving review from +# someone other than the last pusher (branch ruleset), so your review IS the +# gate — the workflow never merges. When the PR merges, the companion workflow +# `release-notes-published.yml` DMs you the published notes to forward. # # ── Required secrets ───────────────────────────────────────────────────────── -# CLAUDE_CODE_OAUTH_TOKEN Claude Code action auth (same token as other repos). +# CLAUDE_CODE_OAUTH_TOKEN Claude Code action auth. # SOURCE_RELEASES_PAT PAT with read access to the private source repos # (fluso-frontend, premapp-backend, chronograph, …) -# AND to fluso-development-skills. Used only to fetch -# release bodies and clone the skill. +# and to fluso-development-skills. # SLACK_BOT_TOKEN Slack bot token (xoxb-…) with chat:write. Optional — -# if unset, the Slack steps no-op and publishing still -# works. -# ── Required variables ─────────────────────────────────────────────────────── -# SLACK_RELEASE_DM_TARGET Slack member ID to DM (e.g. U0123ABCD), or a channel -# ID. Optional alongside SLACK_BOT_TOKEN. -# ── One-time setup (IMPORTANT) ─────────────────────────────────────────────── -# Settings → Environments → create `docs-release` and add a Required reviewer. -# That reviewer approval IS the publish gate. If the environment has no -# required reviewer, the merge is NOT gated and happens automatically. +# if unset, the Slack step no-ops. +# ── Required variable ──────────────────────────────────────────────────────── +# SLACK_RELEASE_DM_TARGET Slack member ID to DM (e.g. U0123ABCD). on: workflow_dispatch: @@ -48,9 +43,6 @@ jobs: pull-requests: write id-token: write actions: read - outputs: - pr_number: ${{ steps.pr.outputs.pr_number }} - pr_url: ${{ steps.pr.outputs.pr_url }} steps: - name: Checkout docs uses: actions/checkout@v6 @@ -120,6 +112,8 @@ jobs: - `.claude/skills/release-notes/references/release-notes-playbook.md` Read both before writing anything. They define the customer voice, the repo→audience mapping, the theme taxonomy, the combine-vs-separate rules, and the exact Mintlify `` output contract. Do not deviate from them. + Also read this repository's `AGENTS.md` and follow its voice rules: banned vocabulary (seamless, robust, leverage, unlock, empower, transform, crucial, …), sentence-case labels, straight quotes, em dashes sparingly, and no emojis in body text. + INPUTS — already fetched for you (do not re-fetch): - `.release-input/manifest.json` — an array of the source releases, each with `owner`, `repo`, `tag`, `name`, `published` (date), `url`, and `body_file`. - Each `body_file` holds the raw engineering release notes for one source release. @@ -174,13 +168,12 @@ jobs: RELEASE_URLS: ${{ inputs.release_urls }} run: | set -euo pipefail - run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" body=$(cat <> "$GITHUB_OUTPUT" - echo "pr_number=$(gh pr view "$url" --json number --jq .number)" >> "$GITHUB_OUTPUT" echo "Opened ${url}" - - name: Slack DM — ready to confirm + - name: Slack DM — ready to review if: always() && steps.pr.outputs.pr_url != '' env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} @@ -202,45 +194,10 @@ jobs: echo "Slack not configured (SLACK_BOT_TOKEN / SLACK_RELEASE_DM_TARGET) — skipping DM." exit 0 fi - run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - text=$(printf '📝 *Release notes ready to publish*\n\n• Review: %s\n• Approve to publish: %s\n\nApprove the docs-release environment on the run to merge to main and deploy to docs.fluso.ai.' \ - "${{ steps.pr.outputs.pr_url }}" "$run_url") - payload=$(jq -n --arg ch "$TARGET" --arg text "$text" '{channel:$ch, text:$text}') + text=$(printf '📝 *Release notes ready*\n\nReview and merge to publish: %s\n\nMerging deploys to docs.fluso.ai, and the published notes come back here for you to forward.' \ + "${{ steps.pr.outputs.pr_url }}") + payload=$(jq -n --arg ch "$TARGET" --arg text "$text" '{channel:$ch, text:$text, unfurl_links:false}') resp=$(curl -sS -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \ -H "Content-type: application/json; charset=utf-8" --data "$payload") - echo "$resp" | jq -e '.ok' >/dev/null || { echo "::warning::Slack DM failed: $(echo "$resp" | jq -r '.error // "unknown"')"; } - - publish: - needs: draft - if: needs.draft.outputs.pr_number != '' - runs-on: ubuntu-latest - environment: docs-release - permissions: - contents: write - pull-requests: write - steps: - - name: Merge PR to main - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euo pipefail - gh pr merge "${{ needs.draft.outputs.pr_number }}" \ - -R "${{ github.repository }}" --squash --delete-branch - - - name: Slack DM — published - if: success() - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - TARGET: ${{ vars.SLACK_RELEASE_DM_TARGET }} - run: | - set -euo pipefail - if [ -z "${SLACK_BOT_TOKEN:-}" ] || [ -z "${TARGET:-}" ]; then - echo "Slack not configured — skipping." - exit 0 - fi - text=$(printf '✅ Release notes published to docs.fluso.ai (PR #%s merged).' "${{ needs.draft.outputs.pr_number }}") - payload=$(jq -n --arg ch "$TARGET" --arg text "$text" '{channel:$ch, text:$text}') - curl -sS -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \ - -H "Content-type: application/json; charset=utf-8" --data "$payload" >/dev/null || true + echo "$resp" | jq -e '.ok' >/dev/null || echo "::warning::Slack DM failed: $(echo "$resp" | jq -r '.error // "unknown"')" diff --git a/.github/workflows/release-notes-published.yml b/.github/workflows/release-notes-published.yml new file mode 100644 index 0000000..d77d0d1 --- /dev/null +++ b/.github/workflows/release-notes-published.yml @@ -0,0 +1,56 @@ +name: Release notes published + +# Fires when release-notes.mdx lands on main (i.e. you merged a release-notes +# PR). DMs the newest published entry, formatted for Slack, so you can forward +# it to the prem-app channel if you choose. +# +# Uses SLACK_BOT_TOKEN + SLACK_RELEASE_DM_TARGET (same as publish-release-notes). +# No-ops if Slack isn't configured. + +on: + push: + branches: [main] + paths: ["release-notes.mdx"] + +concurrency: + group: release-notes-published + cancel-in-progress: false + +jobs: + dm: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: DM the published notes + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + TARGET: ${{ vars.SLACK_RELEASE_DM_TARGET }} + run: | + set -euo pipefail + if [ -z "${SLACK_BOT_TOKEN:-}" ] || [ -z "${TARGET:-}" ]; then + echo "Slack not configured — skipping." + exit 0 + fi + # Take the newest block (top of the file). + awk '//{if(f){exit}}' release-notes.mdx > /tmp/entry.mdx + label=$(grep -oE 'label="[^"]*"' /tmp/entry.mdx | head -1 | sed -E 's/label="(.*)"/\1/' || true) + desc=$(grep -oE 'description="[^"]*"' /tmp/entry.mdx | head -1 | sed -E 's/description="(.*)"/\1/' || true) + # Strip the / lines; convert **bold**->*bold* and "- "->"• " for Slack mrkdwn. + body=$(sed '1d;$d' /tmp/entry.mdx | sed -E 's/\*\*([^*]+)\*\*/*\1*/g; s/^- /• /') + if [ -z "$body" ]; then + echo "No entry found — skipping." + exit 0 + fi + payload=$(jq -n --arg ch "$TARGET" --arg label "$label" --arg desc "$desc" --arg body "$body" ' + {channel: $ch, unfurl_links: false, + text: ("✅ *Published: " + $desc + "* (" + $label + ")\nLive at https://docs.fluso.ai/release-notes\n\n" + + $body + + "\n\n_Forward to the prem-app channel if you want to share it._")}') + resp=$(curl -sS -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \ + -H "Content-type: application/json; charset=utf-8" --data "$payload") + echo "$resp" | jq -e '.ok' >/dev/null || echo "::warning::Slack DM failed: $(echo "$resp" | jq -r '.error // "unknown"')" diff --git a/AGENTS.md b/AGENTS.md index 643db26..4810322 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,3 +80,17 @@ The docs follow Wikipedia's "Signs of AI writing" guide. The bans below aren't s - Never invent feature behaviour. If a capability isn't documented in source materials, leave it out. - Always pair "Fluso can send X" with the approval safety note: drafts are shown for review. - For product actions, point users to the macOS download at `https://fluso.ai/` and to support at `support@premai.io`. Don't link to `app.fluso.ai`. Fluso is a desktop app. + +## Publishing release notes + +Customer release notes live on `/release-notes` (`release-notes.mdx`) as a stack of Mintlify `` blocks, newest first. They are published through a workflow, not edited by hand. + +The flow: + +1. **Actions → Publish release notes → Run workflow.** Paste one or more GitHub release URLs. List a desktop release and the backend cycle behind it together to publish them as one note. +2. The workflow fetches each release body, loads the `release-notes` skill from [`fluso-development-skills`](https://github.com/premAI-io/fluso-development-skills), and has Claude rewrite them into one `` entry: frontend-led and version-labelled, backend folded into themes, deduped, customer voice, engineering detail removed. It follows this file's voice rules. +3. The workflow opens a PR with that diff and sends a Slack DM with the link. +4. **Review and merge the PR to publish.** `main` requires an approving review from someone other than the last pusher, so your review is the gate. Merging deploys to docs.fluso.ai. +5. The companion workflow `release-notes-published.yml` then DMs you the published notes, formatted to forward to the prem-app channel if you choose. + +Claude writes the entry and opens the PR; it never merges. Your review and merge is the gate, enforced by the branch ruleset. The skill (`SKILL.md` and `references/release-notes-playbook.md`) is the source of truth for how releases map to customer voice and when to combine frontend and backend. diff --git a/release-notes.mdx b/release-notes.mdx index fb80d8c..147a5b8 100644 --- a/release-notes.mdx +++ b/release-notes.mdx @@ -11,9 +11,9 @@ description: "What's new in Fluso — product updates, improvements, and fixes." - The assistant got noticeably smarter at research, drafting, and visuals. **Polish & experience** -- Normalised typography, spacing, and layout across the whole app — sidebars, headers, buttons, cards, and empty states all feel more consistent. +- Normalised typography, spacing, and layout across the whole app. Sidebars, headers, buttons, cards, and empty states all feel more consistent. - A clearer step-details panel in the work log. -- On macOS, the window frame now follows your light/dark theme — no more dark strip at the top on launch. +- On macOS, the window frame now follows your light/dark theme. No more dark strip at the top on launch. **Find things faster** - Search past conversations from the sidebar, with matches highlighted. @@ -21,13 +21,13 @@ description: "What's new in Fluso — product updates, improvements, and fixes." **Smarter assistant** - Deep Research asks a clarifying question when your request is ambiguous instead of guessing, and uses refreshed web-search connectors. -- Draft emails and Slack messages get an automatic polish pass so they read like a person wrote them — before you approve and send. +- Draft emails and Slack messages get an automatic polish pass before you approve and send, so they read like a person wrote them. - Slide decks use richer visuals for pitch and brand decks, while data-heavy decks stay clean. - Sharper image generation, now powered by GPT-5.4 Image 2. **Reliability, privacy & trust** - Backend services now run in the EU region for European users. -- Fewer noisy banners — the "Technical Issue" banner only appears when something user-facing is genuinely broken. +- Fewer noisy banners: the "Technical Issue" banner only appears when something user-facing is genuinely broken. - Security hardening across the app from a recent external review. @@ -35,14 +35,14 @@ description: "What's new in Fluso — product updates, improvements, and fixes." **Highlights** -- The app updates itself now — new versions install quietly in the background. -- Drop your connection mid-answer and the assistant picks back up — nothing lost. +- The app updates itself now. New versions install quietly in the background. +- Drop your connection mid-answer and the assistant picks back up, with nothing lost. - Syncs recover on their own instead of getting stuck. **Updates & installation** - Background auto-updates: once you're on 1.0.8+, new builds install on their own. A sidebar dot shows when one is ready, and Settings has a "Check for updates" button. - Windows and Linux now use the same clean, frameless window style as macOS. -- Windows builds are properly signed — no more "unknown publisher" warning — and the taskbar shows the Fluso icon. +- Windows builds are properly signed (no more "unknown publisher" warning), and the taskbar shows the Fluso icon. **Connectors & sync** - Gmail and Slack syncs recover on their own from rate limits and hiccups. If a Gmail connection truly expires, you're clearly prompted to reconnect. @@ -55,7 +55,7 @@ description: "What's new in Fluso — product updates, improvements, and fixes." - The "Worked for X seconds" timer is honest now, and empty voice notes no longer break the conversation. **Plans & onboarding** -- Free and Sponsored Pro plan limits were raised — more headroom before you hit a cap. +- Free and Sponsored Pro plan limits were raised, with more headroom before you hit a cap. - The name, role, and preferences you set during onboarding now carry across the whole app. **Reliability & offline**