Repository navigation
fix(skill-registry): mirror Pi-resolved loaded skills #369
Description
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.mdpath 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.skillspaths, 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.
Activity
barbatdev commentedon Aug 18, 2026
Approved. This is one resource-authority invariant:
.atl/skill-registry.mdmust 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.
danielgap commentedon Sep 21, 2026
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:
SKILL.mdpaths and source metadata preserved), instead of reimplementing package discovery.pi.skillspaths, exclusions, disabled resources, duplicate names, reload behavior.PR follows on a branch off
main.fix(skill-registry): add pure pi-resolved skill seam (Gentleman-Progr…
fix(skill-registry): capture pi-resolved skills per agent turn (Gentl…
test(skill-registry): cover global, project-local, and custom resolve…
docs(skill-registry): document the runtime-authority contract (Gentle…
pablolemosochandio commentedon Sep 27, 2026
Adding one more case to the acceptance matrix, from a
PI_CODING_AGENT_DIRsetup.Setup:
PI_CODING_AGENT_DIR=/Users/lemos_pab/.gentle-shell/agent(gentle-shell launcher), so Pi resolves user skills from<agent-dir>/skillsrather 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.mdomits it —<agent-dir>/skillsis not even listed under## Sources scanned.Cause:
extensions/skill-registry.ts:54userSkillDirs()hardcodesjoin(home, ".pi/agent/skills")at line 57 instead of joining the resolved agent dir. Pi's own loader usesjoin(this.agentDir, "skills")(core/package-manager.js:713,:1964), so the two disagree on any host that setsPI_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 falseskill_resolution: nonedescribed above.Relevant to the fix: consuming
before_agent_start.systemPromptOptions.skillscovers this case for free, since Pi already resolves the agent dir. Worth one explicit test withPI_CODING_AGENT_DIRpointing at a non-default directory.Two notes that may be useful:
install --agent pi --scope globalwriting to~/.pi/agent/agents/while CodeGraph's allowed roots stay scoped toPI_CODING_AGENT_DIR, which loops the first-run setup. Both look like the resolved agent dir being bypassed in favor of~/.pi/agent.~/.config/agents/skills) so the path reaches the registry without double-registering in Pi. Verified: the registry sees one entry via the symlink andloadSkillssees 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.test(skill-registry): cover a skill resolved from a non-default PI_CO…
danielgap commentedon Sep 27, 2026
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.skillsas the runtime authority, so a skill that only exists under a non-defaultPI_CODING_AGENT_DIRreaches 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_DIRat 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.
luispino32 commentedon Oct 24, 2026
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. Itspackage.jsondeclares: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.mdlists only the user-scope skill, and## Sources scannedshowsskills,<agentDir>/skills,~/.agents/skills— no package path. The same skill is listed in the package's own repo, where a loose./skillsroot 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: nonewhile 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/agentand the.gentle-shell/agentprofile (the loose roots of each are scanned; the package is not).danielgap commentedon Oct 24, 2026
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.skillsas the authority and writes each skill to the registry with its exactSKILL.mdpath and package origin. Socode-map-webshould show up in the documented project's.atl/skill-registry.mdeven with no loose./skillsroot, and the copy-and-drift workaround goes away. No package scanning orpi.skillsreparsing 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.danielgap commentedon Oct 24, 2026
@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-webstill doesn't show up in the documented project's.atl/skill-registry.md, the## Sources scannedsection and the package path would be the most useful things to share.