Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 19 additions & 62 deletions .github/workflows/publish-release-notes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Update> 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 <Update> 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:
Expand All @@ -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
Expand Down Expand Up @@ -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 `<Update>` 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.
Expand Down Expand Up @@ -174,24 +168,22 @@ jobs:
RELEASE_URLS: ${{ inputs.release_urls }}
run: |
set -euo pipefail
run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
body=$(cat <<EOF
Customer-facing release notes generated from:

${RELEASE_URLS}

Review the rendered diff. **To publish, approve the \`docs-release\` environment on [the workflow run](${run_url})** — that merges this PR to \`main\` and Mintlify deploys to docs.fluso.ai.
**Review the rendered diff and merge to publish.** \`main\` requires an approving review, so your review is the gate — merging deploys to docs.fluso.ai and DMs you the published notes to forward.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)
url=$(gh pr create --base main --head "${{ steps.prep.outputs.branch }}" \
--title "docs: release notes" --body "$body")
echo "pr_url=${url}" >> "$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 }}
Expand All @@ -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"')"
56 changes: 56 additions & 0 deletions .github/workflows/release-notes-published.yml
Original file line number Diff line number Diff line change
@@ -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 <Update> block (top of the file).
awk '/<Update /{f=1} f{print} /<\/Update>/{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 <Update>/</Update> 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 <Update> 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"')"
14 changes: 14 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<Update>` 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 `<Update>` 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.
16 changes: 8 additions & 8 deletions release-notes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,38 @@ 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.
- Telegram chats are now labelled in the sidebar so you can tell sources apart at a glance.

**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.

</Update>

<Update label="2026-06-04" description="Desktop 1.0.8" tags={["Desktop"]}>

**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.
Expand All @@ -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**
Expand Down
Loading