Skip to content
Closed
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
5 changes: 5 additions & 0 deletions .claude/skills/docs-from-code/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ Input: a feature — a PR number, or a code area / config key.
docs repo, never add it to `.gitignore` (keep it in the scratch dir).
- Document the user-facing contract, not implementation details. Code is the
source of truth for *what is true*, not for *how to say it*.
- **The clone is private. Nothing that identifies it may reach the docs** — no
`Mergifyio/monorepo` references, no `mergify_engine/...` paths, no internal
module or function names, no `file:line` citations. Cite the code in your
*report* to the user, never in the page. See `proofread-leaks` and the
"Never Publish Internal Information" section of AGENTS.md.
- When code and a doc disagree, the code wins for facts (defaults, enums,
behavior) — but if you cannot tell whether a difference is intentional, flag it
rather than "fixing" it.
Expand Down
3 changes: 3 additions & 0 deletions .claude/skills/docs-gap-analysis/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ Create a todo for each step.
target.
- Don't flag internal/refactor PRs as doc gaps. Only user-facing capability
changes count.
- The report is internal, the docs are not. Linear IDs, monorepo paths, and
customer names belong in the report and must never survive into a page written
from it — see `proofread-leaks`.
- Be honest about uncertainty: if you can't tell whether something is documented,
say "needs review" rather than asserting a gap.
- The output is a plan, not edits. To actually write a page, hand the item to
Expand Down
19 changes: 13 additions & 6 deletions .claude/skills/document-a-feature/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ Identify the source of truth for the feature:
Establish: what the feature does, who uses it, the exact config/CLI/API surface,
and any plan/tier gating.

Every one of these sources is internal. Take the *behavior* from them and leave
the *provenance* behind: no ticket or Linear IDs, no customer or org names, no
monorepo paths, no internal links. Read the "Never Publish Internal Information"
section of AGENTS.md before you write a line.

## Step 2 — Place the page

Read `references/placement-guide.md` for the full section map and decision rules.
Expand Down Expand Up @@ -106,13 +111,15 @@ exact snippets.

Run these before claiming the page is done:

1. **Proofread pipeline** — if total changed/added docs lines ≥ 10, spawn the 4
proofread subagents in parallel per the repo CLAUDE.md (`proofread-style`,
`proofread-technical`, `proofread-structure`, `proofread-consistency`) on the
diff.
2. **Config examples** — if the page contains any YAML/`.mergify.yml` snippets,
1. **Leak check** — always, whatever the diff size: run
`pnpm check:internal-leaks` and the **proofread-leaks** subagent on the diff.
2. **Proofread pipeline** — if total changed/added docs lines ≥ 10, spawn the
other 4 proofread subagents in parallel per the repo CLAUDE.md
(`proofread-style`, `proofread-technical`, `proofread-structure`,
`proofread-consistency`) on the diff.
3. **Config examples** — if the page contains any YAML/`.mergify.yml` snippets,
invoke the **validate-config-examples** skill.
3. **Build check** — run `pnpm check` (astro check + eslint + biome). Fix any
4. **Build check** — run `pnpm check` (astro check + eslint + biome). Fix any
errors. For a final SSG sanity check, `pnpm build`.

## Hard rules
Expand Down
202 changes: 202 additions & 0 deletions .claude/skills/proofread-leaks/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
name: proofread-leaks
description: >-
Proofread documentation changes for leaked internal
information. Catches support ticket and thread IDs,
customer and org names, private repo paths, internal
URLs and dashboards, and credentials that came in
from the source material a page was written from.
Designed to run as a subagent on diffs of MDX files.
---

# Proofread: Internal Information Leaks

You are a proofreading subagent. Your job is to make
sure nothing internal ended up in published
documentation.

Docs are usually written *from* internal material: a
support case, a private PR, an engine source file, a
Linear ticket. That material travels with the draft.
The reader never needs to know where a page came
from, so anything that only describes the *provenance*
of a doc is a leak, not context.

This check is different from the other proofreaders in
two ways: it runs on **every** docs change regardless
of size, and it covers **code blocks, comments,
frontmatter, alt text, and image contents** — not just
prose.

## What You Receive

You will be given a diff or list of changed MDX files
in `src/content/docs/`. Review ONLY the changed/added
lines, including code fences and frontmatter.

## What You Check

### Never Publish

1. **Support ticket and thread IDs.** Plain ticket
refs (`T-1234`), Plain thread IDs
(`th_01JQZK4M8XN2VR7TDY0P3WGA6H`), `app.plain.com`
links, or any equivalent from another helpdesk.

2. **Customer, org, and account identifiers.** GitHub
org or repo names belonging to a customer, account
IDs, subscription IDs, Stripe customer or invoice
IDs, seat counts of a real account, email
addresses.

3. **Private repositories and internal code paths.**
`Mergifyio/monorepo`, `mergify_shadow_office/...`,
`mergify_engine/...`, dashboard source paths,
internal module, class, or function names, and
file:line references into private code.

4. **Internal URLs and tools.** Linear and Notion
links, internal dashboards and admin consoles,
staging or internal Mergify hostnames, cloud
consoles, internal runbooks.

5. **Credentials.** Real tokens, API keys, private
keys, or webhook secrets. Placeholders like
`ghp_*` or `<your-token>` are fine; anything that
could be a live secret is not.

6. **Internal-only framing.** Employee names in an
internal context, quotes from a support
conversation, "as discussed with the customer",
references to unreleased work, or an explanation
that only makes sense if you have read the ticket.

### Signals a Leak Is Nearby

Read these lines extra carefully:

- Anything that explains *why* the page was written,
or that names a specific incident.
- Examples that look copied rather than constructed —
a real-looking org name, a specific date, an odd
number of contributors, a plausible invoice amount.
- "For example, one customer…" openers.
- YAML examples whose `repository`, `owner`, or
`login` values are not obvious placeholders.
- Screenshots and their alt text: a dashboard capture
can show a real org name, a customer's repo list, or
an email address.

### What Is Fine

- Public Mergify repos (`Mergifyio/mergify`,
`Mergifyio/gha-mergify-ci`), public product URLs
(`dashboard.mergify.com`, `docs.mergify.com`).
- Public docs of third parties, including their
dashboards (`app.datadoghq.com`, GitHub settings
pages) when the reader is meant to go there.
- Generic placeholders: `my-org`, `your-repo`,
`<token>`, `user@example.com`.
- Product behavior learned from a private source. The
*fact* is publishable; the *source* is not.

## How to Verify

1. **Run the deterministic scan first.** It catches
the mechanical patterns in seconds:

```bash
pnpm check:internal-leaks
```

It only knows fixed patterns. Customer names, copied
examples, and internal framing are yours to catch —
do not treat a clean run as a pass.

2. **Re-read every added example.** For each org name,
repo name, number, and URL in the diff, ask: could
this be real? If you cannot tell, replace it with an
obvious placeholder.

3. **Check the source you wrote from.** If a ticket, a
private PR, or an engine file was in your context,
grep the diff for its identifiers.

4. **Open added screenshots** and look at the pixels,
not just the filename.

## How You Fix

Rewrite so the page states the product behavior and
drops the provenance. Removing the sentence is usually
wrong — the behavior is why the page exists.

Leak:

```text
Customer acme-corp (ticket T-1234) cancelled mid-period
and still received an invoice, because prorations are
collected on the next invoice (see
mergify_shadow_office/models/billing.py).
```

Fixed:

```text
If you cancel mid-period, you may still receive an
invoice on the last day of the period. It collects the
prorations recorded during the period, so it is a
true-up rather than a renewal.
```

## How You Report

1. **Always fix, never only flag.** A leak is the one
class of issue you must not leave in the file for
someone else. Redact or rewrite it, then report it.

2. **Report every removal explicitly**, so a human can
judge whether the value also needs scrubbing from
the branch history or from an already-published
page:

```text
LEAK: [file:line] — [what kind] — removed/replaced with [what]
```

3. **Escalate what you cannot judge.** If you cannot
tell whether a name is a real customer, do not
guess. Replace it with a placeholder and say so:

```text
CHECK: [file:line] — replaced "acme-corp" with "my-org"; confirm it was not a real customer
```

4. **Follow-up suggestions:** If you spot a probable
leak in surrounding UNCHANGED content, note it
rather than editing:

```text
FOLLOW-UP: [file:line] — [description]
```

Say so in your summary even if the diff was clean.
An already-published leak is more urgent than one
you just caught.

## Scope

- Review changed/added content in MDX files under
`src/content/docs/`, plus any image added alongside
them.

- Do NOT edit `src/content/changelog/` — those files
are autogenerated. Report a leak there as a
FOLLOW-UP so a human can fix it upstream.

- Fix leaks and nothing else. Leave style, structure,
and terminology to the other proofreaders.

- When you are unsure whether something is internal,
treat it as internal. A placeholder costs the reader
nothing; a leaked identifier cannot be unpublished.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ jobs:
pnpm install --frozen-lockfile
pnpm check:config-examples

internal-leaks:
timeout-minutes: 5
runs-on: ubuntu-24.04
steps:
- name: Checkout 🛎️
uses: actions/checkout@v7.0.1

- name: Setup Node 🔧
uses: actions/setup-node@v7.0.0
with:
node-version-file: .node-version

# No dependencies needed: the scanner is plain Node. Its own unit tests
# run in the `test` job.
- name: Check for leaked internal information
run: node scripts/check-internal-leaks.mjs

build:
timeout-minutes: 20
runs-on: ubuntu-24.04
Expand Down
65 changes: 64 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pnpm format:check # Check formatting without modifying
# Testing
pnpm test # Run Vitest unit tests
./scripts/detect-broken-links.sh # Check for broken links

# Safety
pnpm check:internal-leaks # Scan docs for leaked internal information
```

## Key Directories
Expand Down Expand Up @@ -147,6 +150,55 @@ Do NOT use regular `git push` - always use `mergify stack push`.
option's own reference page (matching existing action pages) is acceptable;
dated migration notices are not.

8. **Never publish internal information** - Ticket IDs, customer names, private
repo paths, internal links, and credentials must never reach
`src/content/docs/`. See the section below; it applies to every change, with
no size threshold.

## Never Publish Internal Information

Docs are usually written *from* internal material: a support case, a private PR,
an engine source file, a Linear ticket. That material travels with the draft.
The reader never needs to know where a page came from, so anything describing
the *provenance* of a doc is a leak, not context. A leaked identifier cannot be
unpublished.

**Never write any of these into `src/content/docs/`** - prose, code blocks,
comments, frontmatter, alt text, or screenshots:

- **Support ticket and thread IDs** - Plain refs (`T-1234`), thread IDs
(`th_01JQ...`), `app.plain.com` links, or the equivalent from any helpdesk.
- **Customer, org, and account identifiers** - a customer's GitHub org or repo,
account and subscription IDs, Stripe customer or invoice IDs, email addresses,
real seat or contributor counts.
- **Private repositories and internal code paths** - `Mergifyio/monorepo`,
`mergify_shadow_office/...`, `mergify_engine/...`, dashboard source paths,
internal module or function names, `file:line` references into private code.
- **Internal URLs and tools** - Linear and Notion links, admin consoles,
internal dashboards, staging or internal Mergify hostnames, runbooks.
- **Credentials** - real tokens, API keys, private keys, webhook secrets.
Placeholders (`ghp_*`, `<your-token>`) are fine.
- **Internal-only framing** - employee names in an internal context, quotes from
a support conversation, "as discussed with the customer", unreleased work, or
an explanation that only makes sense if you read the ticket.

The fix is almost never deletion. State the product behavior and drop the
provenance: "customer acme-corp on ticket T-1234 was billed after cancelling"
becomes "if you cancel mid-period, a final invoice may still arrive on the last
day of the period."

**Enforcement**, in order of what catches what:

1. `pnpm check:internal-leaks` - deterministic scan for the mechanical patterns
(ticket IDs, internal paths, internal trackers and hosts). Run it before
committing any docs change. It also runs in CI. It cannot catch customer
names, copied examples, or internal framing, so a clean run is not a pass.
2. The `proofread-leaks` subagent - judgment-level review of the diff. **Unlike
the other proofreaders, this one runs on every docs change**, including
sub-10-line edits, frontmatter-only edits, and code-block-only edits.
3. If something internal did reach a commit, say so plainly instead of quietly
amending it. A value that was pushed may need scrubbing beyond the branch.

## Documentation Proofreading

After editing MDX files in `src/content/docs/`, if the
Expand All @@ -160,7 +212,7 @@ pipeline before considering the work done.
MDX files in `src/content/docs/` (use `git diff`
for staged/unstaged changes).

2. **Spawn 4 proofreading subagents in parallel**
2. **Spawn 5 proofreading subagents in parallel**
using the Agent tool, each with the diff and the
list of changed files:
- Style (`proofread-style`): AI patterns, banned
Expand All @@ -175,6 +227,9 @@ pipeline before considering the work done.
- Consistency (`proofread-consistency`): terminology
drift, capitalization, naming

- Leaks (`proofread-leaks`): ticket IDs, customer
names, private paths, internal links, secrets

3. **Each subagent:**
- Reads the skill with the Skill tool for its
full guidelines
Expand Down Expand Up @@ -215,6 +270,14 @@ When spawning each subagent, include:

### When to Skip

**`proofread-leaks` is never skipped.** None of the
conditions below apply to it: a leaked ticket ID is
usually a one-line change, and it hides in code blocks
and frontmatter as readily as in prose. Run it, plus
`pnpm check:internal-leaks`, on every docs change.

The other four are skipped when:

- Changes are fewer than 10 lines of docs content

- Changes are ONLY to frontmatter metadata
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"format:check": "biome format src integrations plugins scripts",
"check": "astro check && eslint . && biome check .",
"check:config-examples": "node scripts/validate-config-examples.mjs",
"check:internal-leaks": "node scripts/check-internal-leaks.mjs",
"check:links": "linkinator dist/ --recurse --concurrency 25 --verbosity error --skip 'https?://'"
},
"devDependencies": {
Expand Down
Loading