Skip to content

fix(skill-registry): mirror Pi-resolved loaded skills #369

Open

Description

@barbatdev

Problem

The generated .atl/skill-registry.md does not mirror the skills Pi actually loaded.

The registry currently scans a fixed collection of loose user and project directories. As a result, skills loaded through npm packages or package-declared pi.skills paths may appear in Pi's <available_skills> block while remaining absent from the registry consumed by subagent delegation.

This produces false skill_resolution: none results even though the parent session has the required skill available.

Current proposals

PR #281 adds direct scanning of global npm node_modules/*/skills directories.

PR #285 reads literal directories from the project root package.json pi.skills array.

Both demonstrate the missing behavior, but both partially duplicate Pi's package/resource loader. This creates parity gaps around:

  • global versus project-local npm installs;
  • scoped, unscoped, and symlinked package layouts;
  • package manifest globs and exclusions;
  • package and resource filters;
  • disabled skills;
  • custom package-declared paths;
  • resource reloads and watcher reconciliation.

The two PRs also overlap in the same registry generation and watcher code.

Expected behavior

The registry should use Pi's resolved loaded-skill set as the authority for Pi-managed resources, preserving each exact skill path and source metadata.

Intentional cross-ecosystem loose skill roots may remain as additional sources, but package discovery and filtering must not be independently reimplemented.

Acceptance criteria

  • Every skill Pi exposes as loaded is represented by its exact SKILL.md path in .atl/skill-registry.md.
  • Global and project-local npm packages are supported.
  • Package manifest paths, globs, exclusions, filters, and disabled resources match Pi's resolution.
  • Inactive or filtered skills are not indexed as active package resources.
  • Existing project-over-user duplicate precedence remains deterministic.
  • Intentional non-Pi loose skill roots remain supported.
  • Resource reload or the next agent turn refreshes the registry without stale package watchers.
  • Tests cover scoped and unscoped packages, project-local packages, custom pi.skills paths, exclusions, disabled resources, duplicate names, and reload behavior.

Runtime authority

before_agent_start.systemPromptOptions.skills exposes Pi's already-resolved skill records, including exact file paths and source information. The implementation should consume that authority rather than recreate package discovery rules.

Related pull requests

Activity

  1. barbatdev commented on Aug 18, 2026

    @barbatdev
    SponsorContributorAuthor

    Approved. This is one resource-authority invariant: .atl/skill-registry.md must mirror the skills Pi resolved as loaded, rather than independently recreating package discovery and filtering.

    PRs #281 and #285 both demonstrate valid missing cases, but their current implementations are overlapping partial scanners. Consolidate the work into one PR that consumes Pi-resolved skill records, preserves intentional cross-ecosystem loose roots, and adds the acceptance coverage listed above.

    Keep both existing PRs open until the consolidation vehicle is selected.

  2. danielgap commented on Sep 21, 2026

    @danielgap
    Contributor

    Taking this one. Credit first: @ChaoXu1997, your #281 and #285 demonstrated the gap concretely, and the runtime-authority direction in this issue builds on that work. If you are already reworking them toward before_agent_start.systemPromptOptions.skills, tell me and I will stand down or take a slice. @barbatdev thanks for the precise writeup, I will treat the acceptance criteria as the contract.

    Plan:

    1. Registry generation consumes Pi's resolved skill records as the single authority for Pi-managed resources (exact SKILL.md paths and source metadata preserved), instead of reimplementing package discovery.
    2. Intentional non-Pi loose skill roots stay as additional sources, project-over-user precedence unchanged.
    3. The reload path refreshes from the resolved set with no package watchers left behind.
    4. Tests per the issue checklist: scoped and unscoped packages, project-local packages, custom pi.skills paths, exclusions, disabled resources, duplicate names, reload behavior.

    PR follows on a branch off main.

  3. pablolemosochandio commented on Sep 27, 2026

    @pablolemosochandio

    Adding one more case to the acceptance matrix, from a PI_CODING_AGENT_DIR setup.

    Setup: PI_CODING_AGENT_DIR=/Users/lemos_pab/.gentle-shell/agent (gentle-shell launcher), so Pi resolves user skills from <agent-dir>/skills rather than ~/.pi/agent/skills.

    Repro: a user skill at <agent-dir>/skills/codegraph/SKILL.md. Pi loads it and it appears in <available_skills>, but .atl/skill-registry.md omits it — <agent-dir>/skills is not even listed under ## Sources scanned.

    Cause: extensions/skill-registry.ts:54 userSkillDirs() hardcodes join(home, ".pi/agent/skills") at line 57 instead of joining the resolved agent dir. Pi's own loader uses join(this.agentDir, "skills") (core/package-manager.js:713, :1964), so the two disagree on any host that sets PI_CODING_AGENT_DIR.

    Why it matters here: neither route reaches the skill. The registry misses it, and the protocol fallback search (assets/orchestrator-skills.md, "Intent-Driven Skill Discovery" step 3, which lists ./skills, .pi/skills, .agents/skills, …) never consults the agent dir either. A delegating parent therefore passes no path, and subagents report the false skill_resolution: none described above.

    Relevant to the fix: consuming before_agent_start.systemPromptOptions.skills covers this case for free, since Pi already resolves the agent dir. Worth one explicit test with PI_CODING_AGENT_DIR pointing at a non-default directory.

    Two notes that may be useful:

    • Same class, different subsystem: bug(launcher): auto-provision setup fails on CodeGraph "path escapes allowed roots" — infinite first-run loop #1388 has install --agent pi --scope global writing to ~/.pi/agent/agents/ while CodeGraph's allowed roots stay scoped to PI_CODING_AGENT_DIR, which loops the first-run setup. Both look like the resolved agent dir being bypassed in favor of ~/.pi/agent.
    • Until this lands I use a symlink into a scanned-but-runtime-dead root (~/.config/agents/skills) so the path reaches the registry without double-registering in Pi. Verified: the registry sees one entry via the symlink and loadSkills sees one entry from the agent dir, with no collision — Pi dedupes by canonicalized real path. Not a proposed solution, just documenting the interim workaround so nobody re-debugs it.
  4. danielgap commented on Sep 27, 2026

    @danielgap
    Contributor

    Thanks for this case, @pablolemosochandio — it is exactly the shape the open PR #1320 was built for, and your read is right.

    Confirmed: the PR consumes before_agent_start.systemPromptOptions.skills as the runtime authority, so a skill that only exists under a non-default PI_CODING_AGENT_DIR reaches the registry through the mirror, with no agent-dir-specific scanning code anywhere.

    I added your case as the explicit test you suggested (496a6d6): isolated HOME, PI_CODING_AGENT_DIR at a non-default directory, skill at <agent-dir>/skills/codegraph/SKILL.md, and the registry must list it through the runtime mirror. It also counter-proves the failure mode you described: with no resolved set, the same skill is unreachable by every loose root, so if anyone ever reintroduces a hardcoded agent-dir scan path, that assertion fails.

    Your symlink workaround should become unnecessary once this lands. And good catch on #1388 being the same root class (resolved agent dir bypassed in favor of ~/.pi/agent) — worth keeping that lens on the install-side surfaces too.

  5. luispino32 commented on Oct 24, 2026

    @luispino32

    Adding one concrete installed-package case to the matrix, from a Pi package that ships its own skills.

    Setup: gentle-shell 4.3.0 (Pi agent dir taken from PI_CODING_AGENT_DIR), with a package installed from git. Its package.json declares:

    "pi": { "extensions": ["./arnes/extension/index.ts"], "skills": ["./skills"] }

    Observed: in every session the package's skill (code-map-web) is listed in <available_skills> — Pi resolves it from the package. But in a documented project (a repository where that package does its work, with no local ./skills), the generated .atl/skill-registry.md lists only the user-scope skill, and ## Sources scanned shows skills, <agentDir>/skills, ~/.agents/skills — no package path. The same skill is listed in the package's own repo, where a loose ./skills root exists, which matches the loose-root behavior described above.

    Why this one bites: the project where the skill matters most (the documented project) is exactly the one where the delegating parent finds no path to pass, so subagents report skill_resolution: none while the parent has the skill loaded. The current workaround is copying the skill into a scanned loose root, which then drifts from the package version.

    Expected: mirroring before_agent_start.systemPromptOptions.skills (as this issue proposes) covers this case with no extra scanning code; PR #1320's direction should reach it. Happy to re-test once it lands.

    Repro details if useful: package docweb@master (57ac0e2), skill at <package>/skills/code-map-web/SKILL.md, registry at <project>/.atl/skill-registry.md, same symptom on both the ~/.pi/agent and the .gentle-shell/agent profile (the loose roots of each are scanned; the package is not).

  6. danielgap commented on Oct 24, 2026

    @danielgap
    Contributor

    Thanks @luispino32, this is a great case to have on the matrix, and your read is right.

    An installed package skill is exactly what #1320 covers: it takes before_agent_start.systemPromptOptions.skills as the authority and writes each skill to the registry with its exact SKILL.md path and package origin. So code-map-web should show up in the documented project's .atl/skill-registry.md even with no loose ./skills root, and the copy-and-drift workaround goes away. No package scanning or pi.skills reparsing is involved.

    The PR has conflicts with main right now, so I'll rebase it first and ping you here when it's ready for your re-test. Your docweb@master (57ac0e2) repro is a good acceptance check.

  7. danielgap commented on Oct 24, 2026

    @danielgap
    Contributor

    @luispino32 #1320 is up to date with main now (head 217c6f4f5), with CI green on Ubuntu, macOS, and Windows and no conflicts.

    It's ready for your re-test whenever you have a moment. If code-map-web still doesn't show up in the documented project's .atl/skill-registry.md, the ## Sources scanned section and the package path would be the most useful things to share.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions