fix: keep plugin descriptions within the Cowork limit (#216)

Co-authored-by: Yang Fan <266078689+yangfan-yf-yf@users.noreply.github.com>
This commit is contained in:
Yang Fan
2026-09-11 06:33:23 +08:00
committed by GitHub
parent fc9c0be3ad
commit 5fb8a197f2
7 changed files with 64 additions and 8 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "diagram-design",
"metadata": {
"description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, waterfall, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg, Mermaid .mmd, or Excalidraw .excalidraw sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling."
"description": "Create architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart, loop, nested, tree, org chart, layer stack, Venn, pyramid/funnel, bar, waterfall, treemap, line, Gantt, scatter, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, database schema diagrams as HTML/SVG/PNG."
},
"owner": {
"name": "Cathryn Lavery"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "diagram-design",
"description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, waterfall, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg, Mermaid .mmd, or Excalidraw .excalidraw sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.",
"description": "Create architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart, loop, nested, tree, org chart, layer stack, Venn, pyramid/funnel, bar, waterfall, treemap, line, Gantt, scatter, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, database schema diagrams as HTML/SVG/PNG.",
"version": "2.6.21",
"author": {
"name": "Cathryn Lavery",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "diagram-design",
"description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, waterfall, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg, Mermaid .mmd, or Excalidraw .excalidraw sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.",
"description": "Create architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart, loop, nested, tree, org chart, layer stack, Venn, pyramid/funnel, bar, waterfall, treemap, line, Gantt, scatter, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, database schema diagrams as HTML/SVG/PNG.",
"version": "2.6.21",
"author": {
"name": "Cathryn Lavery",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "diagram-design",
"description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, waterfall, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg, Mermaid .mmd, or Excalidraw .excalidraw sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.",
"description": "Create architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart, loop, nested, tree, org chart, layer stack, Venn, pyramid/funnel, bar, waterfall, treemap, line, Gantt, scatter, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, database schema diagrams as HTML/SVG/PNG.",
"version": "2.6.21",
"author": {
"name": "Cathryn Lavery",
+6
View File
@@ -84,6 +84,12 @@ Every validation gate below must pass before a PR is ready. They also run automa
The semantic-pattern gate also caps `skills/diagram-design/SKILL.md` at 40,000 bytes so the installed skill remains practical to load. If that gate fails, reduce duplication or move detail into a routed reference; do not remove routing vocabulary from frontmatter.
Keep native plugin and marketplace `description` fields within 500 characters
for Cowork installation compatibility ([#208](https://github.com/cathrynlavery/diagram-design/issues/208)).
They must still name every visual type; keep fuller feature details in the skill
frontmatter and Codex `longDescription`. The docs-sync gate checks both length
and routing vocabulary, and the package gate keeps native descriptions aligned.
Run them all at once before pushing:
```bash
+45
View File
@@ -58,6 +58,51 @@ def load_verify_module():
def main() -> int:
verify = load_verify_module()
# Keep real routing vocabulary in the fixtures so the size check cannot
# accidentally replace the existing lexical-hook validation.
short = json.loads((ROOT / ".claude-plugin/plugin.json").read_text(encoding="utf-8"))["description"]
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
for relative, _ in verify.MANIFEST_DESCRIPTIONS:
path = root / relative
path.parent.mkdir(parents=True, exist_ok=True)
document = json.loads((ROOT / relative).read_text(encoding="utf-8"))
path.write_text(json.dumps(document), encoding="utf-8")
for relative, _ in verify.MANIFEST_DESCRIPTIONS:
path = root / relative
original = path.read_text(encoding="utf-8")
for length in (500, 501):
document = json.loads(original)
container = document["metadata"] if "metadata" in document else document
# Count the original value, including trailing whitespace.
container["description"] = short.ljust(length)
path.write_text(json.dumps(document), encoding="utf-8")
errors: list[str] = []
verify.check_manifest_descriptions(errors, root)
expected = [] if length == 500 else [
f"{relative.as_posix()} description exceeds the Cowork limit "
"(501 > 500 characters)"
]
if errors != expected:
raise AssertionError(f"manifest size boundary failed: {errors}")
path.write_text(original, encoding="utf-8")
codex = root / ".codex-plugin/plugin.json"
document = json.loads(codex.read_text(encoding="utf-8"))
document["interface"]["longDescription"] = short + " More detail." * 50
codex.write_text(json.dumps(document), encoding="utf-8")
errors = []
verify.check_manifest_descriptions(errors, root)
if errors:
raise AssertionError(f"longDescription incorrectly limited: {errors}")
document["description"] = short.replace("Wardley map", "map")
codex.write_text(json.dumps(document), encoding="utf-8")
errors = []
verify.check_manifest_descriptions(errors, root)
if len(errors) != 1 or "lost the lexical hook" not in errors[0]:
raise AssertionError(f"missing routing hook was not rejected: {errors}")
for length in (1024, 1025):
errors: list[str] = []
markdown = f"---\nname: fixture\ndescription: {'x' * length}\n---\n"
+9 -4
View File
@@ -11,10 +11,9 @@ Ten drift classes, each of which has shipped before:
3. Every concrete file named in README.md's architecture tree must exist.
4. Every relative references/*.md link in SKILL.md must resolve.
5. Claude and Pi command/prompt surfaces must route to the matching reference.
6. The plugin manifests repeat the SKILL.md description verbatim. They are the
text a user reads *before installing*, so by ADR 0004's own argument they
need every type's lexical hook too - and nothing else notices when they
drift, because they are four separate copies of one sentence.
6. Plugin descriptions must fit Cowork's installation limit while retaining
every type's lexical hook. The skill and Codex longDescription keep the
fuller feature summary without inheriting the short-description limit.
7. Factory Droid's README install commands and native manifest path must agree
with the package metadata instead of becoming a second hand-maintained API.
8. Every support path a strict skill bundler can extract from SKILL.md must be
@@ -45,6 +44,7 @@ LINE_DARK_EXAMPLE = ROOT / "skills/diagram-design/assets/example-line-dark.html"
VARIANTS = ("", "-dark", "-full")
VISUAL_TYPE_COUNT = 40
AGENT_SKILLS_DESCRIPTION_MAX = 1024
PLUGIN_DESCRIPTION_MAX = 500
# Types whose selection-table name differs from its description vocabulary.
DESCRIPTION_ALIASES = {
"bar chart": "bar",
@@ -549,6 +549,11 @@ def check_manifest_descriptions(errors: list[str], root: Path) -> None:
if value is None:
errors.append(f"{relative.as_posix()} has no {key!r}")
continue
if key == "description" and len(value) > PLUGIN_DESCRIPTION_MAX:
errors.append(
f"{relative.as_posix()} description exceeds the Cowork limit "
f"({len(value)} > {PLUGIN_DESCRIPTION_MAX} characters)"
)
text = normalized(value)
for name in types:
hook = DESCRIPTION_ALIASES.get(normalized(name), normalized(name))