Skip to content

Commit 9fd3bf8

Browse files
committed
docs: wire the terminology section through, and add a scheduled brand-sync review
Extend the brand-MCP consolidation to the brand guide's new Names & terminology section, and make "keep the Vale mirror in sync" an automated process instead of a comment: - STYLE-GUIDE.md: route naming questions (canonical names, preferred terms, retired names) to Names & terminology; drop the Preferred terminology table it duplicated; document the sync manifest and workflow under Automated checks. - AGENTS.md: name the terminology section explicitly and rewrite the Naming bullet around the retired-names table. - glow-up: load terminology alongside voice and writing-style. - styles/Pulumi/BRAND-SYNC.yaml: manifest mapping each mirrored Vale rule to the brand section it tracks, with last_synced. - .github/workflows/brand-style-sync.yml + brand-vale-sync skill: weekly drift check of the mirror against the live brand MCP server (retired names first). Drift -> draft PR with a guide-says/mirror-said/now audit trail; no drift -> last_synced bump. Fails loudly if the MCP is unreachable rather than syncing from memory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KpCy5B47c2oNqEeX1Znwx
1 parent 11b2436 commit 9fd3bf8

6 files changed

Lines changed: 225 additions & 18 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
name: brand-vale-sync
3+
description: Weekly drift check of the offline Vale mirror (styles/Pulumi/) against the Pulumi brand guide served by the brand MCP server, with deprecated/retired terms as the priority. Opens a draft PR when the mirror has fallen behind; updates only the sync manifest when it hasn't. Invoked by the brand-style-sync workflow; also user-invocable for an on-demand check.
4+
---
5+
6+
# Brand → Vale sync review
7+
8+
The Vale rules under `styles/Pulumi/` are an **offline mirror** of the
9+
mechanically enforceable subset of the Pulumi brand guide. The brand guide —
10+
served by the **`pulumi-brand` MCP server** (`https://brand.pulumi.com/mcp`) —
11+
is the source of truth; the mirror only follows. Your job: detect where the
12+
mirror has drifted behind the guide, and open a PR that catches it up.
13+
14+
**If the brand MCP server is unreachable, stop and fail loudly.** Do not
15+
guess at the guide's contents from memory or from cached prose in this repo —
16+
a sync against a hallucinated source is worse than no sync.
17+
18+
## Scope
19+
20+
`styles/Pulumi/BRAND-SYNC.yaml` is the manifest: it maps each mirrored Vale
21+
rule to the brand section and subsection it tracks, and records `last_synced`.
22+
Rules **not** listed there (AI-drafting tells, Hugo mechanics, repo
23+
conventions) are repo-owned — never "sync" them against the guide, and never
24+
edit the brand guide side of anything (that's `pulumi/marketing-web`).
25+
26+
## Process
27+
28+
1. **Load the manifest** (`styles/Pulumi/BRAND-SYNC.yaml`).
29+
1. **Pull each brand section it references** via the MCP server:
30+
`get_guidelines({section: "terminology"})`, `writing-style`, and `voice`.
31+
1. **Compare, rule by rule.** For each manifest entry, read the Vale rule file
32+
and check the guide content it mirrors. You are looking for:
33+
- **Retired terms the mirror doesn't know** — a row in the terminology
34+
section's "Retired and disallowed names" table with no corresponding
35+
entry in `Substitutions.yml` (single fixed replacement) or
36+
`DeprecatedProductNames.yml` (context-dependent replacement). This is the
37+
highest-value check: renamed products rot fastest.
38+
- **Renamed or re-cased canonical names** — a "Product names" row that
39+
`Nomenclature.yml` mis-canonicalizes or misses.
40+
- **Mirror entries the guide no longer supports** — a swap or token whose
41+
brand rule was changed or dropped. Flag these for removal.
42+
- **Stale rule `message:`/`link:` text** that misquotes the guide.
43+
1. **Judge before you write.** The mirror is deliberately narrower than the
44+
guide: only near-zero-false-positive, mechanically checkable rules belong
45+
in it (see the admission criteria in
46+
`.claude/commands/docs-review/scripts/vale-deterministic-fixes.yaml`).
47+
A guide rule with no safe regex (e.g. "runtime code" → "function
48+
serialization", where *runtime* has too many live meanings) is **correctly
49+
absent** — note it in the PR body as intentionally unmirrored rather than
50+
forcing a noisy rule. When adding a retired name, decide the tier:
51+
- single fixed replacement → `Substitutions.yml` (auto-fixable, blocker)
52+
- context-dependent replacement → `DeprecatedProductNames.yml` (flag-only)
53+
1. **Validate.** Run Vale (`make lint-prose ARGS=<a couple of touched content
54+
files>` or `vale` on a scratch fixture exercising each new/changed token,
55+
positive and negative cases) to prove the rules compile and match as
56+
intended. Run `make lint`.
57+
1. **Report.**
58+
- **Drift found:** update the rule files and `BRAND-SYNC.yaml`
59+
(`last_synced` + any mapping changes), and open a **draft PR** titled
60+
`vale: sync brand-guide mirror (<date>)`. The body must list every
61+
change as *guide says X → mirror said Y → now Z*, plus the
62+
intentionally-unmirrored notes. Draft, not ready: tier placement
63+
(blocker vs. advisory) is a human call.
64+
- **No drift:** commit only the `last_synced` bump in `BRAND-SYNC.yaml`
65+
directly to a PR the same way (a one-line draft PR is fine and cheap to
66+
merge), or if invoked interactively, just report "in sync".
67+
- Never push to `master` directly.

.claude/commands/glow-up.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The `file-path` argument is optional. If not provided, the command will attempt
1414

1515
## Requires the `pulumi-brand` MCP server
1616

17-
This skill delegates **all** voice, tone, prose, terminology, grammar, and naming judgment to the Pulumi brand guide served by the **`pulumi-brand` MCP server** (`https://brand.pulumi.com/mcp`). It deliberately keeps no local copy of those rules. Before analyzing anything, confirm the server is reachable and load its voice and writing-style guidance. **If you can't reach it, stop and tell the user the brand guide is unavailable — do not fall back to your own notions of Pulumi style.**
17+
This skill delegates **all** voice, tone, prose, terminology, grammar, and naming judgment to the Pulumi brand guide served by the **`pulumi-brand` MCP server** (`https://brand.pulumi.com/mcp`). It deliberately keeps no local copy of those rules. Before analyzing anything, confirm the server is reachable and load its voice, writing-style, and terminology guidance. **If you can't reach it, stop and tell the user the brand guide is unavailable — do not fall back to your own notions of Pulumi style.**
1818

1919
---
2020

@@ -45,7 +45,7 @@ Read the entire target file and perform comprehensive analysis.
4545

4646
#### Text analysis
4747

48-
Judge the prose against the **brand guide's voice and writing-style sections** (brand.pulumi.com, also exposed through the brand MCP server) — the source of truth for voice and tone, marketing language and superlatives, inclusive language, terminology and product naming, heading case, link text, lists, paragraph length, and grammar. Consult them and flag anything that violates them, quoting the offending line. Don't re-derive those rules here.
48+
Judge the prose against the **brand guide's voice, writing-style, and terminology sections** (brand.pulumi.com, also exposed through the brand MCP server) — the source of truth for voice and tone, marketing language and superlatives, inclusive language, product/feature naming and the retired-names table, heading case, link text, lists, paragraph length, and grammar. Consult them and flag anything that violates them, quoting the offending line. Don't re-derive those rules here.
4949

5050
Then flag the file-specific issues the brand guide doesn't own:
5151

@@ -135,7 +135,7 @@ These references represent current branding standards. Use them to:
135135

136136
Before proposing changes, verify understanding of:
137137

138-
- The brand guide's voice and writing-style sections (brand.pulumi.com, also exposed through the brand MCP server) — voice, prose, terminology, grammar, and naming (the source of truth)
138+
- The brand guide's voice, writing-style, and terminology sections (brand.pulumi.com, also exposed through the brand MCP server) — voice, prose, grammar, and product/feature naming including retired names (the source of truth)
139139
- `STYLE-GUIDE.md` — this site's Hugo/repo mechanics (shortcodes, links, code fences, navigation)
140140
- `AGENTS.md` — Repository conventions and build workflow
141141
- Google Developer Documentation Style Guide — for topics covered by none of the above
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: "Scheduled jobs: Brand style sync"
2+
3+
# Weekly drift check of the offline Vale mirror (styles/Pulumi/) against the
4+
# Pulumi brand guide, with retired/deprecated product names as the priority.
5+
# Vale can't call the brand MCP at lint time, so this job is what keeps the
6+
# mirror honest: it re-reads the brand sections each mirrored rule tracks
7+
# (per styles/Pulumi/BRAND-SYNC.yaml) and opens a draft PR when they've
8+
# drifted. See .claude/commands/brand-vale-sync/SKILL.md for the process.
9+
on:
10+
schedule:
11+
# Mondays at 14:00 UTC — after the weekend, before the US work week.
12+
- cron: '0 14 * * 1'
13+
workflow_dispatch: null
14+
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
id-token: write # Required for ESC OIDC auth
19+
actions: read
20+
21+
jobs:
22+
sync:
23+
name: Check Vale mirror against brand guide
24+
runs-on: ubuntu-latest
25+
steps:
26+
# ESC runs before checkout so the bot token can authenticate the
27+
# checkout — the PR opened by claude-code-action then goes out as
28+
# pulumi-bot, letting downstream workflows (docs review, etc.) fire.
29+
- name: Fetch secrets from ESC
30+
id: esc-secrets
31+
uses: pulumi/esc-action@v3
32+
- name: Checkout repository
33+
uses: actions/checkout@v7
34+
with:
35+
token: ${{ steps.esc-secrets.outputs.PULUMI_BOT_TOKEN }}
36+
# Binary only — the model runs Vale itself against fixtures/changed
37+
# files while validating rule edits; there's no repo-wide report here.
38+
- name: Install Vale
39+
run: |
40+
curl -sL https://github.com/errata-ai/vale/releases/download/v3.9.4/vale_3.9.4_Linux_64-bit.tar.gz \
41+
| sudo tar xz -C /usr/local/bin vale
42+
vale --version
43+
- name: Run Claude Code
44+
id: claude
45+
uses: anthropics/claude-code-action@v1
46+
with:
47+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
48+
# Bot token so the PR triggers downstream workflows.
49+
github_token: ${{ steps.esc-secrets.outputs.PULUMI_BOT_TOKEN }}
50+
prompt: |
51+
You are running in CI on a schedule.
52+
53+
Follow `.claude/commands/brand-vale-sync/SKILL.md` exactly: check
54+
the offline Vale mirror under `styles/Pulumi/` against the Pulumi
55+
brand guide via the `pulumi-brand` MCP server, prioritizing the
56+
terminology section's "Retired and disallowed names" table.
57+
58+
- If the brand MCP server is unreachable, exit non-zero with a
59+
clear error. Do not sync from memory.
60+
- If the mirror has drifted, fix it and open a **draft** PR on a
61+
branch named `vale/brand-sync-<YYYY-MM-DD>` with the auditable
62+
body the skill describes.
63+
- If nothing drifted, bump `last_synced` in
64+
`styles/Pulumi/BRAND-SYNC.yaml` and open the same draft PR with
65+
just that change.
66+
# The public pulumi-brand MCP server is wired via --mcp-config
67+
# (claude-code-action@v1 has no mcp_config input); its tools are in
68+
# --allowed-tools. No auth: the server is public.
69+
claude_args: |
70+
--model claude-opus-5 --effort low
71+
--mcp-config '{"mcpServers": {"pulumi-brand": {"type": "http", "url": "https://brand.pulumi.com/mcp"}}}'
72+
--allowed-tools "Read,Write,Edit,Glob,Grep,Agent,WebFetch,mcp__pulumi-brand__get_guidelines,mcp__pulumi-brand__search_guidelines,Bash(make lint:*),Bash(make lint-prose:*),Bash(vale:*),Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr list:*),Bash(gh search:*),Bash(gh api:*),Bash(git:*),Bash(cat:*),Bash(head:*),Bash(tail:*),Bash(wc:*),Bash(ls:*),Bash(grep:*),Bash(find:*),Bash(rg:*),Bash(sed:*),Bash(awk:*),Bash(jq:*),Bash(diff:*),Bash(echo:*),Bash(printf:*),Bash(tee:*),Bash(date:*),Bash(test:*),Bash(mkdir:*),Bash(python3 -c:*)"
73+
74+
env:
75+
ESC_ACTION_OIDC_AUTH: true
76+
ESC_ACTION_OIDC_ORGANIZATION: pulumi
77+
ESC_ACTION_OIDC_REQUESTED_TOKEN_TYPE: urn:pulumi:token-type:access_token:organization
78+
ESC_ACTION_ENVIRONMENT: github-secrets/pulumi-docs
79+
ESC_ACTION_EXPORT_ENVIRONMENT_VARIABLES: false

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Do not substitute other tools or commands, or change `package.json` to use pnpm
3131

3232
## Code & Content Rules
3333

34-
For all content files, Pulumi's **voice, tone, prose, product naming, and grammar** are defined in the **Pulumi brand guide** ([brand.pulumi.com](https://brand.pulumi.com/)), which is also exposed to agents through the public **brand MCP server**. Consult the relevant section (voice or writing style) before writing or reviewing. `STYLE-GUIDE.md` covers only this site's Hugo/repo mechanics (shortcodes, links, navigation, code fences, etc.) and points to the brand guide for each topic it doesn't own. If a rule is in neither, fall back to the [Google Developer Documentation Style Guide](https://developers.google.com/style). Do not invent new style conventions; ask for clarification if something is ambiguous.
34+
For all content files, Pulumi's **voice, tone, prose, product naming, and grammar** are defined in the **Pulumi brand guide** ([brand.pulumi.com](https://brand.pulumi.com/)), which is also exposed to agents through the public **brand MCP server**. Consult the relevant section (voice, writing style, or terminology) before writing or reviewing — the **terminology** section is the canonical reference for product/feature names and the retired names never to use again. `STYLE-GUIDE.md` covers only this site's Hugo/repo mechanics (shortcodes, links, navigation, code fences, etc.) and points to the brand guide for each topic it doesn't own. If a rule is in neither, fall back to the [Google Developer Documentation Style Guide](https://developers.google.com/style). Do not invent new style conventions; ask for clarification if something is ambiguous.
3535

3636
**Precedence:** wherever the brand guide overlaps with anything in this repo — these conventions, `STYLE-GUIDE.md`, or any skill (including the social, SEO, and AEO guidance that still lives in this repo), the brand guide takes priority. That specialized guidance stays in the repo for now; if the brand guide later grows its own, the brand guide's version wins.
3737

@@ -58,7 +58,7 @@ For all content files (docs, blogs, tutorials, etc.):
5858
- Code examples go under `/static/programs` with a language suffix in the filename.
5959
- Mirror the structure of existing content; do not invent new layouts.
6060
- **Includes**: Use Hugo shortcodes for shared content, never raw Markdown copy-paste.
61-
- **Naming**: Use lowercase for non-proper nouns (e.g. “stack,” not “Stack”).
61+
- **Naming**: Product, feature, and category names — canonical casing, preferred terms, retired names — come from the brand guide's terminology section. Never introduce a name from memory: check the retired-names table first (e.g. it's Pulumi Discovery now, not “Pulumi Insights”; Pulumi Neo, not “Copilot”). Non-proper nouns stay lowercase (“stack,” not “Stack”).
6262
- **Ordered Lists**: Every item begins with `1.` to minimize diff noise.
6363
- **Diagrams**: Prefer Mermaid diagrams over ASCII art. The site renders Mermaid natively via a Hugo code block hook (`layouts/_default/_markup/render-codeblock-mermaid.html`). Use ` ```mermaid ` fenced code blocks. See [Mermaid docs](https://mermaid.js.org/) for syntax.
6464
- **Images on template-driven pages**: Place new images for template-driven pages (homepage, product pages, event pages, case studies — anything rendered through `layouts/partials/template-partials/*`) under `assets/fingerprinted/`, mirroring the path you'd use under `static/`. The template partials route every `<img>` through `layouts/partials/fingerprinted-img.html`, which content-hashes filenames, converts rasters to WebP, and generates responsive `srcset`s. Frontmatter paths still look like `/images/foo.svg`; the partial resolves them. Missing assets cause a build panic, so there is no silent fallback. `meta_image` and assets used by non-template layouts can stay in `static/`.

0 commit comments

Comments
 (0)