Skip to content

refactor(agent): align skill slugs with published packages#3025

Open
daryllimyt wants to merge 7 commits into
daryl/eng-1524-resolution-effective-versionsfrom
daryl/eng-1532-skill-slug-runtime
Open

refactor(agent): align skill slugs with published packages#3025
daryllimyt wants to merge 7 commits into
daryl/eng-1524-resolution-effective-versionsfrom
daryl/eng-1532-skill-slug-runtime

Conversation

@daryllimyt

@daryllimyt daryllimyt commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Mental model

  • Skill.id is the stable ResourceHead identity used by internal edges.
  • Skill.slug is the current published package locator. Publishing or restoring a version atomically advances it to that version's root SKILL.md frontmatter name.
  • Skill.name is user-facing display metadata. The column keeps its current name for compatibility; a later migration can rename it to display_name.
  • SkillVersion.name remains the immutable, version-local Agent Skills package identifier and runtime directory name.
  • Preset relationships remain head-only. Dispatch resolves each Skill head to its current SkillVersion, and the existing per-preset-resolution and executor duplicate-package guards remain in place.

This intentionally does not add SkillVersion.slug, change the Temporal payload, or move runtime staging away from the resolved SkillVersion.name.

Changes

  • Advance Skill.slug from published/restored frontmatter and fail atomically with skill_slug_conflict when another live head owns the locator.
  • Preserve Skill.name when draft frontmatter or published package names change.
  • Keep Workspace Sync's top-level slug as the head locator, top-level name as display metadata, and version name as the immutable package identifier.
  • Preserve legacy head/package mismatches during sync until a later publish advances the head slug.
  • Clarify API schema descriptions, generated client docs, model docstrings, product docs, and regression coverage.

Rollout note

Changing frontmatter name on publish changes slug-authored API, URL, and Workspace Sync references. Internal preset edges are unaffected because they use the stable Skill head ID. Existing skills whose historical stable slug differs from their current version remain readable and syncable; republishing opts them into the new behavior.

Related: ENG-1532

Verification

  • 749 changed unit and migration tests passed.
  • 19 Temporal tests passed; 4 approval tests skipped by their existing markers.
  • just gen-client-ci produced no diff.
  • Ruff check/format, changed-file basedpyright, frontend check/typecheck, and Alembic single-head verification passed.

Summary by cubic

Use skill slugs as the package identity and runtime directory; keep name display-only. Adds expand-window safeguards, strict slug validation, and 409-conflict handling across publish/restore and sync to prevent duplicate effective slugs and shadowed bindings. (ENG-1532)

  • Refactors

    • Skill.slug is the canonical package locator; Skill.name is user-facing only. API/DB/docs and generated clients clarify both fields.
    • Publish/restore advance slug from the root SKILL.md name and pre-validate availability (excluding the owner, including against legacy rows with slug IS NULL); conflicts surface as HTTP 409 skill_slug_conflict on both public and internal restore routes.
    • Draft seeding/uploads carry the allocated slug in SKILL.md: duplicate display-name creates seed a suffixed slug, and duplicate-name uploads rewrite the manifest name to the allocated slug so untouched drafts publish cleanly.
    • Runtime resolver adds SkillService.get_skill_by_slug; Workspace Sync rename checks validate against coalesce(slug, name), and imports/preset bindings resolve via this resolver so exact owners win and legacy-only ambiguity fails loud.
    • Workspace Sync exports dedupe per effective slug (full and dependency exports) and fail with ambiguous_skill_slug when only legacy rows contend; preset exports reject shadowed_skill_binding when a legacy binding is masked by a live slug owner; sync schemas enforce the canonical SkillName for both skill specs and preset binding slugs.
  • Migration

    • Renaming the SKILL.md frontmatter name changes the slug; update any slug-based API, URL, or Workspace Sync references after publish/restore.
    • Display names can duplicate; slugs must be unique per workspace.
    • Legacy skills without slug continue to work (fallback to name) until re-publish backfills slug; sync exports may surface ambiguous_skill_slug or shadowed_skill_binding during the expand window.
    • Presets resolve attached skills by slug and automatically use each skill’s current published version; publish to roll out changes.

Written for commit 1c12315. Summary will update on new commits.

Review in cubic

@daryllimyt daryllimyt changed the title refactor(agent): use skill slugs as package identity refactor(agent): align skill slugs with published packages Jul 12, 2026
@daryllimyt daryllimyt added agents LLM agents skills refactor Refactoring breaking Breaking changes labels Jul 12, 2026
@daryllimyt
daryllimyt marked this pull request as ready for review July 12, 2026 23:46
@zeropath-ai

zeropath-ai Bot commented Jul 12, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 1c12315.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► docs/agents/skills.mdx
    -► Tracecat skill package identifier and slug behavior updates
► frontend/src/client/schemas.gen.ts
    -► Add descriptions for SkillRead and SkillReadMinimal fields
► frontend/src/client/types.gen.ts
    -► Annotate SkillRead and SkillReadMinimal with display name and slug descriptions
► tests/unit/test_agent_preset_service.py
    -► Adjust test to reuse legacy handling of duplicate bound skill names and introduce new test for duplicate display names
► tests/unit/test_agent_skill_internal_router.py
    -► Extend tests to cover internal/public restore skill version slug conflict handling
► tests/unit/test_skill_service.py
    -► Add tests for duplicate display name behavior, slug handling, and publish/restore interactions
► tests/unit/test_workspace_sync_acceptance_contract.py
    -► Extend tests for invalid skill slugs, exact vs legacy slug handling, and projection behaviors related to slugs
► tracecat/agent/skill/internal_router.py
    -► Handle TracecatValidationError by mapping to HTTP error in internal restore
► tracecat/agent/skill/router.py
    -► Map TracecatValidationError to HTTP error in public restore route
► tracecat/agent/skill/schemas.py
    -► Add descriptive metadata for SkillRead and SkillReadMinimal fields
► tracecat/agent/skill/service.py
    -► (No explicit changes shown beyond context)
Refactor ► tracecat/agent/skill/internal_router.py
    -► Surround restore_skill_version with error handling to map to HTTP errors
Other relevant changes ► tracecat/workspace_sync adapters and tests (various files)
    -► Adjust slug/skill handling expectations in integration tests
► diff includes multiple test updates and new test cases for slug conflict resolution and legacy vs exact owner slug resolution

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 477b68f22a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/agent/skill/service.py
Comment thread tracecat/workspace_sync/adapters/skill.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 12 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread tracecat/workspace_sync/adapters/skill.py
Comment thread tracecat/workspace_sync/adapters/agent_preset.py Outdated
Comment thread tracecat/agent/skill/service.py
Comment thread tracecat/agent/skill/service.py
Comment thread tracecat/agent/skill/service.py
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 477b68f to 72bf05e Compare July 13, 2026 00:40
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 26518da to 6fe6d45 Compare July 13, 2026 00:40

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72bf05e74e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/agent/skill/service.py
Comment thread tracecat/workspace_sync/adapters/skill.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72bf05e74e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/agent/skill/service.py
Comment thread tracecat/workspace_sync/adapters/skill.py Outdated
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 72bf05e to 104b5a0 Compare July 13, 2026 01:15
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 6fe6d45 to 796b9ec Compare July 13, 2026 01:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 104b5a0d24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/skill.py
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 104b5a0 to c8e9748 Compare July 13, 2026 02:21
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 796b9ec to 83ca8d8 Compare July 13, 2026 02:21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8e9748087

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/skill.py
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 83ca8d8 to 6203a77 Compare July 13, 2026 02:57
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from c8e9748 to 2a1cc8c Compare July 13, 2026 02:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a1cc8ca9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/agent_preset.py Outdated
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 6203a77 to 56d977c Compare July 13, 2026 04:00
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 2a1cc8c to b84dda6 Compare July 13, 2026 04:00

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b84dda6ad3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/agent_preset.py
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from b84dda6 to 8ec3a5e Compare July 13, 2026 15:07
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from 56d977c to be3e4a0 Compare July 13, 2026 15:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ec3a5ec15

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/skill.py Outdated
@daryllimyt
daryllimyt force-pushed the daryl/eng-1524-resolution-effective-versions branch from be3e4a0 to ae0bba9 Compare July 13, 2026 16:25
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 8ec3a5e to 38c44ef Compare July 13, 2026 16:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38c44efe41

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tracecat/workspace_sync/adapters/skill.py
Legacy rows written by old pods still carry slug IS NULL and project
their name as the effective slug, which the partial unique index cannot
see. Close the paths that could mint a duplicate effective slug or bind
against the wrong owner:

- restore_version validates the restored package slug against live rows
  (same pre-check as the publish paths) before minting the new version.
- Workspace-sync skill renames check availability on
  coalesce(slug, name) so a mapped rename cannot land on a legacy row's
  effective slug (NameSwapPlan gains an optional availability_column);
  unmapped imports resolve through get_skill_by_slug so exact owners
  win and legacy-only ambiguity fails loud.
- Dependency-closure exports dedupe per requested slug with
  exact-owner preference and fail loud (ambiguous_skill_slug) when only
  legacy rows contend, instead of emitting duplicate specs for one slug.
- Preset-sync skill bindings resolve through the runtime resolver
  (new SkillService.get_skill_by_slug, extracted from
  get_skill_by_identifier): exact slug owners win over legacy rows and
  ambiguous legacy-only matches fail loud.
- Both restore routes map slug conflicts to 409 skill_slug_conflict
  instead of escaping as unhandled validation errors.
- Seeded drafts carry the allocated live slug: duplicate display-name
  creates seed SKILL.md with the suffixed slug, and duplicate-name
  uploads get their manifest name rewritten, so publish no longer hits
  skill_slug_conflict on untouched drafts.
Full workspace exports reached _projection_from_skills without the
exact-owner/legacy dedupe that project_dependency_refs applies, so an
expand-window canonical+legacy pair emitted two specs claiming one
slug. Factor the dedupe into a shared helper used by both projection
paths: exact slug owners win, legacy-only contention fails loud with
ambiguous_skill_slug.
A preset version bound to a legacy skill (slug IS NULL) whose name is
owned as a slug by a different live skill exported the binding as that
non-unique effective slug; the dependency closure then resolved it to
the canonical owner, silently rebinding the preset on import. Detect
the shadowed state with a batched EXISTS probe and fail loud with
shadowed_skill_binding during the expand window.
Sync schemas accepted any non-empty string as a skill slug, so a
manifest slug with uppercase or spaces imported verbatim into
Skill.slug while the strict runtime resolver returned None — the
preset's skill binding silently dropped although the pull succeeded.
Apply the canonical SkillName shape to the skill resource spec and
preset binding ref slugs so invalid manifests fail loud as parse
diagnostics before any database write.
@daryllimyt
daryllimyt force-pushed the daryl/eng-1532-skill-slug-runtime branch from 38c44ef to 1c12315 Compare July 13, 2026 19:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c123156e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

description="Current package locator used for cross-references.",
)
name: str = Field(min_length=1, description="Human-readable skill name.")
name: str = Field(min_length=1, description="User-facing display name.")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cap synced skill display names at DB length

Because the importer now persists this field to Skill.name, a skill.yml with a valid slug but a display name longer than 64 characters passes Pydantic parsing and dependency validation, then hits the String(64) database column during insert/update (name=spec.name) and fails as an unhandled DB error instead of a sync validation diagnostic. Add the same 64-character limit here or validate before assigning it.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents LLM agents breaking Breaking changes refactor Refactoring skills

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant