Repository navigation
Look up a Step skill in ~/.thirdshift/skills - #1413
Merged
Merged
Conversation
…hand A Custom process skill is resolved in the repository first, then ~/.thirdshift/skills/<name>/SKILL.md, then the thirdshift-<name> Factory skill. Home skills are linked into the worktree like the Factory skills, and a repository skill of the same name wins.
A Trial binds that folder and not ~/.thirdshift/skills, so a link at the home directory was unreadable. The worktree link now points at the copy. check and the session prompt still name the home file.
# Conflicts: # docs/guide.md # site/docs/index.html # tests/process.rs
The Trial sandbox binds the Factory skills folder, not ~/.thirdshift/skills. The readability test invoked bwrap to prove the copy was visible under those binds. CI does not install bwrap, so the session exited 127. The published tree is plain files in that folder.
This was referenced Oct 27, 2026
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 Step's skill is resolved in this order, then linked into the worktree the way the Factory skills are:
thirdshift process checkprints the home file, which is where the skill was found. The session prompt names that same file. The worktree link points at the copy. A Trial already binds the Factory skills folder and does not bind~/.thirdshift/skills, so the copy is what the sandbox can read.A repository skill of the same name wins and is left in place. A skill file that resolves outside the directory being searched is not a match.
Seam:
thirdshift processandthirdshift process checkthroughtests/process.rs.skills::findis the same lookupthirdshift skilluses.Evidence
Before: a worktree link at
~/.thirdshift/skills/house-styleis readable on the host and unreadable inside the Trial's binds. With/usr,/lib,/lib64, and/binmounted only so/usr/bin/testcan run, this exits 1:The reviewer's command as written (
bwrap … -- test -f …with only the repository, an empty factory directory, and a fresh home) exits 1 withbwrap: execvp test: No such file or directory, becausetestis not in that mount set. The run above is the same three skill binds with atestbinary that can execute, and it fails because the skill file is not there. Mounting~/.thirdshift/skillsmakes that same check exit 0.After:
cargo test --test process -- a_home_skill_link_is_readable_in_the_trial_sandboxpasses. The session readsSKILL.mdandnotes.mdthrough.claude/skills/house-style, the link target is inside the Factory skills folder, a sibling symlink that leaves the home skills directory is not copied, and the samebwrapbinds can readSKILL.md. The prompt still names the home file.cargo test --bin thirdshift skills::tests— 4 passed.cargo clippy --all-targets -- -D warnings— passed.npm run docs:check --prefix site— passed./usr/bin/time -p scripts/affected-tests origin/issue-877ona3d87a08exited 0 in real 2925.56s, compilation included.npm test --prefix sitepassed 50 tests.cargo nextest runpassed 3120 tests, skipped 70, in 2554.229s.After merging
origin/issue-877(93d6f8ed, pull request Custom process: named throwaway worktrees and parallel groups #1409),cargo test --test processpassed 31 tests (1 ignored) andnpm run docs:check --prefix sitepassed. That merge did not changesrc/skills.rs.link_intoruns once per Step worktree, including a parallel group.Merge Danger
Door: two-way
Reverting the commits removes the home-skill lookup and the published copy. Exclude lines already written stay, as the Factory
thirdshift-*lines do.Blast Radius: sessions
Every session that links Factory skills also links home skills, including Ticket runs, Resumes, the security-review fallback, standalone
thirdshift skill, and Trials. A Trial can read those published copies because they sit in the Factory skills folder it already binds.checkstill prints the home path.Unaddressed findings
Standards
Duplicated Code in
src/skills.rs(repository_skills,read_home_skills,repository_has_skill). The two directory scans already disagree on purpose: a non-UTF-8 repository directory name fails the lookup (repository_skills,entry.file_name().into_string().map_err), and a non-UTF-8 home name is skipped (read_home_skills,let Ok(name) = entry.file_name().into_string() else { continue; }). The reviewer said that split is not a claim that either policy is wrong.repository_has_skillprobesSKILL.mdfor one name and does notread_dirthe project skills directory. Listing that directory failsskills::tests::links_in_ordinary_directories_without_directory_read_permission, which sets the directory mode to0o300.Duplicated Code in
docs/guide.md. Standalone skills and Custom processes both state the lookup order. The acceptance criterion is thatdocs/guide.mddocuments that order, and the Custom process section is where a process reader looks. The process wording now matches the standalone wording: Factory exact name, then.agents/skills/<name>/SKILL.md, or.claude/skills/<name>/SKILL.mdwhen only that copy exists, then~/.thirdshift/skills/<name>/SKILL.md, thenthirdshift-<name>. The earlier drift ("and.claude/skills" against "or.claude/skills… when only that copy exists") is gone.Spec
skills::findandskills::link_intoontothirdshift skill, Ticket runs, Resumes, the security-review fallback, and Trials. The spec says a home skill is linked into the worktree the way the Factory skills are (ADR-0012). ADR-0012's mechanism is that sharedlink_into, called fromsrc/session.rs(within_sandboxed,checked_within, and the resume path) and fromsrc/skill.rs. The dangling Trial link was the part that was wrong.tests/process.rsa_home_skill_link_is_readable_in_the_trial_sandboxkeeps the reviewer's binds (repository, Factory skills folder, fresh home) and passes: the link points at the published copy, andtest -finside those binds succeeds.Security
No unaddressed findings introduced by this change. Guidance-mode review of
src/skills.rsagainst the supply-chain plugin-trust and agent-instruction attack classes: home skills are same-user operator content (per the skill guidance, intended installation of same-user plugins is not a privilege boundary, and sessions run fully trusted per ADR-0013), so no cross-principal boundary is crossed. Confinement holds on both new paths:findresolves names by exact lookup only, home and repository entries that canonicalize outside the searched directory are skipped (resolved_inside), home skill directory names are restricted to a single path component, and the published copy drops symlinks that leave the home skills directory. Evidence:cargo test --bin thirdshift skills::tests(4 passed),cargo test --test process -- skill(5 passed, including the outside-directory symlink cases), plus a localgit check-ignoreprobe confirming the per-name.git/info/excludelines match. No fix was needed, so no commits were made in this review.Security review outcome
No unaddressed introduced findings.
Review coverage
Neither axis left a changed file unread.
site/docs/index.htmlwas excluded as generated output ofdocs/guide.md(npm run docs:check --prefix siteexited 0; the placeholder is escaped as~/.thirdshift/skills/<name>/SKILL.md).Closes #1384
Built with grok grok 1.0.70 (f50904eaee6c) [stable] · default model · default effort