Repository navigation
fix(skills): a deprecated library skill says so — listing, assign, Library and Skills tab (abilityai/trinity-enterprise#672) - #3133
Merged
Conversation
…brary and Skills tab (Abilityai/trinity-enterprise#672) A skills library retires a skill with two frontmatter keys, `deprecated: true` and `superseded-by: <text>`. The platform parser dropped both, so a retired skill was listed, assignable and injected exactly like a live one until its directory was deleted. Parser (`skill_packaging.extract_contract`) - carries `deprecated` (a real boolean) and `superseded_by` (the hyphenated key; the underscore spelling is read too; a `trinity:` block wins in either spelling; a null key masks nothing) - `superseded_by` is the author's text — one printable line, at most 200 characters, None unless the skill is deprecated — not a resolved skill name - garbage is named, never fatal: `frontmatter_invalid:deprecated`, `frontmatter_invalid:superseded-by` - `deprecation_warning()` is the one producer of the machine code: `deprecated:<successor>` when the text is a valid skill name, bare `deprecated` otherwise Surfaces - `list_skills` / `get_skill`, `GET /api/skills/library` (named in the route's explicit `SkillInfo(...)`) and MCP `list_skills` (named in its field map) carry both fields - a deprecated skill is still injected; the code rides every per-skill result (injected, unchanged, conflict) and the start endpoint's public projection - assigning one still succeeds: `delivery.skills[name].warnings` carries the code on EVERY delivery outcome. It is read from the library entry, beside delivery, because the delivery report reduces results to a status and a stopped agent never runs an injection. Present only for a deprecated name; lifecycle codes only - Library card, Skills tab assigned row and Skills tab picker: a warning `deprecated` badge beside the name and a "Superseded by …" line; a warning-toned note after assigning one. Nothing is hidden, dimmed or refused - the agent's CLAUDE.md is deliberately not annotated: an agent that already holds a deprecated skill behaves exactly as before Not marked yet: skill-set member lists, the skill-runner picker, and the CLI's `skills list` table (its JSON output carries the fields). No migration: both fields are derived from the synced repository on every parse and never persisted. Tests: tests/unit/test_ent672_skill_deprecation.py (49), src/frontend/tests/unit/skillDeprecation.spec.js (17, mounted), src/mcp-server/src/tools/skills.test.ts (+3). Mutation check: 39 wiring lines mutated one at a time (both router kwargs, both MCP map keys, the parse copy and its defaults, the inject append, the delivery stamp and its fail-open arm, the concurrent read, the projection regex, every parser rule, all six template sites, the badge titles, both notes and their lifetimes) — 39 red, each file restored byte-identical. Refs Abilityai/trinity-enterprise#672 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rt (Abilityai/trinity-enterprise#672) /cso --diff on the branch: no findings at the 8/10 gate; four candidates recorded below the gate with their evidence. The one pin the audit added: the Library card renders a library-authored successor containing markup as characters — red when the successor line is mutated to v-html. Refs Abilityai/trinity-enterprise#672 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecation-lifecycle
This was referenced Sep 30, 2026
…ad is waited for (Abilityai/trinity-enterprise#672) Review finding on PR #3133: the docstring claimed the read is "done long before any delivery outcome". That holds for the budget-bound in_progress path; a fast outcome (pending_start, docker_unavailable) waits for it — a cached listing read. Comment only. Refs Abilityai/trinity-enterprise#672 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
merge-train (#3143): on this train. /validate-pr and /review came back READY with no criticals. The deprecation value is traced end to end, and breaking it on purpose fails tests. #3134 and #3135 are both bugs already on Non-blocking:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A skills library retires a skill with two frontmatter keys,
deprecated: trueandsuperseded-by: <text>. The platform parser dropped both, so a retired skill was listed, assignable and injected exactly like a live one until its directory was deleted. Four skills on the community library'smaincarry the keys today (two of them are already in thev0.2.0tag that fresh installs pin), and none of them was marked anywhere.extract_contractcarriesdeprecated(a real boolean) andsuperseded_by.superseded_byis the author's text: one printable line, at most 200 characters,nullunless the skill is deprecated. It is not a resolved skill name, because two of the four live values are sentences.trinity:block wins.frontmatter_invalid:*warning. A library whose CI runs this parser fails on it.list_skills/get_skill,GET /api/skills/library(named in the route's explicitSkillInfo(...)) and MCPlist_skills(named in its field map).delivery.skills[name].warningscarriesdeprecatedordeprecated:<name>on every delivery outcome, a stopped agent included.deprecatedbadge and a "Superseded by …" line, and an amber note appears after assigning one. Nothing is hidden, dimmed or refused.No migration: both fields are derived from the synced repository on every parse and never persisted.
Changes
src/backend/services/skill_packaging.py—extract_contract+_first_present/_one_line, anddeprecation_warning()(the one producer of the code).src/backend/services/skill_service.py—_parse_skill_infocopies the fields,_inject_skills_lockedappends the code, anddeliver_assignedruns the library read beside delivery and stamps the report.src/backend/routers/skills.py+src/backend/db_models.py::SkillInfo— two fields.src/backend/services/agent_service/lifecycle.py—_WARNING_REkeepsdeprecated:<name>.src/mcp-server/src/tools/skills.ts—list_skillsmaps both fields; descriptions updated.LibrarySkillsSection.vue,SkillsPanel.vueandskills/AssignedAgents.vue, with shared helpers inskills/contract.js(supersededLine,DEPRECATED_TITLE) andutils/skillDelivery.js(deprecationText,isDeprecationCode).architecture/backend.mdandarchitecture/mcp-server.md;Test plan
tests/unit/test_ent672_skill_deprecation.py— 49 tests. Covers the parse table, the warning grammar, the fields through the listing / get / REST route, the code on injected / unchanged / conflict results, the delivery stamp on running / stopped / docker-unreadable / over-budget outcomes, the library read running beside delivery, fail-open on an unreadable library, the start projection, and the un-annotated CLAUDE.md line.src/frontend/tests/unit/skillDeprecation.spec.js— 18 tests, mounted. Covers each of the three surfaces with its own test ids, both post-assign notes and their lifetimes, a live skill unmarked, and an HTML-shaped successor rendered as text.src/mcp-server/src/tools/skills.test.ts— 3 new tests, including a backend that predates the fields.dev:tscclean;@vue/compiler-sfcload failures;check:tokenspass./verify-local --skip-agent --skip-unitpasses on the merged commit: backend image build +import main, isolated boot, integration 70 passed. The unit stage was skipped because it fails on every branch off currentdevfor order-dependent reasons, and it runs in CI./cso --diff: no findings at the 8/10 gate —docs/security-reports/cso-diff-2026-09-30-672-skill-deprecation.md.main(four deprecated skills): the Library cards, assigning from a card, the Skills tab picker and assigned row, and the API fields.Not in this PR
Not marked yet:
skills listtable (its JSON output carries the fields).Tracked in abilityai/trinity-enterprise#736.
Found along the way, filed separately:
user-invocable: falseare reported as user-invocable — the platform parser reads only the underscore spelling #3134 — the parser reads onlyuser_invocable, so library skills markeduser-invocable: falseread as invocable;shadowedbadge tooltip reads "Shadowed by: [object Object]" #3135 — theshadowedbadge tooltip renders[object Object];Library side: a validator rule for
superseded-by, the "removed at the next major vs minor tag" wording, and bumping the library CI's pinned copy of this parser. Forabilityai/trinity-skills.Fixes abilityai/trinity-enterprise#672
🤖 Generated with Claude Code