Skip to content

fix(skills): skip mirror fan-out to agents that read the universal store - #3325

Open
santhiprakash wants to merge 1 commit into
heygen-com:mainfrom
santhiprakash:fix/skills-mirror-skip-pi
Open

fix(skills): skip mirror fan-out to agents that read the universal store#3325
santhiprakash wants to merge 1 commit into
heygen-com:mainfrom
santhiprakash:fix/skills-mirror-skip-pi

Conversation

@santhiprakash

Copy link
Copy Markdown
Contributor

What

The global skills mirror no longer fans out into agent directories whose agent already discovers the universal ~/.agents/skills store globally. Currently that set is { pi }.

Why

Pi discovers skills from both ~/.pi/agent/skills/ and ~/.agents/skills/ as global locations (see pi's packages/coding-agent/docs/skills.md → Locations). The global install already writes real files into the universal store, so mirroring an additional per-agent copy into ~/.pi/agent/skills makes Pi discover every HyperFrames skill twice. Pi then reports a name collision, keeps the ~/.pi/agent/skills entry, and skips the universal entry:

"hyperframes" collision:
  ✓ auto (user) ~/.pi/agent/skills/hyperframes/SKILL.md
  ✗ ~/.agents/skills/hyperframes/SKILL.md (skipped)

Fixes #3294 (the deterministic duplicate-discovery half; the broader target-control surface proposed there is left for maintainers to design).

How

  • Added a UNIVERSAL_STORE_READERS capability set in packages/cli/src/utils/skillsMirror.ts (currently pi) and skip those agents in the fan-out loop, before the installed-marker check.
  • The set deliberately lives in the mirror module, not in agentDirs.generated.ts: that file is @generated from vercel-labs/skills and a plain (agent, base, sub) list — it cannot carry per-agent capabilities, and any hand edit would be clobbered by the next gen:agent-dirs sync.
  • Minimal by design: no cleanup of pre-existing ~/.pi/agent/skills entries from earlier runs. Removing entries in a directory we no longer manage would risk deleting user-placed content (the mirror's replace-on-refresh precedent only applies to dirs it still mirrors). A one-time stale-link cleanup can be a follow-up if maintainers want it.

Test plan

  • New test in skillsMirror.test.ts: with both Pi (~/.pi/agent) and cursor markers present, mirrored contains cursor and not pi, and no ~/.pi/agent/skills/hyperframes entry is created.
  • Full skills-related suites pass: skillsMirror, skillsManifest, skillsUpdateCheck, commands/skills — 116/116.
  • oxlint / oxfmt --check clean on changed files; repo check-skill-mirror invariant still passes; lefthook pre-commit gates (format, fallow against synced main, typecheck after generating core runtime artifacts) pass.
  • Manual testing performed (not applicable here — reproduction requires a Pi + HyperFrames co-install; covered by the deterministic unit test above)

@miga-heygen miga-heygen 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.

LGTM — clean, minimal fix.

The problem is well-defined: Pi discovers ~/.agents/skills natively, so the mirror's per-agent fan-out created a duplicate that Pi resolved by keeping the per-agent copy and skipping the universal one — the wrong winner.

The fix is a single continue in the fan-out loop gated on a UNIVERSAL_STORE_READERS set. Good design choices:

  • Set lives in skillsMirror.ts, not in agentDirs.generated.ts. The generated file is a plain (agent, base, sub) list synced from vercel-labs/skills — it can't carry per-agent capabilities, and a hand edit would be clobbered. Correct placement.
  • No stale-entry cleanup. Removing entries in a directory the mirror no longer manages risks deleting user-placed content. The replace-on-refresh precedent only applies to dirs still mirrored. Right call.
  • Test is specific. Seeds both Pi and Cursor markers, asserts Pi is excluded and Cursor included, verifies no ~/.pi/agent/skills/hyperframes entry was created. Covers both the positive and negative cases.

No SSOT concerns — the skip check is one line, one source of truth for which agents are universal-store readers, and the comment explains the invariant it protects.

Review by Miga

@miguel-heygen

Copy link
Copy Markdown
Collaborator

@santhiprakash sign the commit pls

Pi discovers both ~/.pi/agent/skills and the universal ~/.agents/skills
globally, so the per-agent mirror copy collided with the universal copy
and Pi skipped the universal entry on name conflict (heygen-com#3294). Skip agents
that natively consume the universal store instead of fanning out to them.

Fixes heygen-com#3294
@santhiprakash
santhiprakash force-pushed the fix/skills-mirror-skip-pi branch from 6c9d5c6 to 4dc197d Compare August 20, 2026 05:46
@santhiprakash

Copy link
Copy Markdown
Contributor Author

Done — commits are now signed. You should see the Verified badge on the latest commit.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global skill mirroring should avoid redundant agent directories and provide target controls

3 participants