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
8 changes: 8 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
"category": "engineering",
"tags": ["kaizen", "improvement", "optimization", "automation", "autoresearch", "kpi", "refactoring"]
},
{
"name": "plantuml",
"source": "./plantuml",
"description": "Authoring, rendering, and maintenance of PlantUML diagrams — policy-driven projects with multi-target rendering, lint, validate, review, advisor, and migrate",
"version": "1.0.0",
"category": "documentation",
"tags": ["plantuml", "diagrams", "uml", "c4", "documentation", "rendering", "lint"]
},
{
"name": "project-management",
"source": "./project-management",
Expand Down
11 changes: 11 additions & 0 deletions plantuml/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "plantuml",
"version": "1.0.0",
"description": "Authoring, rendering, and maintenance of PlantUML diagrams — policy-driven projects with multi-target rendering, lint, validate, review, advisor, and migrate",
"author": {
"name": "MrBogomips",
"url": "https://github.com/MrBogomips"
},
"license": "MIT",
"keywords": ["plantuml", "diagrams", "uml", "c4", "documentation", "rendering", "lint"]
}
125 changes: 125 additions & 0 deletions plantuml/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# plantuml

Authoring, rendering, and maintenance of PlantUML diagrams in Claude Code projects. Policy-driven theming, multi-target output (web/docx/pdf/pptx), and a maintenance layer for lint, validate, review, advisor, and migration.

## Status

v1.0.0 — all 8 skills, 4 agents, and 1 command are present and validated by in-tree smoke tests.

The smoke tests (`plantuml/tests/smoke/`) are static structural assertions: they verify that skills, agents, commands, and the plugin manifest are correctly wired. Behavioral correctness (LLM-driven authoring and maintenance flows) is validated in real use after install.

## Requirements

- `plantuml` CLI — `brew install plantuml` (macOS) or `apt install plantuml` (Debian/Ubuntu)
- `java` — pulled transitively by the plantuml package
- `jq` — required by the marketplace structural tests

## Install

Add this marketplace to Claude Code and install the `plantuml` plugin via the plugin manager.

## Quickstart

```
# 1. Bootstrap your project
> /plantuml-init

Creating ## PlantUML Policy in CLAUDE.md...
Materializing .plantuml/ (theme: aws, targets: png svg)...
Done. Edit CLAUDE.md > PlantUML Policy to customize.

# 2. Author a diagram (the plantuml-authoring skill activates on intent)
> Create a sequence diagram for our login flow and save it as diagrams/login.puml

[plantuml-authoring activates]
Writing diagrams/login.puml with skinparam includes from _base.puml...
Done.

# 3. Maintain it
> Lint all .puml files

[plantuml-lint activates, dispatches puml-linter agents in parallel]
diagrams/login.puml: OK

> plantuml-validate mode=bless

[plantuml-validate activates, renders all targets, writes baselines]
diagrams/login.puml [png]: blessed
diagrams/login.puml [svg]: blessed
```

## Components

### Authoring and Rendering

| Component | Kind | Purpose |
|-----------|------|---------|
| `plantuml-authoring` | Skill | Create or restructure `.puml` files for any diagram type (UML, C4, ER, ArchiMate, MindMap, WBS, Gantt, Salt, JSON/YAML, nwdiag family) |
| `plantuml-convert` | Skill | Convert `.puml` files to PNG, SVG, or PDF; used by document skills as a render step |
| `puml-renderer` | Agent | Build-time worker: render or validate a single (file, target) pair and compare against a baseline |

### Bootstrap

| Component | Kind | Purpose |
|-----------|------|---------|
| `plantuml-bootstrap` | Skill | Create the `## PlantUML Policy` in `CLAUDE.md` and materialize `.plantuml/`; also runs in `mode=reverse` to recover policy from an existing directory |
| `/plantuml-init` | Command | User-facing shortcut that delegates to `plantuml-bootstrap` |

### Maintenance

| Component | Kind | Purpose |
|-----------|------|---------|
| `plantuml-lint` | Skill | Check `.puml` files for Policy drift, broken includes, and invariant violations (hardcoded colors, missing `_base.puml`, filename/title mismatch) |
| `plantuml-validate` | Skill | Render all declared targets and verify output against committed baselines; accepts `mode=check|bless` and `level=checkonly|svg-hash|png-perceptual` |
| `plantuml-review` | Skill | Qualitative review of a diagram for clarity, type-fit, layout, and readability |
| `plantuml-advisor` | Skill | Advise on diagram-type fit: confirm the current type or suggest a better one with a migration sketch |
| `plantuml-migrate` | Skill | Apply a Policy change (theme switch, target add/remove, brand colors) across all `.puml` files; backs up `.plantuml/` before any destructive write |

### Build-time Workers

| Component | Kind | Purpose |
|-----------|------|---------|
| `puml-linter` | Agent | Lint a batch of `.puml` files against Policy invariants; dispatched in parallel by `plantuml-lint` |
| `puml-migrator` | Agent | Apply a declarative edit plan to a single `.puml` file; dispatched by `plantuml-migrate` |
| `puml-visual-checker` | Agent | Smoke-check a rendered image for color, font, and layout correctness; build-time only, not user-facing in v1.0.0 |

## Maintenance Flow

Typical lifecycle after initial bootstrap:

1. **Bootstrap** — `/plantuml-init` once per project.
2. **Author** — `plantuml-authoring` to create or restructure `.puml` files.
3. **Lint** — `plantuml-lint` to catch Policy drift and invariant violations.
4. **Validate** — `plantuml-validate mode=bless` to commit baselines; `mode=check` in CI.
5. **Review / Advisor** — `plantuml-review` for qualitative feedback; `plantuml-advisor` when the diagram type feels wrong.
6. **Policy change** — edit `## PlantUML Policy` in `CLAUDE.md`, then `plantuml-migrate` to propagate to all files.

## Verifying Install

From the marketplace root:

```bash
bash tests/ci/run-structural-tests.sh
```

Then run the six plugin smoke tests:

```bash
for t in bootstrap lint validate review advisor migrate; do
bash plantuml/tests/smoke/test-$t.sh
done
```

All must pass before considering the install complete.

## Known Limitations (v1.0.0)

- `plantuml-validate level=png-perceptual` is not implemented and returns `unsupported`. Use `level=checkonly` (default) or `level=svg-hash` for CI.
- `plantuml-migrate` has no concurrent-edit locking. Do not run while another tool is writing `.puml` files.
- `puml-visual-checker` is a build-time agent only; it is not exposed as a user-facing skill in v1.0.0.
- Cross-machine `level=svg-hash` comparisons require pinned fonts. On heterogeneous CI, prefer `level=checkonly`.
- Agents (`agents/<name>/AGENT.md`) are auto-discovered by Claude Code. If discovery fails on first install, the orchestrating skills degrade to inline Sonnet invocations (correct but slower and costlier). Verify agent availability at first use.

## Dev

The plugin is the source of truth for all PlantUML evolution. Edits go directly under `plantuml/`. Smoke tests live at `plantuml/tests/smoke/`. The minimal fixture project used by the smoke tests is at `plantuml/tests/fixtures/minimal-project/`.
80 changes: 80 additions & 0 deletions plantuml/agents/puml-linter/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
name: puml-linter
description: "Lint a list of `.puml` files against PlantUML Policy invariants. Returns a JSON array of violations. Dispatched by the plantuml-lint skill in parallel batches."
model: haiku
allowed-tools: Read
---

# PlantUML Linter Agent

You are a Haiku worker for the `plantuml-lint` skill. You receive a JSON
array of file paths in the user's project. Read each file and apply the
fixed rule set below. Emit a JSON array of violations.

**Never read plugin assets.** Only the user-project paths in your input.

## Input format

The orchestrator passes a JSON array as your prompt context, e.g.:

```json
{
"project_root": "/abs/path/to/project",
"files": ["diagrams/Foo.puml", "diagrams/Bar.puml"],
"policy_present": true
}
```

`project_root` is absolute. `files` are relative to `project_root`.
`policy_present` indicates whether the project has a `## PlantUML Policy`
section in `CLAUDE.md` and a `.plantuml/_base.puml` — when false, rules
that depend on policy (R1, R2, R3) are suppressed.

## Rules

For each file, evaluate:

- **R1 (require base include)** — file must contain
`!include` ending with `_base.puml` (or be a partial via `_*.puml`
filename convention). Suppressed if `policy_present=false`.
- **R2 (no inline skinparam duplication)** — `skinparam` lines that the
base sets are forbidden: `defaultFontName`, `defaultFontSize`,
`backgroundColor`, `ArrowColor`. Suppressed if `policy_present=false`.
- **R3 (no hex color literals)** — pattern `#[0-9A-Fa-f]{6,8}` outside of
a `' …` comment. Allowed only inside `_*.puml` policy partials.
Suppressed if `policy_present=false`.
- **R4 (filename matches title)** — first `@startuml <title>` directive
must match the file's basename without extension. Title is required.
- **R5 (single startuml/enduml)** — exactly one `@startuml … @enduml`
block per file.

## Output format

JSON only — no prose, no markdown. Schema:

```json
[
{
"file": "diagrams/Drift.puml",
"rule": "R3",
"severity": "error",
"message": "hex color literal `#FF00FF` (line 3) — use brand variable like $primary",
"line": 3
}
]
```

Empty array `[]` if no violations.

## Severity

- `error` — R4, R5, or any rule violation in a file that has a Policy.
- `warning` — R1, R2, R3 in a file that explicitly opts out via
`' lint-disable: R<n>` comment within the first 10 lines.

## Don'ts

- Do NOT write to disk.
- Do NOT read files outside `files`.
- Do NOT emit anything besides the JSON array.
- Do NOT invent rules beyond R1–R5.
88 changes: 88 additions & 0 deletions plantuml/agents/puml-migrator/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
name: puml-migrator
description: "Apply a declarative edit plan to a single `.puml` file. Returns a JSON status of applied/skipped/error operations. Dispatched by plantuml-migrate."
model: haiku
allowed-tools: Read, Edit
---

# PlantUML Migrator Agent

Haiku worker for `plantuml-migrate`. You receive one file and a list of
edit operations. Apply them mechanically. Emit a JSON status.

**Never read plugin assets.** Only the user-project paths in your input.

## Input

```json
{
"project_root": "/abs/path",
"file": "diagrams/Foo.puml",
"edit_plan": [
{"op": "replace_include", "from": "_theme_v1.puml", "to": "_theme_v2.puml"},
{"op": "rename_var", "from": "$oldname", "to": "$newname"},
{"op": "update_target_directive", "to": "docx"}
]
}
```

Supported ops (no others — emit `error` if you receive an unknown op):

- `replace_include` — replace the unique line `!include <from>` with
`!include <to>`. Use `Edit` with the file's actual `!include <from>`
text as `old_string` (read it first to capture exact whitespace).
- `rename_var` — replace **all occurrences** of `<from>` with `<to>`,
case-sensitive. Use `Edit` with `replace_all: true`. Match is exact
string substitution; do not re-format.
- `update_target_directive` — find the line matching
`^\s*!\s*\$target\s*=\s*"[^"]*"\s*$`, read it via `Read` to capture
exact whitespace, then `Edit` it to `!$target = "<to>"` preserving
the file's leading indentation. The directive appears at most once.

## Behavior

For each op in order:

1. **Locate** the relevant lines via `Read` to capture exact whitespace
and surrounding context (Edit requires byte-exact `old_string`).
2. **Apply** via `Edit`. If `Edit` reports no match, mark the op as
`skipped` with `reason: "no match"`. If `Edit` errors out for any
other reason, stop processing further ops and set the agent-level
`error` field.
3. **Confirm** after each op: re-Read the file. If `@startuml` /
`@enduml` are missing, doubled, or otherwise malformed, stop. The
file is now in an **inconsistent state** — record this in `error`
and surface in the response. Do NOT attempt to undo applied edits;
the orchestrator's backup mechanism handles recovery.

After all ops, do one final confirmation pass.

## Output

```json
{
"file": "diagrams/Foo.puml",
"applied": [{"op": "replace_include", "from": "_theme_v1.puml", "to": "_theme_v2.puml"}],
"skipped": [{"op": "rename_var", "from": "$x", "reason": "no match"}],
"error": null
}
```

`error` is `null` on success or a one-line message describing the
failure. When `error` is non-null, `applied` lists the ops that were
already written to disk before the failure — the file is in an
inconsistent state and the orchestrator must surface this prominently.

If the input JSON cannot be parsed, emit:

```json
{"file": "", "applied": [], "skipped": [], "error": "input parse error"}
```

## Don'ts

- Do NOT invent ops not listed.
- Do NOT modify files outside `file`.
- Do NOT touch `.plantuml/_*.puml` policy partials.
- Do NOT attempt rollback of partial edits — the orchestrator owns recovery.
- Do NOT emit anything besides the JSON object.
Loading
Loading