feat: review Gustavo and Marcos submitted skills

This commit is contained in:
Marcos Silva
2026-09-04 09:07:54 -03:00
parent 6ccc692759
commit 76d83c9cf9
38 changed files with 2749 additions and 6 deletions
@@ -0,0 +1,113 @@
---
name: page-reviewer
description: Audit a Confluence-ready body before it is posted or updated. Use as the last gate before confluence_create_page_from_file or confluence_update_page_from_file; do not post a page that has not been through this skill.
---
# Page reviewer
A Confluence page is hard to walk back once it's live: watchers, reactions,
and links accumulate, and `minorEdit=true` will not save you from a body that
embarrasses the team. Run this skill before every create or update.
The reviewer reads the draft and the page-context, and returns one of three
verdicts:
- **PASS** — body is ready, post it
- **REVISE** — specific, line-anchored changes are required before posting
- **BLOCK** — something about the draft cannot be fixed locally (wrong space,
wrong parent, scope creep, secret leak) — escalate
The reviewer never edits the draft. It returns a checklist; the human or the
`confluence-page` skill applies the changes.
## Hard rules
- **No body that contains secrets, tokens, session cookies, customer PII, or
internal hostnames** (`*.netcracker.com` internal suffixes are fine in
links; IPs, hostnames and ports from runbooks are not). The reviewer
blocks on first match.
- **No body that references the local mirror path** (`~/Netcracker/Projects/NDO/knowledge/...`).
Use the public BASS URL.
- **No body larger than 300 lines** without a one-line reason in the draft
header. Pages drift; reviewers and readers both lose when they do.
- **No body whose title collides with an existing page** under the same
parent — see step 2 of the workflow.
- **No unrendered macros** — every `{plantuml}`, `{code}`, `{info}`, `{note}`,
`{warning}` block must be in its proper storage form (see
`confluence-page/references/macros.md`). The reviewer rejects raw wiki
markup and raw Markdown inside storage bodies.
## Workflow
1. **Identify the page.** Title, parent, space key, target id (for update).
2. **Collision check.** If creating:
- `mcp__atlassian.confluence_search(cql="space=<SPACE> AND title~\"<title>\"")`
- If a page already exists under the same parent, return **BLOCK** with
"title collision — pick a more specific title or update the existing
page instead".
3. **Pull upstream context.** If updating, fetch the current body with
`mcp__atlassian.confluence_get_page_content(pageId)` and diff against the
draft. Flag any section that was renamed or deleted upstream and carried
forward in the draft without intent.
4. **Lint the body.** For each of the checks below, return a line number and
a short rationale. See [references/checks.md](references/checks.md) for the
full list and severity table.
5. **Slop pass.** Run the `unslop` skill on the body. If unslop returns more
than 5 fixes for a page under 100 lines, or more than 10 for any page,
return **REVISE** — the author should reread, not the agent.
6. **Diagram sanity.** For every `{plantuml}` block, parse to a `.puml` temp
file and run `plantuml -checkonly -syntax` if `plantuml` is on `$PATH`. If
the tool is missing, skip the parse and warn — do not block on a missing
optional tool.
7. **Render verdict.**
## Verdict shape
```
PASS:
- ready to post; no blocking issues
- (optional) minor notes for the author
REVISE:
- L<line>: <rule> — <one-line fix>
- L<line>: <rule> — <one-line fix>
- ...
- estimated fix effort: <s|m|l>
BLOCK:
- <rule>: <what's wrong, what to do instead>
- <rule>: ...
```
The verdict is the only thing the calling skill should consume. Everything
else (diff, lint output, slop report) goes to stderr / a side file for the
human.
## What the reviewer does NOT do
- **Edit the draft.** The author or the `confluence-page` skill applies fixes.
Reviewer that also edits is hard to audit.
- **Post anything.** The reviewer never calls a write MCP tool.
- **Judge voice.** Use `unslop` for that. The reviewer enforces structure,
safety, and rendering correctness; unslop enforces voice.
- **Approve secrets in test data.** Even "obvious" test fixtures get blocked.
If you need sample data with realistic-looking identifiers, generate them
with the project's standard placeholder vocabulary.
## Severity table
| Severity | Returns | Examples |
|----------|---------|----------|
| Blocker | BLOCK | secret leak, wrong parent, wrong space, title collision, raw wiki markup in storage body |
| Major | REVISE | unrendered macro, broken internal link, image without alt text, slop cluster |
| Minor | PASS (with note) | inconsistent heading levels, missing one-line summary, sub-optimal anchor text |
Full rule list: [references/checks.md](references/checks.md).
## Related
| Skill | Role |
|-------|------|
| `confluence-page` | Calls the reviewer before every create/update |
| `unslop` | Voice-level pass; the reviewer delegates voice to it |
| `diagram-plantuml` | Owns PlantUML syntax; the reviewer delegates diagram parsing to it |
@@ -0,0 +1,77 @@
# Page Reviewer — Checks
The full rule list the `page-reviewer` skill runs. Each check has a severity
(BLOCKER / MAJOR / MINOR), the pattern it looks for, and the verdict it
returns.
## BLOCKER
| ID | Rule | How to detect |
|----|------|---------------|
| `B-SECRET` | Body contains a token, key, password, or PII pattern from `confluence-page/references/secrets.md` | `grep -nE "<patterns>" <draft>` |
| `B-MIRROR-PATH` | Body references a local mirror path (`~/Netcracker/Projects/NDO/knowledge/...`) | grep for the root path |
| `B-COLLISION` | A page with the same title exists under the same parent | `confluence_search` for the title |
| `B-WRONG-SPACE` | Draft targets a space that doesn't match content kind (see `confluence-page/references/space-keys.md`) | manual check by reviewer |
| `B-WRONG-FORMAT` | Body is wiki markup or Markdown, not storage XHTML | header doesn't start with `<p`, `<h`, `<ac:`, or `<table`; presence of `---` front-matter fences |
| `B-LOCAL-FS-LINK` | Body contains `file://`, `~/`, or `/home/masi1023/` paths | grep |
| `B-CUSTOMER-PII` | Customer name, hostname, or payment info in body | grep + manual review |
| `B-PARENT-LOOP` | Parent resolves to a descendant of itself | `confluence_get_page` ancestry walk |
## MAJOR
| ID | Rule | How to detect |
|----|------|---------------|
| `M-UNRENDERED-MACRO` | `{plantuml}`, `{code}`, `{info}`, `{note}`, etc. not in proper storage form | grep for unclosed or naked `{...}` macros |
| `M-BROKEN-LINK` | Internal link points to a page id that doesn't exist or a URL that 404s | `confluence_search` for the target title; HEAD on the URL |
| `M-MISSING-ALT` | Image element without `ac:alt` | grep for `<ac:image` without `ac:alt` |
| `M-DIAGRAM-IN-PANEL` | PlantUML block inside an info / note / warning panel | grep + structure check |
| `M-DIAGRAM-IN-CODE` | PlantUML block inside a `{code}` block | grep + structure check |
| `M-CODE-NO-LANG` | `{code}` block without `language` parameter | grep + structure check |
| `M-EMPTY-SECTION` | Section heading followed by nothing or a single sentence | structure walk |
| `M-STALE-SECTION` | Section in draft was deleted from upstream since the last pull (update flow) | diff against `confluence_get_page_content` |
| `M-SLOP-CLUSTER` | `unslop` skill returns >5 fixes for a 30-line block | unslop report count |
| `M-NO-SUMMARY` | First paragraph is missing for a how-to or runbook | structure check |
| `M-OVER-300` | Page body is over 300 lines and no justification header exists | `wc -l` |
## MINOR (PASS with note)
| ID | Rule | How to detect |
|----|------|---------------|
| `m-HEADING-LEVEL` | Skipped heading level (h1 → h3 with no h2) | structure walk |
| `m-MISSING-ANCHOR` | Cross-page reference without an explicit anchor text | structure walk |
| `m-LOOSE-LINK` | "click here", "this link" | grep |
| `m-EMOJI-IN-HEADING` | Emoji in headings that (h1 / h2) | grep |
| `m-CAPITALIZED-LINE` | Long uppercase run (more than 5 words) | grep |
| `m-MULTI-COLON` | Multiple consecutive `:` in a sentence | grep |
| `m-RUN-ON-LINE` | A single line over 200 chars | `awk '{ print length, NR }'` |
## Severity → verdict
```
BLOCKER > 0 → BLOCK
MAJOR > 0 → REVISE
MINOR > 0 → PASS (with note)
```
A single BLOCKER short-circuits. The reviewer still lists MAJOR / MINOR
findings so the author can fix them in the same pass.
## Diff mode (updates)
When the reviewer is called for an update, also run:
| ID | Rule |
|----|------|
| `D-UNINTENDED-DROP` | A section in the upstream body that the draft does not have (and was not intentionally removed by `versionMessage`) |
| `D-UNINTENDED-RENAME` | A heading in the upstream body that the draft has under a different name |
| `D-STALE-VERSION` | The `versionMessage` does not match the change set |
`D-` rules are MAJOR by default; BLOCKER only if the dropped content was
flagged as load-bearing by the previous reviewer.
## What the reviewer does NOT check
- Correctness of the technical content — that's an SME responsibility
- Style / voice — that's `unslop`
- Compliance with team conventions outside this list — escalate to the page
owner