Skip to content

feat(skills): vendor the outsource skill (explore/review/write)#4

Open
OriNachum wants to merge 1 commit into
mainfrom
feat/vendor-outsource-skill
Open

feat(skills): vendor the outsource skill (explore/review/write)#4
OriNachum wants to merge 1 commit into
mainfrom
feat/vendor-outsource-skill

Conversation

@OriNachum
Copy link
Copy Markdown
Contributor

Summary

  • Vendors the canonical outsource skill (explore / review / write) from guildmaster into lecodeur's .claude/skills/outsource/
  • Cite-don't-import: lecodeur owns its copy and can adapt it independently
  • Fixed 8 markdownlint violations in the prompt files (MD041 missing first-line headings, MD032 blank lines around lists) to conform to lecodeur's .markdownlint-cli2.yaml
  • Patch version bump 0.1.0 → 0.1.1 per the version-check CI rule

What the outsource skill does

Hands a scoped repo task to convertible — a different engine/mind — for a diverse second opinion:

  • outsource explore <topic> — fresh-eyes read-only investigation
  • outsource review [focus] — independent diff review versus branch base
  • outsource write <task> — implement the smallest correct change

The portable shell wrapper resolves the convertible CLI from PATH.

Test plan

  • CI passes (lint, tests, version-check)

  • .claude/skills/outsource/SKILL.md frontmatter name: outsource is present

  • markdownlint-cli2 ".claude/skills/outsource/**/*.md" reports 0 errors

  • Companion align-issue filed on this repo

  • lecodeur (Claude)

Cite-don't-import copy of the canonical outsource skill from guildmaster:
hand a scoped repo task to convertible (a different engine/mind) for a
diverse second opinion — outsource review|explore|write. Portable wrapper;
resolves the convertible CLI from PATH. Patch bump per version-check rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Vendor outsource skill with explore/review/write verbs

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Vendors canonical outsource skill from guildmaster into .claude/skills/outsource/
• Implements three verbs: explore (read-only investigation), review (independent diff opinion),
  write (implementation delegation)
• Portable shell wrapper resolves convertible CLI from PATH with fallback to local dev mode
• Fixes 8 markdownlint violations (MD041, MD032) and bumps version 0.1.0 → 0.1.1
Diagram
flowchart LR
  User["User invokes outsource.sh"] -->|explore| ReadOnly1["Throwaway worktree at HEAD"]
  User -->|review| ReadOnly2["Throwaway worktree at HEAD"]
  User -->|write| InPlace["In-place drive branch"]
  ReadOnly1 -->|render_prompt| Explore["explore.md template"]
  ReadOnly2 -->|render_prompt| Review["review.md template"]
  InPlace -->|render_prompt| Write["write.md template"]
  Explore -->|convertible drive| Result1["TaskResult JSON"]
  Review -->|convertible drive| Result2["TaskResult JSON"]
  Write -->|convertible drive| Result3["TaskResult JSON"]
  Result1 -->|print_result| Output1["Summary + findings"]
  Result2 -->|print_result| Output2["Summary + review"]
  Result3 -->|print_result| Output3["Summary + branch/PR"]

Loading

Grey Divider

File Changes

1. .claude/skills/outsource/scripts/outsource.sh ✨ Enhancement +259/-0

Portable outsource skill wrapper script

• New 259-line bash script implementing the outsource skill entry point
• Resolves convertible CLI portably (installed or local dev via uv run)
• Parses three verbs (explore/review/write) with comprehensive flag parsing (--repo, --base,
 --engine, --model, --base-url, --max-steps, --timeout, --allow-dirty, --pr)
• Implements run_readonly() for explore/review using throwaway git worktrees with automatic
 cleanup
• Implements run_write() for in-place drive branch creation with dirty-tree guard
• Renders prompt templates with variable substitution and parses JSON results from convertible

.claude/skills/outsource/scripts/outsource.sh


2. .claude/skills/outsource/SKILL.md 📝 Documentation +104/-0

Skill documentation with verbs and rules

• New 104-line skill documentation with YAML frontmatter (name: outsource, type: command)
• Describes three verbs and their use cases: review (second opinion on diff), explore (fresh read),
 write (delegation)
• Documents all CLI options and environment variable overrides
• Specifies hard rules: read-only enforcement, dirty-tree guard, output as second opinion not
 authority
• Lists honest limits: worktree isolation + prompt constraint (not sandbox), committed-only review,
 single-model default
• Includes provenance note about cite-don't-import policy

.claude/skills/outsource/SKILL.md


3. .claude/skills/outsource/prompts/explore.md 📝 Documentation +24/-0

Explore verb prompt template

• New 24-line prompt template for read-only investigation verb
• Instructs model to investigate topic and report findings with file:line citations
• Enforces read-only constraint: read_file, list_dir, read-only run_command only
• Emphasizes concrete findings over tidy summaries; surfaces surprises and risks
• Includes step budget awareness and finish call structure

.claude/skills/outsource/prompts/explore.md


View more (4)
4. .claude/skills/outsource/prompts/review.md 📝 Documentation +31/-0

Review verb prompt template

• New 31-line prompt template for independent diff review verb
• Instructs model to review committed diff ($BASE...HEAD) with candid second opinion
• Enforces read-only constraint and step budget awareness
• Structures output: correctness risks, design concerns, actionable suggestions (ranked)
• Emphasizes terse, prioritized findings over padding

.claude/skills/outsource/prompts/review.md


5. .claude/skills/outsource/prompts/write.md 📝 Documentation +16/-0

Write verb prompt template

• New 16-line prompt template for implementation delegation verb
• Instructs model to implement smallest correct change following repo patterns
• Allows full read/write/command access (unlike explore/review)
• Emphasizes scope constraint and existing code style adherence
• Requires finish call with summary of changes

.claude/skills/outsource/prompts/write.md


6. CHANGELOG.md 📝 Documentation +8/-0

Add changelog entry for version 0.1.1

• Added new [0.1.1] section with 2026-05-31 date
• Includes placeholder subsections: Added, Changed, Fixed (all empty)
• Maintains existing [0.1.0] section below

CHANGELOG.md


7. pyproject.toml ⚙️ Configuration changes +1/-1

Patch version bump to 0.1.1

• Bumped version from "0.1.0" to "0.1.1" per version-check CI rule

pyproject.toml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 31, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1)

Context used
✅ Compliance rules (platform): 28 rules

Grey Divider


Action required

1. outsource.sh depends on external convertible 📘 Rule violation ⚙ Maintainability
Description
The new skill entrypoint relies on an external convertible CLI from PATH (or an external
convertible checkout via uv run), rather than a vendored in-repo dependency. This violates the
requirement that skill scripts not depend on resources outside the repository, reducing portability
and increasing supply-chain risk.
Code

.claude/skills/outsource/scripts/outsource.sh[R22-48]

Evidence
Rule 731646 requires skill scripts to avoid depending on binaries/resources outside the repository.
The added resolve_convertible() logic explicitly runs convertible from PATH and falls back to
uv run convertible from an external convertible checkout, which is an out-of-repo dependency.

Rule 731646: Skill scripts must not depend on external paths outside the repository
.claude/skills/outsource/scripts/outsource.sh[22-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`.claude/skills/outsource/scripts/outsource.sh` resolves and executes `convertible` from the system (`PATH`) and even supports running from an external `convertible` checkout. Compliance requires skill scripts to avoid dependencies on paths/resources outside this repository.

## Issue Context
The script currently:
- Executes `convertible` if found on `PATH`.
- Falls back to `uv run convertible` when it detects it is inside a separate `convertible` repository checkout.

This makes the skill non-self-contained and dependent on external installations/repos.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[22-48]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Base value command injection 🐞 Bug ⛨ Security
Description
--base is substituted into the review prompt’s suggested git diff $BASE...HEAD commands without
quoting or validation, so a crafted base containing shell metacharacters can turn a “read-only” step
into arbitrary command execution by the outsourced model.
Code

.claude/skills/outsource/prompts/review.md[R10-15]

Evidence
The prompt embeds $BASE directly into shell commands, and the wrapper accepts arbitrary --base
values and performs raw string replacement into the prompt, so unsafe base strings will be rendered
verbatim into the commands the outsourced agent is told to run.

.claude/skills/outsource/prompts/review.md[10-15]
.claude/skills/outsource/scripts/outsource.sh[115-165]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `review` prompt instructs the outsourced agent to run `git diff $BASE...HEAD`, and `outsource.sh` allows arbitrary `--base` values. If `--base` contains shell metacharacters (e.g., `main; <cmd>`), the prompt becomes an injection vector when the outsourced agent executes the command.

## Issue Context
This is not executed by `outsource.sh` directly, but it is explicitly executed by the outsourced agent via its command-running tool, so prompt text must be treated as a command construction surface.

## Fix
Do both:
1) **Validate** `--base` in `outsource.sh` to a safe git-revision charset (reject whitespace and shell metacharacters).
2) **Quote** the revision range in the prompt template to avoid accidental word-splitting/injection.

Examples:
- In `outsource.sh`, after parsing flags:
 - `[[ "$BASE" =~ ^[A-Za-z0-9._/-]+$ ]] || { echo "error: unsafe --base value" >&2; exit 2; }`
- In `review.md`, change to something like:
 - `git diff "${BASE}...HEAD" --stat`
 - `git diff "${BASE}...HEAD"`
 (or `git diff --stat "$BASE"...HEAD` if you prefer two args)

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[115-165]
- .claude/skills/outsource/prompts/review.md[10-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Cleanup may delete user branch 🐞 Bug ☼ Reliability
Description
The EXIT cleanup deletes any branch named by the drive if it matches convertible/*, even if that
branch pre-existed, which can destroy a user’s legitimate local branch.
Code

.claude/skills/outsource/scripts/outsource.sh[R206-215]

Evidence
The cleanup logic unconditionally branch -D’s any convertible/* branch returned by the drive,
without checking whether it existed before the run.

.claude/skills/outsource/scripts/outsource.sh[206-216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`_cleanup_worktree` deletes `$_DRIVE_BRANCH` whenever it matches `convertible/*`, but it does not verify the branch was created by this run. If a user already has a branch with that name, it can be deleted.

## Issue Context
This cleanup runs for read-only verbs. The script already treats the branch name as potentially unsafe (pattern-check), but the pattern is broad enough to overlap with real user branches.

## Fix
Track whether the branch existed before running the drive, and only delete if it did **not** exist.

One approach:
- Before calling `convertible drive`, snapshot existing `convertible/*` heads into a global (or temp file).
- After parsing `branch` from JSON, in cleanup:
 - delete only if it matches `convertible/*` **and** was not present in the snapshot.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[200-216]
- .claude/skills/outsource/scripts/outsource.sh[218-235]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

4. Write repo not validated 🐞 Bug ☼ Reliability
Description
run_write doesn’t validate that --repo is a git repository (unlike run_readonly), so a non-git
--repo won’t fail fast with the wrapper’s clear message and instead defers error handling to
downstream commands.
Code

.claude/skills/outsource/scripts/outsource.sh[R238-252]

Evidence
The read-only path validates --repo as a git repo before proceeding, but the write path jumps
straight to git status/convertible drive without that validation.

.claude/skills/outsource/scripts/outsource.sh[218-252]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`run_readonly` explicitly checks `git rev-parse --is-inside-work-tree` and emits a clear `--repo is not a git repository` error, but `run_write` does not. This makes failures on non-git repos less consistent and typically surfaces later via `convertible`.

## Issue Context
Consistency matters here because `--repo` is a primary user input.

## Fix
At the start of `run_write`, add the same `git -C "$REPO" rev-parse --is-inside-work-tree` check and error message used by `run_readonly`.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[218-222]
- .claude/skills/outsource/scripts/outsource.sh[237-252]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@sonarqubecloud
Copy link
Copy Markdown

Comment on lines +22 to +48
# ── resolve the convertible CLI (installed, then local-dev fallback) ─────────
CONVERTIBLE=()
resolve_convertible() {
if command -v convertible >/dev/null 2>&1; then
CONVERTIBLE=(convertible) # installed tool — the normal case
return 0
fi
# Local-dev fallback: inside the convertible checkout, run via uv.
local dir="$PWD"
while [[ -n "$dir" ]] && [[ "$dir" != "/" ]]; do
if [[ -f "$dir/pyproject.toml" ]] \
&& grep -q '^name = "convertible-cli"' "$dir/pyproject.toml" 2>/dev/null; then
if command -v uv >/dev/null 2>&1; then
CONVERTIBLE=(uv run convertible)
return 0
fi
break
fi
dir=$(dirname "$dir")
done
cat >&2 <<'EOF'
error: convertible CLI not found.
hint: install it with `uv tool install convertible-cli` (or `pipx install convertible-cli`),
or run from inside the convertible checkout with `uv` available.
https://github.com/agentculture/convertible
EOF
return 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. outsource.sh depends on external convertible 📘 Rule violation ⚙ Maintainability

The new skill entrypoint relies on an external convertible CLI from PATH (or an external
convertible checkout via uv run), rather than a vendored in-repo dependency. This violates the
requirement that skill scripts not depend on resources outside the repository, reducing portability
and increasing supply-chain risk.
Agent Prompt
## Issue description
`.claude/skills/outsource/scripts/outsource.sh` resolves and executes `convertible` from the system (`PATH`) and even supports running from an external `convertible` checkout. Compliance requires skill scripts to avoid dependencies on paths/resources outside this repository.

## Issue Context
The script currently:
- Executes `convertible` if found on `PATH`.
- Falls back to `uv run convertible` when it detects it is inside a separate `convertible` repository checkout.

This makes the skill non-self-contained and dependent on external installations/repos.

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[22-48]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +10 to +15
The change under review is the committed diff on this branch versus its base
(`$BASE`). Start by running, read-only:

git diff $BASE...HEAD --stat
git diff $BASE...HEAD

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Base value command injection 🐞 Bug ⛨ Security

--base is substituted into the review prompt’s suggested git diff $BASE...HEAD commands without
quoting or validation, so a crafted base containing shell metacharacters can turn a “read-only” step
into arbitrary command execution by the outsourced model.
Agent Prompt
## Issue description
The `review` prompt instructs the outsourced agent to run `git diff $BASE...HEAD`, and `outsource.sh` allows arbitrary `--base` values. If `--base` contains shell metacharacters (e.g., `main; <cmd>`), the prompt becomes an injection vector when the outsourced agent executes the command.

## Issue Context
This is not executed by `outsource.sh` directly, but it is explicitly executed by the outsourced agent via its command-running tool, so prompt text must be treated as a command construction surface.

## Fix
Do both:
1) **Validate** `--base` in `outsource.sh` to a safe git-revision charset (reject whitespace and shell metacharacters).
2) **Quote** the revision range in the prompt template to avoid accidental word-splitting/injection.

Examples:
- In `outsource.sh`, after parsing flags:
  - `[[ "$BASE" =~ ^[A-Za-z0-9._/-]+$ ]] || { echo "error: unsafe --base value" >&2; exit 2; }`
- In `review.md`, change to something like:
  - `git diff "${BASE}...HEAD" --stat`
  - `git diff "${BASE}...HEAD"`
  (or `git diff --stat "$BASE"...HEAD` if you prefer two args)

## Fix Focus Areas
- .claude/skills/outsource/scripts/outsource.sh[115-165]
- .claude/skills/outsource/prompts/review.md[10-15]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

1 participant