feat(workspace): use EnterWorktree for self-repo project isolation - #261
feat(workspace): use EnterWorktree for self-repo project isolation#261fonta-rh wants to merge 17 commits into
Conversation
|
Skipping CI for Draft Pull Request. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: fonta-rh The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
WalkthroughThe workspace plugin now supports self-repository worktree creation, resumption, cleanup, and frontmatter updates. It also adds recurring update scheduling, background documentation updates, and version 0.2.2 metadata. ChangesWorkspace lifecycle
Update automation
Plugin release metadata
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5 | ❌ 6❌ Failed checks (6 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Tools execution failed with the following error: Failed to run tools: 14 UNAVAILABLE: read ECONNRESET Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/workspace/skills/close-project/SKILL.md`:
- Around line 164-167: Update the clean-worktree path in the close-project
procedure to invoke AskUserQuestion for final confirmation before removing the
worktree and deleting the local branch. If the user declines, stop the removal
and branch-operation flow; preserve the existing commit-and-push and
keep-worktree paths.
- Around line 189-190: Update the close-project workflow around Step 2.5 and
Step 3b so an externally missing worktree is treated as successfully removed:
clear the frontmatter worktree_path even when removal is skipped because the
path does not exist. Preserve silent handling of the absent path while ensuring
completed closure cannot retain the stale location.
- Around line 146-153: Update the close-project status collection in the
worktree cleanup flow to validate that P.frontmatter.worktree_path exists and
check the exit status of every Git command. Use git rev-parse --verify
'@{upstream}' to distinguish no_upstream from other failures, and stop before
prompting or cleanup when any status command fails; preserve the existing
dirty/ahead/no-upstream derivation from section 2.5a.
- Around line 161-165: Update the commit-and-push workflow in the close-project
instructions to stop immediately when either operation fails; re-run the
worktree status checks, then ask whether to retry, keep the worktree, or discard
changes before allowing removal. Preserve the existing removal behavior only
after successful operations or an explicit user choice to proceed.
- Around line 167-187: Update the close-project cleanup instructions to resolve
and run fallback Git commands from the owning checkout or common Git directory,
not the current session directory. Require confirmation before removing a clean
worktree, and stop before branch deletion or frontmatter updates when
ExitWorktree or any Git command fails, including refusal due to remaining
changes. Add lifecycle tests covering cleanup and missing-worktree recovery as
required by CONTRIBUTING.md.
In `@plugins/workspace/skills/resume-project/SKILL.md`:
- Around line 109-119: Update the Step 2.5 summary rendering to use the actual
worktree state rather than blindly using P.frontmatter.worktree_path: omit the
active worktree details when the user continues without one, refresh the
in-memory path after successful recreation, and show the active-worktree/session
message only when EnterWorktree succeeds.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 3ea06546-9211-4a9e-9c57-07e586ede355
📒 Files selected for processing (3)
plugins/workspace/skills/close-project/SKILL.mdplugins/workspace/skills/new-project/SKILL.mdplugins/workspace/skills/resume-project/SKILL.md
| 1. Check dirty state inside the worktree: | ||
|
|
||
| ```bash | ||
| git -C <P.frontmatter.worktree_path> status --porcelain | ||
| git -C <P.frontmatter.worktree_path> rev-list --count @{upstream}..HEAD 2>/dev/null | ||
| ``` | ||
|
|
||
| Derive status using the same logic as 2.5a (dirty/ahead/no-upstream). |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target file outline ---'
ast-grep outline plugins/workspace/skills/close-project/SKILL.md 2>/dev/null || true
printf '%s\n' '--- target section ---'
sed -n '120,210p' plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- resume script references ---'
rg -n -C 8 'rev-parse|upstream|status --porcelain|worktree_path|remove|push' plugins/workspace/scripts/resume-project.py
printf '%s\n' '--- related close-project references ---'
rg -n -C 5 'status --porcelain|rev-list|upstream|worktree_path|remove|push|2\.5a|self-repository' plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- relevant tests/files ---'
rg -n -C 3 'close-project|resume-project|missing-worktree|dirty|no-upstream|upstream' plugins/workspace tests 2>/dev/null | head -300 || trueRepository: openshift-eng/edge-tooling
Length of output: 37537
🏁 Script executed:
#!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cd "$tmpdir"
git init -q repo
cd repo
git config user.email review@example.invalid
git config user.name review
printf 'x\n' > file
git add file
git commit -qm initial
git branch -M main
printf '%s\n' '--- no-upstream behavior ---'
set +e
git status --porcelain
status_rc=$?
git rev-list --count '@{upstream}..HEAD' >/tmp/review-rev-list.out 2>/tmp/review-rev-list.err
rev_rc=$?
git rev-parse --verify '@{upstream}' >/tmp/review-rev-parse.out 2>/tmp/review-rev-parse.err
parse_rc=$?
set -e
printf 'status_rc=%s\nrev_list_rc=%s\nrev_parse_rc=%s\n' "$status_rc" "$rev_rc" "$parse_rc"
printf 'rev_list_stderr='; cat /tmp/review-rev-list.err
printf 'rev_parse_stderr='; cat /tmp/review-rev-parse.err
printf '%s\n' '--- invalid worktree behavior ---'
set +e
git -C "$tmpdir/does-not-exist" status --porcelain >/tmp/review-status.out 2>/tmp/review-status.err
invalid_status_rc=$?
git -C "$tmpdir/does-not-exist" rev-list --count '@{upstream}..HEAD' >/tmp/review-invalid-rev-list.out 2>/tmp/review-invalid-rev-list.err
invalid_rev_rc=$?
set -e
printf 'invalid_status_rc=%s\ninvalid_rev_list_rc=%s\n' "$invalid_status_rc" "$invalid_rev_rc"
printf 'invalid_status_stderr='; cat /tmp/review-status.err
printf 'invalid_rev_list_stderr='; cat /tmp/review-invalid-rev-list.err
printf '%s\n' '--- missing upstream ref behavior ---'
git remote add origin "$tmpdir/remote.git" 2>/dev/null || true
git config --unset-all branch.main.remote 2>/dev/null || true
git config --unset-all branch.main.merge 2>/dev/null || true
git config branch.main.remote origin
git config branch.main.merge refs/heads/missing
set +e
git rev-list --count '@{upstream}..HEAD' >/tmp/review-missing-upstream.out 2>/tmp/review-missing-upstream.err
missing_rev_rc=$?
git rev-parse --verify '@{upstream}' >/tmp/review-missing-parse.out 2>/tmp/review-missing-parse.err
missing_parse_rc=$?
set -e
printf 'missing_upstream_rev_list_rc=%s\nmissing_upstream_rev_parse_rc=%s\n' "$missing_rev_rc" "$missing_parse_rc"
printf 'missing_upstream_rev_list_stderr='; cat /tmp/review-missing-upstream.err
printf 'missing_upstream_rev_parse_stderr='; cat /tmp/review-missing-parse.errRepository: openshift-eng/edge-tooling
Length of output: 1071
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- full workflow sections ---'
sed -n '1,115p' plugins/workspace/skills/close-project/SKILL.md
sed -n '135,205p' plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- resume-project.py relevant implementation ---'
sed -n '1,240p' plugins/workspace/scripts/resume-project.py
printf '%s\n' '--- close-project tests and references ---'
rg -n -C 5 'close-project|resume-project|worktree_path|rev-list|rev-parse|status --porcelain' . -g '!node_modules' -g '!dist' -g '!build' | head -500Repository: openshift-eng/edge-tooling
Length of output: 50384
Handle status-command failures before cleanup
git rev-list --count '@{upstream}..HEAD' returns nonzero both when no upstream exists and when the worktree path or upstream reference is invalid. Check that <P.frontmatter.worktree_path> exists and check each Git command’s exit status. Use git rev-parse --verify '@{upstream}' to identify no_upstream. Stop before prompting or removing when status collection fails.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/close-project/SKILL.md` around lines 146 - 153,
Update the close-project status collection in the worktree cleanup flow to
validate that P.frontmatter.worktree_path exists and check the exit status of
every Git command. Use git rev-parse --verify '@{upstream}' to distinguish
no_upstream from other failures, and stop before prompting or cleanup when any
status command fails; preserve the existing dirty/ahead/no-upstream derivation
from section 2.5a.
| If "commit and push": help the user commit and push. For | ||
| `no_upstream` branches: `git -C <worktree_path> push -u fork <branch>`. | ||
|
|
||
| If the worktree is clean (or the user chose to commit and push), proceed | ||
| to removal. If the user chose to keep the worktree, skip to step 5. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- target skill outline ---'
ast-grep outline plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- relevant workflow ---'
sed -n '120,210p' plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- tool and status references ---'
rg -n -C 3 'commit and push|git status|git commit|git push|remove|worktree|confirmation|failure|stop' plugins/workspace/skills/close-project/SKILL.md
printf '%s\n' '--- contribution and skill guidelines references ---'
rg -n -C 2 'worktree|commit|push|destructive|confirmation|failure|status|test' CONTRIBUTING.md plugins/docs/SKILL-GUIDELINES.mdRepository: openshift-eng/edge-tooling
Length of output: 22910
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
p = Path("plugins/workspace/skills/close-project/SKILL.md")
text = p.read_text()
start = text.index("**2.5s. Self-repo worktree cleanup**")
end = text.index("**2.5e. Remove skill symlinks**", start)
section = text[start:end]
print("--- self-repo cleanup decision flow ---")
for i, line in enumerate(section.splitlines(), 1):
if any(term in line.lower() for term in (
"commit and push", "proceed", "failure", "fail", "status", "remov",
"keep worktree", "askuserquestion"
)):
print(f"{i:03}: {line}")
print("--- required safeguards ---")
checks = {
"rechecks status after commit/push": any(
"re-run" in line.lower() or "recheck" in line.lower()
for line in section.splitlines()
),
"stops on commit/push failure": any(
"stop" in line.lower() and "fail" in line.lower()
for line in section.splitlines()
),
"proceeds after commit/push selection": (
'If "commit and push"' in section
and "proceed" in section
),
}
for name, value in checks.items():
print(f"{name}: {value}")
PY
printf '%s\n' '--- closure steps after cleanup ---'
sed -n '225,265p' plugins/workspace/skills/close-project/SKILL.mdRepository: openshift-eng/edge-tooling
Length of output: 2890
Stop when commit or push fails.
If either operation fails, do not proceed to removal. Re-run the worktree status checks and ask whether to retry, keep the worktree, or discard changes. A failed commit can leave dirty files, and a failed push can leave committed changes unpushed. Per CONTRIBUTING.md, changed skill workflows must handle failure paths, including cleanup.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/close-project/SKILL.md` around lines 161 - 165,
Update the commit-and-push workflow in the close-project instructions to stop
immediately when either operation fails; re-run the worktree status checks, then
ask whether to retry, keep the worktree, or discard changes before allowing
removal. Preserve the existing removal behavior only after successful operations
or an explicit user choice to proceed.
| **If `P.frontmatter.worktree_path` is present (self-repo worktree):** | ||
| Show the worktree status: | ||
|
|
||
| > **Worktree:** `<worktree_path>` → branch `<branch>` (active) | ||
|
|
||
| If Step 2.5 entered the worktree successfully, add: "Session is in the | ||
| worktree — code changes apply to branch `<branch>`." | ||
|
|
||
| If the worktree was missing and recreated, note: "Worktree was missing | ||
| and has been recreated at `<new-path>`." | ||
|
|
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file="plugins/workspace/skills/resume-project/SKILL.md"
printf '%s\n' '--- target file outline ---'
ast-grep outline "$file" 2>/dev/null || true
printf '%s\n' '--- relevant sections ---'
cat -n "$file" | sed -n '1,150p'
printf '%s\n' '--- worktree-related references ---'
rg -n -C 4 'EnterWorktree|worktree_path|Continue without worktree|recreated|Step 2\.5' \
plugins/workspace plugins/docs CONTRIBUTING.md 2>/dev/null || true
printf '%s\n' '--- workflow skill files and tool declarations ---'
git ls-files 'plugins/workspace/skills/**/SKILL.md' 'plugins/docs/SKILL-GUIDELINES.md' 'CONTRIBUTING.md'
rg -n -C 3 '^allowed-tools:|^name:|^description:' plugins/workspace/skills/*/SKILL.md 2>/dev/null || trueRepository: openshift-eng/edge-tooling
Length of output: 29093
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- exact EnterWorktree definitions and call sites ---'
rg -n -C 8 'EnterWorktree|enter.*worktree|worktree.*missing|missing.*worktree' \
plugins .github scripts 2>/dev/null || true
printf '%s\n' '--- resume-project references across repository ---'
rg -n -C 5 'resume-project|P\.frontmatter\.worktree_path|Session is in the worktree|Continue without worktree' \
. --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' 2>/dev/null || true
printf '%s\n' '--- relevant documentation ---'
cat -n plugins/docs/SKILL-GUIDELINES.md | sed -n '1,240p'
cat -n CONTRIBUTING.md | sed -n '1,240p'Repository: openshift-eng/edge-tooling
Length of output: 50384
🏁 Script executed:
#!/bin/bash
set -eu
file="plugins/workspace/skills/resume-project/SKILL.md"
printf '%s\n' '--- target file ---'
cat -n "$file"
printf '%s\n' '--- all EnterWorktree mentions ---'
rg -n -C 12 'EnterWorktree' . --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' 2>/dev/null || true
printf '%s\n' '--- relevant tests ---'
rg -n -C 8 'resume-project|EnterWorktree|worktree_path|Continue without worktree' \
--glob '*test*' --glob '*spec*' --glob '*.md' . 2>/dev/null || trueRepository: openshift-eng/edge-tooling
Length of output: 50384
🏁 Script executed:
sed -n '1,150p' plugins/workspace/skills/resume-project/SKILL.mdRepository: openshift-eng/edge-tooling
Length of output: 6025
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
text = Path("plugins/workspace/skills/resume-project/SKILL.md").read_text()
step = text[text.index("## Step 2.5:"):text.index("## Step 3:")]
summary = text[text.index("**If `P.frontmatter.worktree_path` is present"):]
checks = {
"failure branch preserves configured path": (
'"Continue without worktree"' in step
and "proceed without isolation" in step
and "P.frontmatter.worktree_path" not in step[
step.index('"Continue without worktree"'):
]
),
"summary activates from persisted path alone": (
"**If `P.frontmatter.worktree_path` is present" in summary
and "(active)" in summary
),
"summary success message has an explicit success guard": (
"If Step 2.5 entered the worktree successfully" in summary
),
"recreation says to persist a new path": (
"Update `worktree_path`" in step
),
"recreation says to refresh the in-memory project object": (
"refresh" in step.lower() or "re-read" in step.lower()
or "reload" in step.lower()
),
}
for name, result in checks.items():
print(f"{name}: {'PASS' if result else 'FAIL'}")
assert checks["failure branch preserves configured path"]
assert checks["summary activates from persisted path alone"]
assert checks["recreation says to persist a new path"]
assert not checks["recreation says to refresh the in-memory project object"]
PY
printf '%s\n' '--- CONTRIBUTING worktree/documentation guidance ---'
rg -n -C 4 'component names|documented behavior|worktree|side effect|Markdown|test' CONTRIBUTING.mdRepository: openshift-eng/edge-tooling
Length of output: 516
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
text = Path("plugins/workspace/skills/resume-project/SKILL.md").read_text()
step = text[text.index("## Step 2.5:"):text.index("## Step 3:")]
summary = text[text.index("**If `P.frontmatter.worktree_path` is present"):]
# Model the documented state transitions. The failure branch contains no
# instruction that clears or replaces P.frontmatter.worktree_path.
initial = {"worktree_path": "/old/path", "branch": "feature"}
continue_without = dict(initial)
recreated = dict(initial)
assert '"Continue without worktree"' in step
assert "proceed without isolation" in step
assert continue_without["worktree_path"] == "/old/path"
assert "Update `worktree_path`" in step
assert "new path" not in step.lower() or True # avoid treating the prose as a refresh
assert recreated["worktree_path"] == "/old/path"
assert "(active)" in summary
assert summary.find("**If `P.frontmatter.worktree_path` is present") < summary.find("(active)")
assert "If Step 2.5 entered the worktree successfully" in summary
print("continue-without-worktree retains P.frontmatter.worktree_path: PASS")
print("recreate branch does not refresh P.frontmatter.worktree_path: PASS")
print("summary can label any present P.frontmatter.worktree_path active: PASS")
print("summary success sentence is conditional, but active status is not: PASS")
PY
printf '%s\n' '--- CONTRIBUTING.md relevant guidance ---'
rg -n -C 5 'component names|documented behavior|side effects|worktree|Markdown|test' CONTRIBUTING.md || trueRepository: openshift-eng/edge-tooling
Length of output: 4411
Render the actual Step 2.5 worktree state.
If the user selects “Continue without worktree,” do not report P.frontmatter.worktree_path as active. If recreation succeeds, refresh the in-memory path before rendering the summary. Show the active-worktree message only after successful EnterWorktree; otherwise, the summary can direct edits to the wrong checkout.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/resume-project/SKILL.md` around lines 109 - 119,
Update the Step 2.5 summary rendering to use the actual worktree state rather
than blindly using P.frontmatter.worktree_path: omit the active worktree details
when the user continues without one, refresh the in-memory path after successful
recreation, and show the active-worktree/session message only when EnterWorktree
succeeds.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
plugins/workspace/skills/new-project/SKILL.md (1)
108-119: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winUse one absolute
worktree_pathfor creation and frontmatter. Pass$WS/.claude/worktrees/<branch>togit worktree addinstead of the current relative path. Keeprepos: []and omitworktrees:for self-repository projects.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@plugins/workspace/skills/new-project/SKILL.md` around lines 108 - 119, Update the worktree creation flow in Steps 3b–4 to pass the absolute $WS/.claude/worktrees/<branch> path to git worktree add and record that same value in frontmatter as worktree_path. Preserve repos: [] and omit worktrees: for self-repository projects, including the existing no-worktree and failure fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/workspace/skills/new-project/SKILL.md`:
- Around line 112-114: Update the worktree-creation failure path in the Step 4
workflow to report the failure and stop before creating any project files.
Require explicit user confirmation before continuing with edit-in-place, then
omit branch: and worktree_path: from frontmatter and note in the Step 4 summary
that isolation was not possible; define this failure and stop condition
explicitly.
- Around line 104-105: Update the worktree creation instructions around git
worktree add to require an approved branch value stored in a quoted shell
variable, validate it with git check-ref-format --branch "$branch", and use
quoted variable expansions for both the branch argument and worktree path. Also
define clear safety boundaries for this state-changing operation, including
validation before any shell interpolation.
- Around line 94-105: Update the default-branch resolution before the worktree
creation command, using the remote’s actual default branch when origin/HEAD,
main, and master are unavailable. Ensure an unresolved default_branch is handled
through the documented edit-in-place fallback instead of invoking git worktree
add with origin/.
---
Nitpick comments:
In `@plugins/workspace/skills/new-project/SKILL.md`:
- Around line 108-119: Update the worktree creation flow in Steps 3b–4 to pass
the absolute $WS/.claude/worktrees/<branch> path to git worktree add and record
that same value in frontmatter as worktree_path. Preserve repos: [] and omit
worktrees: for self-repository projects, including the existing no-worktree and
failure fallback behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 5d7832e3-4e54-472a-b90e-e06a61f5a4fe
📒 Files selected for processing (3)
plugins/workspace/skills/close-project/SKILL.mdplugins/workspace/skills/new-project/SKILL.mdplugins/workspace/skills/resume-project/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (2)
- plugins/workspace/skills/close-project/SKILL.md
- plugins/workspace/skills/resume-project/SKILL.md
| git -C "$WS" worktree add \ | ||
| .claude/worktrees/<branch> -b <branch> origin/$default_branch |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Quote and validate the branch before shell interpolation.
The <branch> placeholder is inserted directly into the path and the -b argument. If the branch name comes from task text, shell metacharacters can execute as shell syntax before Git processes the value. Store the approved value in a quoted shell variable, validate it with git check-ref-format --branch "$branch", and use quoted values for both the branch and worktree path.
As per path instructions, state-changing skills must define clear safety boundaries.
🧰 Tools
🪛 SkillSpector (2.5.1)
[warning] 213: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
[warning] 380: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
[warning] 435: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/new-project/SKILL.md` around lines 104 - 105, Update
the worktree creation instructions around git worktree add to require an
approved branch value stored in a quoted shell variable, validate it with git
check-ref-format --branch "$branch", and use quoted variable expansions for both
the branch argument and worktree path. Also define clear safety boundaries for
this state-changing operation, including validation before any shell
interpolation.
Source: Path instructions
| 4. If `git worktree add` fails, warn the user and fall back to | ||
| edit-in-place: omit `branch:` and `worktree_path:` from frontmatter, | ||
| and note in the Step 4 summary that isolation was not possible. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Require confirmation before the edit-in-place fallback.
When worktree creation fails, the workflow continues in $WS. This can mix project files with uncommitted or unrelated changes in the main checkout. Report the failure, stop before creating project files, and continue only after the user confirms edit-in-place operation.
As per path instructions, state-changing skills must define explicit failure and stop conditions.
🧰 Tools
🪛 SkillSpector (2.5.1)
[warning] 213: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
[warning] 380: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
[warning] 435: [AS3] Skill Enumeration: Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Remediation: Remove all code or instructions that list or read other skills' files or directories. Skills should operate independently; cross-skill access is a privilege escalation.
(Agent Snooping (AS3))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/new-project/SKILL.md` around lines 112 - 114, Update
the worktree-creation failure path in the Step 4 workflow to report the failure
and stop before creating any project files. Require explicit user confirmation
before continuing with edit-in-place, then omit branch: and worktree_path: from
frontmatter and note in the Step 4 summary that isolation was not possible;
define this failure and stop condition explicitly.
Source: Path instructions
resume-project now starts a 270s ScheduleWakeup loop after loading a project. Each wakeup dispatches a background Agent to update project docs, keeping the prompt cache warm. Includes an idle-loop guard that skips when nothing changed and a post-completion reminder about cache expiry. Manual update-project invocations re-schedule the loop if active. Bumps workspace plugin version to 0.2.1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…p updates Include the resolved project name in ScheduleWakeup prompts so update-project targets the correct project if the user switches contexts mid-session. Also fix no-op manual updates killing the auto-update loop by routing them through Step 5 when a loop is active. Co-Authored-By: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ScheduleWakeup requires /loop dynamic mode which most sessions never activate, making the auto-update feature dead on arrival. Replace with a user-initiated /loop tip that uses CronCreate — jobs only fire while the REPL is idle, which is exactly the behavior needed. - Delete update-project Step 0 (ScheduleWakeup guard + agent dispatch) - Delete update-project Step 5 (re-schedule after manual update) - Replace resume-project Step 6 with user-facing /loop suggestion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Always run the file edits in a background agent so the main session stays clean. The main session identifies what changed (Steps 1-3), builds a self-contained prompt, and hands off to an agent for the mechanical edits. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keeps /loop invocations quiet during idle — no output instead of announcing "nothing to update". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single command to start the 5-minute idle update loop. Checks for an existing loop before scheduling a duplicate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When update-project finds nothing to update and a cron job is active, cancel it and prompt the user to re-enable with /workspace:auto-update. Avoids burning tokens on indefinite empty loops. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e run Using /loop fires update-project immediately before the user has done any work, which triggers the cancel-on-no-op and kills the loop. Calling CronCreate directly lets the first fire happen after 5 minutes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Suggests /clear + /workspace:resume-project to start fresh at lower cost after an idle period with no activity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing project-type filter for self-repo worktree creation: ci-testing and analysis types skip worktree by default. Clarify clean worktree removal trigger in close-project flow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EnterWorktree sandboxes the session, preventing writes to $WS/projects/ which breaks project file updates. Switch all three self-repo worktree skills to use git worktree add/remove directly — same approach as multi-repo workspaces, no sandbox tension. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1b2c05e to
c9904a0
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/workspace/skills/auto-update/SKILL.md`:
- Around line 13-14: The auto-update workflow must use one exact job identity
rather than substring matching. In plugins/workspace/skills/auto-update/SKILL.md
lines 13-14, match the normalized prompt exactly against
/workspace:update-project or persist and reuse the created job ID; in
plugins/workspace/skills/update-project/SKILL.md lines 51-52, delete only that
exact auto-update job for the current project.
- Around line 13-20: Update the CronList and CronCreate instructions in the
auto-update workflow to handle failures before reporting success: stop without
calling CronCreate when CronList fails, and report scheduling failure when
CronCreate fails or returns no valid job ID. Only confirm the recurring schedule
after CronCreate provides a valid job ID.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 374c71c6-e00d-4308-9fa7-e4abe06bdf7d
📒 Files selected for processing (7)
.claude-plugin/marketplace.jsonplugins/workspace/.claude-plugin/plugin.jsonplugins/workspace/skills/auto-update/SKILL.mdplugins/workspace/skills/close-project/SKILL.mdplugins/workspace/skills/new-project/SKILL.mdplugins/workspace/skills/resume-project/SKILL.mdplugins/workspace/skills/update-project/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (3)
- plugins/workspace/skills/new-project/SKILL.md
- plugins/workspace/skills/resume-project/SKILL.md
- plugins/workspace/skills/close-project/SKILL.md
| Run CronList. If any job's prompt contains `update-project`, tell the | ||
| user it's already running (show the job ID) and stop. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Use one exact identity for the auto-update job.
Both workflows match cron prompts by substring. This can mistake another job for the auto-update job, block scheduling, or delete the wrong job.
plugins/workspace/skills/auto-update/SKILL.md#L13-L14: match the normalized prompt exactly against/workspace:update-project, or persist the created job ID.plugins/workspace/skills/update-project/SKILL.md#L51-L52: delete only the exact auto-update job for the current project.
📍 Affects 2 files
plugins/workspace/skills/auto-update/SKILL.md#L13-L14(this comment)plugins/workspace/skills/update-project/SKILL.md#L51-L52
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/auto-update/SKILL.md` around lines 13 - 14, The
auto-update workflow must use one exact job identity rather than substring
matching. In plugins/workspace/skills/auto-update/SKILL.md lines 13-14, match
the normalized prompt exactly against /workspace:update-project or persist and
reuse the created job ID; in plugins/workspace/skills/update-project/SKILL.md
lines 51-52, delete only that exact auto-update job for the current project.
| Run CronList. If any job's prompt contains `update-project`, tell the | ||
| user it's already running (show the job ID) and stop. | ||
|
|
||
| ## Step 2: Schedule | ||
|
|
||
| Call CronCreate directly with cron `*/5 * * * *`, prompt | ||
| `/workspace:update-project`, recurring `true`. Confirm: scheduled every | ||
| 5 minutes, auto-expires after 7 days, cancel with CronDelete (show the |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- candidate skill ---'
cat -n plugins/workspace/skills/auto-update/SKILL.md
printf '%s\n' '--- skill guidelines ---'
cat -n plugins/docs/SKILL-GUIDELINES.md
printf '%s\n' '--- contributing files ---'
find . -maxdepth 2 -iname 'CONTRIBUTING.md' -print
printf '%s\n' '--- relevant references ---'
rg -n -C 3 'allowed-tools|CronList|CronCreate|CronDelete|auto-update|update-project' \
plugins/workspace/skills plugins/docs CONTRIBUTING.md 2>/dev/null || true
printf '%s\n' '--- change summary ---'
git diff --stat -- plugins/workspace/skills/auto-update/SKILL.mdRepository: openshift-eng/edge-tooling
Length of output: 1938
🏁 Script executed:
#!/bin/bash
set -u
for url in \
https://raw.githubusercontent.com/openshift-eng/edge-tooling/main/plugins/workspace/skills/auto-update/SKILL.md \
https://raw.githubusercontent.com/openshift-eng/edge-tooling/master/plugins/workspace/skills/auto-update/SKILL.md \
https://raw.githubusercontent.com/openshift-eng/edge-tooling/main/plugins/docs/SKILL-GUIDELINES.md \
https://raw.githubusercontent.com/openshift-eng/edge-tooling/main/CONTRIBUTING.md
do
echo "--- $url ---"
curl -L --fail --silent --show-error --max-time 20 "$url" || true
echo
doneRepository: openshift-eng/edge-tooling
Length of output: 1938
🌐 Web query:
openshift-eng edge-tooling plugins/workspace/skills/auto-update/SKILL.md
💡 Result:
The path openshift-eng/edge-tooling/plugins/workspace/skills/auto-update/SKILL.md refers to a specific skill definition file within the edge-tooling repository's plugin marketplace [1][2]. This repository, maintained by the OpenShift Edge engineering team, provides tools for OpenShift edge deployments and workflows, including a Claude Code plugin marketplace that allows engineers to utilize AI-assisted skills [3][4]. SKILL.md files in this repository function as self-documenting specifications for individual skills [5][6]. They follow a standard structure that includes YAML frontmatter for configuration and Markdown documentation for usage, implementation, and edge cases [5][6]. Key components of these files include: 1. YAML Frontmatter: Defines essential metadata such as the skill name, a description used by the AI to determine invocation, whether the skill is user-invocable, allowed tools (e.g., Bash, Agent, Read), and argument hints [5][6]. 2. Documentation: Explains the purpose of the skill, the steps it performs (often involving sub-agents or orchestrator logic), and provides usage examples [7][8]. 3. Quality Guidelines: The repository enforces strict standards for these files, checked by scripts like plugins/scripts/lint-skills.py and PR review processes (such as CodeRabbit) to ensure consistency in descriptions, tool restrictions, and documentation of edge cases [6]. While a specific file at plugins/workspace/skills/auto-update/SKILL.md may be a custom or organizational skill within the broader ecosystem, it conforms to the standard plugin architecture provided by the edge-tooling framework [1][2]. You can find templates for creating new skills in the plugins/.templates/ directory of the repository [5][9].
Citations:
- 1: https://github.com/openshift-eng/edge-tooling/blob/main/plugins/README.md
- 2: https://github.com/openshift-eng/edge-tooling/tree/main/plugins
- 3: https://github.com/openshift-eng/edge-tooling
- 4: https://github.com/openshift-eng/edge-tooling/blob/main/README.md
- 5: https://github.com/openshift-eng/edge-tooling/blob/main/plugins/.templates/SKILL.md.template
- 6: https://github.com/openshift-eng/edge-tooling/blob/main/plugins/docs/SKILL-GUIDELINES.md
- 7: https://github.com/openshift-eng/edge-tooling/blob/main/plugins/two-node/skills/bug-reproducer/SKILL.md
- 8: https://github.com/openshift-eng/edge-tooling/blob/main/plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md
- 9: 6c22af8
🌐 Web query:
site:github.com/openshift-eng/edge-tooling/blob/main/plugins/workspace/skills/auto-update/SKILL.md "CronList" "CronCreate"
💡 Result:
No indexed result was found for that exact edge-tooling file and phrase. The closest matches describe CronCreate as creating scheduled tasks and CronList as listing them. [1] (github.com)
Citations:
🌐 Web query:
site:github.com/openshift-eng/edge-tooling/blob/main/plugins/docs/SKILL-GUIDELINES.md "failure" "allowed-tools"
💡 Result:
The term allowed-tools refers to a configuration property, typically found in the frontmatter of plugin or skill definitions within software development frameworks (such as the OpenShift edge-tooling ecosystem) [1]. Its purpose is to implement the principle of least privilege by explicitly defining the set of tools a specific skill or plugin is permitted to access [1]. When a developer specifies allowed-tools, they create a security boundary that limits the skills execution environment [1]. Key aspects of this configuration include: - Blast Radius Reduction: By restricting a skill to only the tools it requires to perform its function, the potential impact of a failure or a malicious action is contained [1]. - Mandatory Specification: For user-invocable skills, specifying allowed-tools is often a requirement to ensure transparency for reviewers [1]. Omitting the field typically grants the skill access to all available tools, which is generally discouraged except for trivial, low-risk operations [1]. - Security Review: Reviewers use this field to verify that a skill does not possess excessive permissions [1]. For instance, any skill that invokes Bash is required to declare it explicitly in this list due to the higher risk associated with executing scripts [1]. If a failure occurs in the context of allowed-tools, it usually indicates a violation of these permissions—such as a skill attempting to use a tool that was not declared in its metadata—or a misconfiguration where the necessary tools for a function were omitted, causing the skill to fail at runtime [1].
Citations:
🌐 Web query:
site:github.com/openshift-eng/edge-tooling/blob/main/CONTRIBUTING.md "medium"
💡 Result:
No exact match was found for site:github.com/openshift-eng/edge-tooling/blob/main/CONTRIBUTING.md "medium".
Handle cron failures before reporting success. If CronList fails, stop and do not call CronCreate. If CronCreate fails or returns no valid job ID, report scheduling failure. Confirm the schedule only after receiving a valid job ID.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/workspace/skills/auto-update/SKILL.md` around lines 13 - 20, Update
the CronList and CronCreate instructions in the auto-update workflow to handle
failures before reporting success: stop without calling CronCreate when CronList
fails, and report scheduling failure when CronCreate fails or returns no valid
job ID. Only confirm the recurring schedule after CronCreate provides a valid
job ID.
Sources: Path instructions, Learnings
Summary
EnterWorktreeby default when creating projects in single-repo (self) workspaces, giving branch isolation without polluting the main checkoutEnterWorktree(path)when resuming a self-repo project, with missing-worktree recoveryExitWorktreeorgit worktree removefallback, with dirty-state checks matching the multi-repo flowPreviously self-repo workspaces used "edit-in-place" (no isolation). Multi-repo behavior (
git worktree addunder.worktrees/) is unchanged.Details
worktree_path:(self-repo) is mutually exclusive withworktrees:(multi-repo)ci-testingandanalysisproject types skip worktree creation (they don't modify code)EnterWorktreefailure falls back to edit-in-place gracefullyTest plan
/workspace:new-projecton a self-repo workspace → verify worktree is created viaEnterWorktree/workspace:resume-projecton the project → verify auto-entry into the worktree/workspace:close-project→ verify worktree cleanup (ExitWorktree or git fallback)ci-testingproject → verify no worktree is created🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes