From fda2bbd601885b1d0f4a4fab9d75f56789fd218d Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 20 Jul 2026 14:39:05 +0200 Subject: [PATCH] fix(plugin): trim SKILL.md description to fit the 1024-char skill spec limit Claude Desktop rejects the kbagent skill with "field 'description' in SKILL.md must be at most 1024 characters" because the frontmatter description had grown to 5069 characters of trigger keywords. Over the limit the skill fails to load entirely, so the extra keywords added no trigger surface at all. Rewrite the description to 965 characters covering the same command domains plus the highest-value triggers, and add a static compliance test (tests/test_skill_frontmatter.py) so CI fails if the description ever exceeds the limit again. Fixes #447 --- plugins/kbagent/skills/kbagent/SKILL.md | 88 ++++--------------------- tests/test_skill_frontmatter.py | 55 ++++++++++++++++ 2 files changed, 69 insertions(+), 74 deletions(-) create mode 100644 tests/test_skill_frontmatter.py diff --git a/plugins/kbagent/skills/kbagent/SKILL.md b/plugins/kbagent/skills/kbagent/SKILL.md index 29db2abb..520859da 100644 --- a/plugins/kbagent/skills/kbagent/SKILL.md +++ b/plugins/kbagent/skills/kbagent/SKILL.md @@ -1,80 +1,20 @@ --- name: kbagent description: > - Use when working with Keboola Connection projects via kbagent CLI. - Covers: exploring and searching configurations (extractors, writers, transformations), - browsing job history, analyzing cross-project data lineage, calling MCP tools - across multiple projects, managing development branches, debugging SQL in - temporary workspaces, bulk-onboarding organizations, syncing project configs - as local files (GitOps), git-branching with Keboola dev branch isolation, - sharing buckets across projects, linking shared data, - encrypting secrets for MCP tool call workflows, - uploading/downloading Storage Files with tag management, - and syncing storage metadata and job history. Triggers: kbagent, Keboola project, - keboola configs, keboola jobs, keboola lineage, keboola transformations, - keboola MCP tools, keboola workspace, SQL debugging, keboola branches, - keboola organization, keboola sharing, bucket sharing, link bucket, - keboola sync, keboola git, - keboola gitops, sync pull, sync push, sync diff, branch-link, - search configs, find in configurations, audit configurations, - input mapping migration, remove input mapping, Snowflake paths, - MULTI_STATEMENT_COUNT, statement count error, SQL transformation migration, - keboola encrypt, encrypt secrets, encrypt credentials, encrypt password, - keboola encryption API, #password, #api_token, KBC::ProjectSecure, - safe config write, dry-run preview, fresh fetch before edit, - stale local config file, config version overwrite, - default bucket, output bucket, default_bucket, storage.output, - raw mode bucket override, custom output bucket name, - data app, data apps, keboola data app, streamlit app, streamlit deployment, - flask app, fastapi app, node app, python-js, deploy data app, - data-app create, data-app deploy, data-app password, data-app start, - data-app logs, container logs, app logs, tail logs, build logs, - app stdout, app stderr, troubleshoot data app, debug data app, - app proxy, simpleAuth, app auto-suspend, configVersion, redeploy contract, - Data Science API, /apps endpoint, app password, KBC::Project ciphertext, - data-app secrets, app secrets, app runtime secrets, secrets-set, - secrets-list, secrets-get, secrets-remove, encrypt app secret, - app environment variable, validate repo, validate-repo, - data-app golden rule, pre-flight repo check, repo structure check, - managed git repo, use-managed-git-repo, Keboola-hosted repo, - git-credentials, git-credentials-create, git-repo, - deploy from git, managed repository, - data app runs, deploy attempts, deploy failure reason, why deploy stopped, - local workspace, project directory, kbagent init, - invite user, invite member, project invitation, manage members, - list members, remove member, change role, project role, - bulk invite, invite from CSV, project access, member management, - manage token prompt, --allow-env-manage-token, KBC_MANAGE_API_TOKEN, - feature flag, feature flags, list features, project features, user features, - enable feature, disable feature, set feature flag, add feature, remove feature, - early-adopter-preview, direct-access, pay-as-you-go, /manage/features, - super admin token, super-admin feature, stack feature catalogue, - data stream, data streams, keboola data streams, stream source, OTLP, - OpenTelemetry, otel, OTLP endpoint, OTEL_EXPORTER_OTLP_ENDPOINT, telemetry ingest, - logs metrics traces, stream create-source, stream detail, stream list, - stream delete, otlp source, http source, stream-in, ingest endpoint, - scoped token, scoped storage token, token create, token delete, token refresh, - mint token, revoke token, rotate token, short-lived token, expiring token, - bucket-write token, single-bucket write token, canManageTokens, device enrollment, - per-device credential, per-device token, per-device stream source, - create_scoped_token, create_stream_source, delete_token, refresh_token, - semantic-layer, semantic layer, semantic-layer model, metastore, - semantic-metric, semantic-dataset, semantic-relationship, - semantic-constraint, semantic-glossary, add metric, edit metric, - rename metric, remove metric, validate model, validate semantic layer, - promote model, semantic-layer build, semantic-layer export, - semantic-layer diff, semantic-layer import, semantic-layer token, - metric SQL, dataset FQN, constraint rule, threshold constraint, - 4-band health, _critical _warning _healthy _review, CODE_METRIC, - DIM_METRIC_THRESHOLD, dangling metric FK, orphaned constraint, - phantom field, AGG on STRING, SUM on PCT, deep validate, - sl, kbagent sl, semantic layer wizard, sl-build, sl-add, sl-edit, - reference data, semantic-layer reference-data, chart of accounts, COA, - dimension members, account list, dimension data, member list, - developer portal, dev-portal, apps-api, register component, vendor app, - portal property, ui-options, encryption portal, defaultBucket portal, - app icon, configurationSchema portal, publish component, deprecate component, - kbagent dev-portal, portal identity, vendor login, service account portal. + Use when working with Keboola Connection projects via the kbagent CLI. + Covers: exploring and searching component configurations, job history and + job runs, cross-project data lineage, Keboola MCP tools, development + branches, SQL debugging in temporary workspaces, GitOps sync of configs as + local files (pull/push/diff/clone), bucket sharing and linking, encrypting + secrets, Storage tables and files, data apps (create/deploy/logs/secrets), + conditional flows and schedules, project members and invitations, feature + flags, OTLP data streams, scoped Storage tokens, the semantic layer + (models, datasets, metrics, constraints, reference data), and the Keboola + Developer Portal. Triggers: kbagent, Keboola, keboola config, keboola job, + keboola lineage, keboola sync, gitops, dev branch, workspace SQL, data app, + streamlit deploy, semantic layer, sl, dev-portal, data stream, OTLP, + scoped token, bucket sharing, encrypt secrets, feature flag, flow schedule, + invite member. --- # kbagent -- Keboola Agent CLI diff --git a/tests/test_skill_frontmatter.py b/tests/test_skill_frontmatter.py new file mode 100644 index 00000000..dadaf1dd --- /dev/null +++ b/tests/test_skill_frontmatter.py @@ -0,0 +1,55 @@ +"""Static compliance tests for the kbagent skill frontmatter. + +Claude Desktop (and the Agent Skills spec) enforce a hard limit of 1024 +characters on the ``description`` field in SKILL.md frontmatter; a longer +description makes the whole skill fail to load with +"field 'description' in SKILL.md must be at most 1024 characters" +(issue #447). These tests keep the frontmatter within every consumer's +limits so the plugin stays loadable in Claude Desktop, Claude Code, and +claude.ai alike. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +import pytest +import yaml + +REPO_ROOT = Path(__file__).parent.parent +SKILL_MD = REPO_ROOT / "plugins" / "kbagent" / "skills" / "kbagent" / "SKILL.md" + +# Hard limit from the Agent Skills spec, enforced by Claude Desktop at +# skill-load time (issue #447). +DESCRIPTION_CHAR_LIMIT = 1024 + + +@pytest.fixture(scope="module") +def frontmatter() -> dict: + text = SKILL_MD.read_text(encoding="utf-8") + match = re.match(r"^---\n(.*?)\n---\n", text, re.DOTALL) + assert match is not None, "SKILL.md is missing YAML frontmatter" + data = yaml.safe_load(match.group(1)) + assert isinstance(data, dict), "SKILL.md frontmatter must be a YAML mapping" + return data + + +class TestSkillFrontmatter: + def test_skill_file_exists(self) -> None: + assert SKILL_MD.is_file(), f"SKILL.md missing at {SKILL_MD}" + + def test_name_matches_directory(self, frontmatter: dict) -> None: + assert frontmatter.get("name") == "kbagent" + + def test_description_present(self, frontmatter: dict) -> None: + description = frontmatter.get("description", "") + assert description.strip(), "SKILL.md description must not be empty" + + def test_description_within_claude_desktop_limit(self, frontmatter: dict) -> None: + description = frontmatter["description"] + assert len(description) <= DESCRIPTION_CHAR_LIMIT, ( + f"SKILL.md description is {len(description)} characters; Claude " + f"Desktop rejects skills whose description exceeds " + f"{DESCRIPTION_CHAR_LIMIT} characters (issue #447). Trim it." + )